Skip to content

CVE-2024-23334: Verified Repro With Script Download

CVE-2024-23334: aiohttp static file directory traversal via follow symlinks

CVE-2024-23334 is verified against aiohttp · pip. Affected versions: >= 1.0.5, < 3.9.2. Fixed in 3.9.2. Vulnerability class: Path Traversal. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00199.

REPRO-2026-00199 aiohttp · pip Path Traversal Jul 2, 2026 CVE entry ↗ .txt
Severity
HIGH
CVSS
8.2
Confidence
HIGH
Reproduced in
11m 4s
Tool calls
69
Spend
$1.88
01 · Overview

What Is CVE-2024-23334?

CVE-2024-23334 is a high-severity path traversal vulnerability (CWE-22, CVSS 8.2) in aiohttp's static file handler that allows attackers to read arbitrary files outside the configured static root. Pruva reproduced it (reproduction REPRO-2026-00199).

02 · Severity & CVSS

CVE-2024-23334 Severity & CVSS Score

CVE-2024-23334 is rated high severity, with a CVSS base score of 8.2 out of 10.

HIGH threat level
8.2 / 10 CVSS base
03 · Affected Versions

Affected aiohttp Versions

aiohttp · pip versions >= 1.0.5, < 3.9.2 are affected.

How to Reproduce CVE-2024-23334

$ pruva-verify REPRO-2026-00199
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00199/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2024-23334

Information disclosure — reproduced
  • reached the target end-to-end
  • on the real production code path
  • high confidence
  • the upstream fix blocks the same trigger
Trigger

URL path with ../ traversal sequences sent via HTTP GET

Attack chain
  1. HTTP GET /static/../poc-aiohttp-test.txt to aiohttp web.static() route with follow_symlinks=True
Runnable proof: reproduction_steps.sh
Captured evidence: fixed 1vulnerable 1fixed 2vulnerable 2
How the agent worked 185 events · 69 tool calls · 11 min
11 minDuration
69Tool calls
52Reasoning steps
185Events
11Dead-ends
Agent activity over 11 min
Support
10
Hypothesis
2
Repro
138
Judge
32
0:0011:04

Root Cause and Exploit Chain for CVE-2024-23334

Vulnerability Summary

CVE: CVE-2024-23334 Package: aiohttp (pip) Vulnerable versions: >= 1.0.5, < 3.9.2 Patched version: 3.9.2 CWE: CWE-22 (Path Traversal) Severity: High

Description

aiohttp's web.static() handler allows directory traversal when follow_symlinks=True is configured. Path traversal sequences (../) in the URL can escape the configured static root directory and read arbitrary files on the server filesystem, even when no symlinks are present.

Root Cause

The vulnerability is in StaticResource._handle() in aiohttp/web_urldispatcher.py.

Vulnerable code (aiohttp 3.9.1)
async def _handle(self, request: Request) -> StreamResponse:
    rel_url = request.match_info["filename"]
    try:
        filename = Path(rel_url)
        if filename.anchor:
            raise HTTPForbidden()
        filepath = self._directory.joinpath(filename).resolve()
        if not self._follow_symlinks:
            filepath.relative_to(self._directory)
    except (ValueError, FileNotFoundError) as error:
        raise HTTPNotFound() from error

When follow_symlinks=True:

  1. filename = Path(rel_url) creates a Path from the URL filename (e.g., ../poc-aiohttp-test.txt)
  2. filename.anchor only checks for absolute paths; ../... is relative, so it passes
  3. filepath = self._directory.joinpath(filename).resolve() joins the directory with the traversal path and resolves .. sequences to the real filesystem path outside the static root
  4. if not self._follow_symlinks: is False when follow_symlinks=True, so the relative_to(self._directory) validation is skipped entirely
  5. The code proceeds to serve the file at the escaped path
