Skip to content
Verified reproduction

REPRO-2026-00299: Horilla protected_media public-prefix normalization bypass: unauthenticated private in-root read on the repaired release

REPRO-2026-00299 is verified against horilla/horilla-hr · github vulnerability class: Path Traversal This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00299.

REPRO-2026-00299 horilla/horilla-hr · github Path Traversal Jul 27, 2026 .txt
Severity HIGH
Confidence HIGH
Reproduced in 84m 5s
Tool calls 263
Spend $4.05
$ pruva-verify REPRO-2026-00299
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00299/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.
02 · The vulnerability

Horilla's protected_media() view makes the authorization decision using path.startswith() on the RAW request path, while the filesystem decision uses safe_join(settings.MEDIA_ROOT, path) on the CANONICAL path. When an attacker requests /../../, the raw path passes the allowlist prefix check (authorization granted), but the filesystem normalizes the dot segments and serves a private in-root media file. The resolved file never leaves MEDIA_ROOT, so safe_join() is satisfied. This is NOT path traversal.

03 · Root cause
04 · Reproduction transcript

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

Loading session...

05 · Artifacts

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

bundle/repro/reproduction_steps.sh17.8 KB
bundle/repro/rca_report.md11.2 KB
bundle/repro/runtime_manifest.json2.2 KB
bundle/logs/reproduction_steps.log5.0 KB
bundle/logs/repro/1.6.0_oracle_run1.json0.2 KB
bundle/logs/repro/1.6.0_observed_paths_run1.txt0.5 KB
bundle/logs/repro/1.6.0_dotseg_bypass_run1.resp.body0.0 KB
bundle/logs/repro/1.6.0_oracle_run2.json0.2 KB
bundle/logs/repro/1.6.0_observed_paths_run2.txt0.9 KB
bundle/logs/repro/1.6.0_dotseg_bypass_run2.resp.body0.0 KB
bundle/logs/repro/1.6.0_direct_private_run1.resp.hdr0.7 KB
bundle/logs/repro/1.6.0_direct_private_run2.resp.hdr0.7 KB
bundle/logs/repro/1.6.0_server.log1.2 KB
bundle/logs/repro/1.6.0_modified_files.txt0.0 KB
bundle/logs/repro/1.6.0_head.txt0.0 KB
bundle/logs/repro/dev_v2.0_oracle_run1.json0.3 KB
bundle/logs/repro/dev_v2.0_oracle_run2.json0.3 KB
bundle/logs/repro/dev_v2.0_observed_paths_run1.txt0.5 KB
bundle/logs/repro/dev_v2.0_observed_paths_run2.txt0.9 KB
bundle/logs/repro/dev_v2.0_dotseg_bypass_run1.resp.body0.0 KB
bundle/logs/repro/dev_v2.0_dotseg_bypass_run2.resp.body0.0 KB
bundle/logs/repro/dev_v2.0_direct_private_run1.resp.hdr0.7 KB
bundle/logs/repro/dev_v2.0_direct_private_run2.resp.hdr0.7 KB
bundle/logs/repro/dev_v2.0_server.log1.6 KB
bundle/logs/repro/dev_v2.0_modified_files.txt0.0 KB
bundle/logs/repro/dev_v2.0_head.txt0.1 KB
bundle/logs/repro/1.5.0_oracle_run1.json0.3 KB
bundle/logs/repro/1.5.0_oracle_run2.json0.3 KB
bundle/logs/repro/1.5.0_observed_paths_run1.txt0.3 KB
bundle/logs/repro/1.5.0_observed_paths_run2.txt0.5 KB
bundle/logs/repro/1.5.0_dotseg_bypass_run1.resp.body0.0 KB
bundle/logs/repro/1.5.0_dotseg_bypass_run2.resp.body0.0 KB
bundle/logs/repro/1.5.0_direct_private_run1.resp.hdr0.7 KB
bundle/logs/repro/1.5.0_direct_private_run2.resp.hdr0.7 KB
bundle/logs/repro/1.5.0_server.log0.8 KB
bundle/logs/repro/1.5.0_modified_files.txt0.0 KB
bundle/logs/repro/1.5.0_head.txt0.0 KB
bundle/repro/validation_verdict.json0.8 KB