Fixed code (aiohttp 3.9.2)
async def _handle(self, request: Request) -> StreamResponse:
    rel_url = request.match_info["filename"]
    try:
        filename = Path(rel_url)
        if filename.anchor:
            raise HTTPForbidden()
        unresolved_path = self._directory.joinpath(filename)
        if self._follow_symlinks:
            normalized_path = Path(os.path.normpath(unresolved_path))
            normalized_path.relative_to(self._directory)
            filepath = normalized_path.resolve()
        else:
            filepath = unresolved_path.resolve()
            filepath.relative_to(self._directory)
    except (ValueError, FileNotFoundError) as error:
        raise HTTPNotFound() from error

The fix adds a relative_to(self._directory) check even when follow_symlinks=True. It normalizes the path with os.path.normpath() first (resolving .. sequences without following symlinks), then validates it stays within the directory before resolving symlinks. If the path escapes the directory, relative_to() raises ValueError which is caught and results in HTTPNotFound (404).

Reproduction Evidence

Environment
  • Python 3.11 (via uv standalone build)
  • aiohttp 3.9.1 (vulnerable) and 3.9.2 (fixed)
  • Server: web.static("/static", "static/", follow_symlinks=True)
  • Probe file: poc-aiohttp-test.txt placed as a sibling of the static root
Results

Vulnerable aiohttp 3.9.1:

  • HTTP GET /static/../poc-aiohttp-test.txt with curl --path-as-is or raw-socket HTTP -> HTTP 200, body contains probe content
  • Traversal variants include raw ../, %2f, %2e, %2F, and a raw HTTP socket request
  • Leak method: raw_path_as_is
  • Both vulnerable attempts leaked

Fixed aiohttp 3.9.2:

  • Same requests -> HTTP 404 Not Found for all variants
  • Both fixed attempts blocked

Arbitrary file read via HTTP path traversal. An attacker can read any file accessible to the aiohttp server process by sending crafted HTTP requests with ../ sequences to a static route configured with follow_symlinks=True.

Surface and Impact Classification

The ticket metadata claims claimed_surface=converter_document and expected_impact=code_execution. However:

  • Actual surface: api_remote -- the vulnerability is exploited via HTTP requests to a running aiohttp web server, not a document converter.
  • Actual impact: info_leak -- the vulnerability allows arbitrary file read (path traversal), not code execution.

The vulnerability is real and confirmed at the api_remote surface, but the claim metadata misclassifies both the surface and the impact.

References

CVE-2024-23334 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:001:48
0:00
session startedaccounts/fireworks/routers/glm-5p2-fast · CVE-2024-23334 · REPRO-20
0:03
0:04
0:06
web search
0:13
0:13
extract_facts
no facts extracted
0:14
0:14
0:14
supportrepro
0:24
0:26
0:26
0:26
0:27
0:27
0:27
0:27
0:39
0:39
0:39
0:41
0:41
0:42
$python3 --version && pip3 --version && which curl && which jq
0.7s
Python 3.14.4
pip 25.1.1 from /usr/lib/python3/dist-packages/pip (python 3.14)
/usr/bin/curl
/usr/bin/jq
0:46
0:47
$ls /usr/bin/python* 2>/dev/null; ls /usr/local/bin/python* 2>/dev/null; which python3.11 python3.10 python3.12 python3.13 2>/dev/null; echo "---pyenv---"; which pyenv 2>/dev/null; echo "---deadsnakes---"; ls /usr/bin/python3.1* 2>/dev/null
/usr/bin/python
/usr/bin/python3
/usr/bin/python3-config
/usr/bin/python3.14
/usr/bin/python3.14-config
---pyenv---
---deadsnakes---
/usr/bin/python3.14
1:01
$cd /tmp && python3 -m venv testvenv 2>&1 | head -5 && /tmp/testvenv/bin/pip install --dry-run aiohttp==3.9.1 2>&1 | tail -20
14.4s
{"cwd":"/data/pruva/runs/2fe67f5c-a344-41e3-887b-3d210ff0947f","duration_ms":14364,"exit_code":0,"stderr":"","stdout":"Collecting multidict<7.0,>=4.5 (from aiohttp==3.9.1)\n  Downloading multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.metadata (5.3 kB)\nCollecting yarl<2.0,>=1.0 (from aiohttp==3.9.1)\n  Downloading yarl-1.24.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.metadata (94 kB)\nCollecting frozenlist>=1.1.1 (from aiohttp==3.9.1)\n  Downloading frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl.metadata (20 kB)\nCollecting aiosignal>=1.1.2 (from aiohttp==3.9.1)\n  Downloading aiosignal-1.4.0-py3-none-any.whl.metadata (3.7 kB)\nCollecting idna>=2.0 (from yarl<2.0,>=1.0->aiohttp==3.9.1)\n  Downloading idna-3.18-py3-none-any.whl.metadata (6.1 kB)\nCollecting propcache>=0.2.1 (from yarl<2.0,>=1.0->aiohttp==3.9.1)\n  Downloading propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.metadata (16 kB)\nDownloading multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (24… [truncated]
1:03
1:03
#!/bin/bash
set -euo pipefail
cd /tmp
rm -rf testvenv
python3 -m venv testvenv
/tmp/testvenv/bin/pip install aiohttp==3.9.1 2>&1 | tail -30
echo "EXIT: $?"
/tmp/testvenv/bin/python -c "import aiohttp; print('aiohttp', aiohttp.__version__)"
1:03
error

Unknown error

1:48

Artifacts and Evidence for CVE-2024-23334

Scripts, logs, diffs, and output captured during the reproduction.

bundle/repro/runtime_manifest.json4.0 KB
bundle/repro/validation_verdict.json0.7 KB
bundle/ticket.json3.5 KB
bundle/ticket.md3.0 KB
bundle/logs/uv_venv_3.9.1.log0.2 KB
bundle/logs/uv_pip_3.9.2.log0.6 KB
bundle/logs/fixed_1.log1.7 KB
bundle/logs/vulnerable_1.log1.5 KB
bundle/logs/pip_install_3.9.2.log0.0 KB
bundle/logs/fixed_2.log1.7 KB
bundle/logs/uv_install.log0.0 KB
bundle/logs/reproduction_steps.log14.2 KB
bundle/logs/uv_venv_3.9.2.log0.2 KB
bundle/logs/pip_install_3.9.1.log0.0 KB
bundle/logs/uv_pip_3.9.1.log0.6 KB
bundle/logs/vulnerable_2.log1.5 KB
bundle/repro/reproduction_steps.sh31.2 KB
bundle/repro/rca_report.md4.6 KB
bundle/repro/artifacts/http/fixed_1/health_resp.txt0.0 KB
bundle/repro/artifacts/http/fixed_1/leak_method.txt0.0 KB
bundle/repro/artifacts/http/fixed_1/m1_headers.txt0.2 KB
bundle/repro/artifacts/http/fixed_1/m1_resp.txt0.0 KB
bundle/repro/artifacts/http/fixed_1/m2_headers.txt0.2 KB
bundle/repro/artifacts/http/fixed_1/m2_resp.txt0.0 KB
bundle/repro/artifacts/http/fixed_1/m3_headers.txt0.2 KB
bundle/repro/artifacts/http/fixed_1/m3_resp.txt0.0 KB
bundle/repro/artifacts/http/fixed_1/m4_headers.txt0.2 KB
bundle/repro/artifacts/http/fixed_1/m4_resp.txt0.0 KB
bundle/repro/artifacts/http/fixed_1/result.txt0.0 KB
bundle/repro/artifacts/http/fixed_1/version.txt0.0 KB
bundle/repro/artifacts/http/fixed_2/health_resp.txt0.0 KB
bundle/repro/artifacts/http/fixed_2/leak_method.txt0.0 KB
bundle/repro/artifacts/http/fixed_2/m1_headers.txt0.2 KB
bundle/repro/artifacts/http/fixed_2/m1_resp.txt0.0 KB
bundle/repro/artifacts/http/fixed_2/m2_headers.txt0.2 KB
bundle/repro/artifacts/http/fixed_2/m2_resp.txt0.0 KB
bundle/repro/artifacts/http/fixed_2/m3_headers.txt0.2 KB
bundle/repro/artifacts/http/fixed_2/m3_resp.txt0.0 KB
bundle/repro/artifacts/http/fixed_2/m4_headers.txt0.2 KB
bundle/repro/artifacts/http/fixed_2/m4_resp.txt0.0 KB
bundle/repro/artifacts/http/fixed_2/result.txt0.0 KB
bundle/repro/artifacts/http/fixed_2/version.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_1/health_resp.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_1/leak_method.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_1/m1_headers.txt0.2 KB
bundle/repro/artifacts/http/vulnerable_1/m1_resp.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_1/m2_headers.txt0.2 KB
bundle/repro/artifacts/http/vulnerable_1/m2_resp.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_1/m3_headers.txt0.2 KB
bundle/repro/artifacts/http/vulnerable_1/m3_resp.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_1/m4_headers.txt0.2 KB
bundle/repro/artifacts/http/vulnerable_1/m4_resp.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_1/proof_leak.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_1/proof_leak_headers.txt0.2 KB
bundle/repro/artifacts/http/vulnerable_1/result.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_1/version.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_2/health_resp.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_2/leak_method.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_2/m1_headers.txt0.2 KB
bundle/repro/artifacts/http/vulnerable_2/m1_resp.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_2/m2_headers.txt0.2 KB
bundle/repro/artifacts/http/vulnerable_2/m2_resp.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_2/m3_headers.txt0.2 KB
bundle/repro/artifacts/http/vulnerable_2/m3_resp.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_2/m4_headers.txt0.2 KB
bundle/repro/artifacts/http/vulnerable_2/m4_resp.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_2/proof_leak.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_2/proof_leak_headers.txt0.2 KB
bundle/repro/artifacts/http/vulnerable_2/result.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_2/version.txt0.0 KB
bundle/repro/artifacts/source_diff.txt2.3 KB
bundle/repro/artifacts/http/fixed_1/m5_headers.txt0.2 KB
bundle/repro/artifacts/http/fixed_1/m5_resp.txt0.0 KB
bundle/repro/artifacts/http/fixed_1/runtime_versions.txt1.3 KB
bundle/repro/artifacts/http/fixed_2/m5_headers.txt0.2 KB
bundle/repro/artifacts/http/fixed_2/m5_resp.txt0.0 KB
bundle/repro/artifacts/http/fixed_2/runtime_versions.txt1.3 KB
bundle/repro/artifacts/http/vulnerable_1/m5_headers.txt0.2 KB
bundle/repro/artifacts/http/vulnerable_1/m5_resp.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_1/runtime_versions.txt1.3 KB
bundle/repro/artifacts/http/vulnerable_2/m5_headers.txt0.2 KB
bundle/repro/artifacts/http/vulnerable_2/m5_resp.txt0.0 KB
bundle/repro/artifacts/http/vulnerable_2/runtime_versions.txt1.3 KB
08 · How to Fix

How to Fix CVE-2024-23334

Upgrade aiohttp · pip to 3.9.2 or later.

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2024-23334 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2024-23334

How does the CVE-2024-23334 path traversal work?

When a route is registered with web.static(..., follow_symlinks=True), the handler's path validation can be bypassed with traversal sequences in the requested URL, letting an attacker read arbitrary files readable by the aiohttp process instead of only files under the intended static directory.

Which aiohttp versions are affected by CVE-2024-23334, and where is it fixed?

Versions from 1.0.5 up to (but not including) 3.9.2 are affected. It is fixed in aiohttp 3.9.2.

How severe is CVE-2024-23334?

It is rated high severity with a CVSS score of 8.2, reflecting that an attacker can read arbitrary files outside the static root without needing prior authentication in a typical deployment.

How can I reproduce CVE-2024-23334?

Download the verified script from this page and run it in an isolated environment against aiohttp before 3.9.2 with a web.static() route configured using follow_symlinks=True. It sends a crafted request with directory-traversal sequences and shows the server returning contents of a file outside the static root.
11 · References

References for CVE-2024-23334

Authoritative sources for CVE-2024-23334 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.