Skip to content

REPRO-2026-00298: Verified Reproduction

REPRO-2026-00298: Horilla protected media composed chain: unauthenticated outside-root file read, with necessity controls for each component defect

REPRO-2026-00298 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-00298.

REPRO-2026-00298 horilla/horilla-hr · github Path Traversal Jul 27, 2026 .txt
Severity
HIGH
Confidence
HIGH
Reproduced in
54m 42s
Tool calls
254
Spend
$3.63
01 · Overview

What Is REPRO-2026-00298?

REPRO-2026-00298 is a high-severity Path Traversal vulnerability affecting horilla/horilla-hr. Pruva has independently reproduced it and publishes a verified, runnable proof-of-concept (reproduction REPRO-2026-00298).

02 · Severity & CVSS

REPRO-2026-00298 Severity

REPRO-2026-00298 is rated high severity.

HIGH threat level

High — serious impact or readily exploitable. Prioritize remediation.

How to Reproduce REPRO-2026-00298

$ pruva-verify REPRO-2026-00298
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00298/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 REPRO-2026-00298

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

media path (../canary_outside.txt) and Referer header (http://attacker.invalid/login); no credential

Attack chain
  1. GET /media/../canary_outside.txt with Referer: http://attacker.invalid/login
How the agent worked 626 events · 254 tool calls · 55 min
55 minDuration
254Tool calls
153Reasoning steps
626Events
30Dead-ends
Agent activity over 55 min
Policy
1
Support
14
Repro
350
Judge
84
Variant
172
Verify
1
0:0054:42

Root Cause and Exploit Chain for REPRO-2026-00298

Versions: Horilla HRMS 1.5.0 (commit 61bd5173220d19925ad8220db9152a75c881ea73). Both defects are present. The traversal fix landed in commit 67ac2056813ee95d4c4a0bfe7c0124a361cb6c48 (2026-02-23) and the authorization fix landed in commit b6eaec1386d8b8741a42fe7c78f318f073375791 (2026-05-20), both included in tag 1.6.0 (commit b3bd29d15819cbece45c58e6268ddd0614e387d6).

Horilla HRMS's protected_media() view in base/views.py composes two independently necessary defects: (1) a Referer-based authorization bypass that treats any request whose Referer path matches a public page (e.g., /login) as authenticated, and (2) an uncontained os.path.join() path traversal that allows the requested media path to escape MEDIA_ROOT via dot-segment traversal (../). A single HTTP request carrying no cookie, no session, no JWT, and no bearer token — only a crafted Referer: http://attacker.invalid/login header and a traversal path /media/../canary_outside.txt — returns the contents of a file stored outside the media directory. This reproduction establishes the composition by showing that removing either defect breaks the chain while the other remains independently exploitable.

  • Package/component affected: base/views.pyprotected_media() view, routed via base/urls.py as re_path(r"^media/(?P<path>.*)$", views.protected_media, name="protected_media").
  • Affected versions: Horilla HRMS 1.5.0 (commit 61bd5173220d19925ad8220db9152a75c881ea73). Both defects are present. The traversal fix landed in commit 67ac2056813ee95d4c4a0bfe7c0124a361cb6c48 (2026-02-23) and the authorization fix landed in commit b6eaec1386d8b8741a42fe7c78f318f073375791 (2026-05-20), both included in tag 1.6.0 (commit b3bd29d15819cbece45c58e6268ddd0614e387d6).
  • Risk level and consequences: High. An unauthenticated remote attacker can read arbitrary files accessible to the Horilla process by combining the Referer bypass with the path traversal. Impact is bounded to file read (info_leak); no code execution, privilege escalation, or account takeover is claimed.

Impact Parity

  • Disclosed/claimed maximum impact: Unauthenticated arbitrary file read (info_leak) via the real /media/<path> HTTP route.
  • Reproduced impact from this run: Unauthenticated read of a canary file stored outside MEDIA_ROOT via a single HTTP request with Referer: http://attacker.invalid/login and path /media/../canary_outside.txt. Response body exactly equals the outside-root canary. No credential of any kind was sent.
  • Parity: full.
  • Not demonstrated: No code execution, privilege escalation, session forgery, or secret extraction. The oracle is a random canary, not a real secret.

Root Cause

Defect 1: Referer Authorization Bypass (GHSA-9wjx-4j4r-ff8w)

The protected_media() view on 1.5.0 checks whether the URL path extracted from the Referer header is in a public_pages list:

referer_path = urlparse(request.META.get("HTTP_REFERER", "")).path
if referer_path not in public_pages and not any(
    path.startswith(f) for f in exempted_folders
):
    if not request.user.is_authenticated and not jwt_user:
        # ... redirect to login

Since /login is in public_pages, any request with Referer: http://attacker.invalid/login bypasses the authentication check entirely — regardless of whether the request carries a cookie, session, or token. The attacker controls the Referer header, so this is a trivial authorization bypass.

Defect 2: Uncontained os.path.join() Path Traversal (GHSA-x52c-5hrq-76pq)

The view constructs the file path with:

media_path = os.path.join(settings.MEDIA_ROOT, path)

Python's os.path.join() does not contain the result within MEDIA_ROOT. If path contains .. segments (e.g., ../canary_outside.txt), the resulting path escapes the media directory. The os.path.exists() check and FileResponse(open(media_path, "rb")) call then operate on a file outside MEDIA_ROOT.

Composition

A single unauthenticated request with both Referer: http://attacker.invalid/login and path /media/../canary_outside.txt:

  1. The Referer bypass skips the authentication gate.
  2. The os.path.join() traversal escapes MEDIA_ROOT.
  3. FileResponse returns the outside-root file.
Fixes
  • Traversal fix (commit 67ac2056): Replaced os.path.join() with Django's safe_join(), which raises ValueError if the path escapes the base directory. Also added os.path.isfile() check.
  • Authorization fix (commit b6eaec13, included in 1.6.0): Removed the Referer-based authorization entirely. Replaced with public_media_prefixes that only exempt specific asset directories (e.g., base/icon/), requiring authentication for all other media.

Reproduction Steps

  1. Script: bundle/repro/reproduction_steps.sh
  2. What the script does:
    • Clones (or reuses cached) the Horilla HRMS repository.
    • For each of three upstream refs (1.5.0, 67ac2056, 1.6.0), checks out the ref, installs its requirements.txt, runs migrations on a fresh SQLite database, creates two random canary files (one outside MEDIA_ROOT, one inside at a nonpublic path), and starts the real Django runserver.
    • Sends real HTTP requests via curl --path-as-is (preserving dot segments) from a separate attacker process to the running Horilla server.
    • 1.5.0 (vulnerable oracle): Sends the escaping request without Referer (expect 302 denied), with Referer (expect 200 + outside canary), and as an authenticated low-priv user (expect 200 + outside canary). Also sends an in-root request with Referer (expect 200 + in-root canary).
    • 67ac2056 (containment necessity control): Sends the escaping chain request with Referer (expect 404 — safe_join blocks traversal) and an in-root request with Referer (expect 200 + in-root canary — Referer bypass still works).
    • 1.6.0 (fixed control): Sends the chain request with Referer (expect 404), in-root request with Referer (expect 302 — no bypass), and a legitimate authenticated in-root request (expect 200 — service works).
    • Runs the complete three-ref matrix twice from clean targets with new canaries.
  3. Expected evidence: All tests pass (exit 0). Evidence files under bundle/repro/evidence/ include request/response captures, HTTP headers, status codes, server logs with server-observed paths, and canary verification for every request.

Evidence

  • Main log: bundle/logs/reproduction_steps.log — complete execution output.
  • Run logs: bundle/logs/reproduction_run1.log, bundle/logs/reproduction_run2.log (if separate).
  • Evidence directory: bundle/repro/evidence/run{1,2}/{1.5.0,67ac2056,1.6.0}/
    • request_*.txt — request metadata (method, URL, path, cookie/auth status, headers)
    • response_*.txt — response body
    • headers_*.txt — response headers
    • status_*.txt — HTTP status code
    • server.log — Django dev server log with server-observed paths
    • server_observed_paths.txt — extracted server-observed paths
    • checkout.log — git checkout and resolved commit
    • migrate.log — migration output
    • modified_files.txt — startup accommodation inventory
    • media_root_check.txt — MEDIA_ROOT and outside-canary path verification
    • outside_canary_value.txt / inroot_canary_value.txt — canary values
    • create_user.log — low-priv user creation (is_staff=False, is_superuser=False)
    • cookies.txt — session cookies for authenticated requests
  • Runtime manifest: bundle/repro/runtime_manifest.json
  • Validation verdict: bundle/repro/validation_verdict.json
Key evidence excerpts (from initial validation)

On 1.5.0:

  • GET /media/../canary_outside.txt without Referer → HTTP 302 (redirect to login), no canary in body.
  • GET /media/../canary_outside.txt with Referer: http://attacker.invalid/login → HTTP 200, body = outside-root canary.
  • Server log: "GET /media/../canary_outside.txt HTTP/1.1" 302 0 then "GET /media/../canary_outside.txt HTTP/1.1" 200 21.

On 67ac2056:

  • GET /media/../canary_outside.txt with Referer → HTTP 404 (safe_join blocks traversal).
  • GET /media/private_inroot/canary_inroot.txt with Referer → HTTP 200, body = in-root canary.
  • Server log: "GET /media/../canary_outside.txt HTTP/1.1" 404 52013 then "GET /media/private_inroot/canary_inroot.txt HTTP/1.1" 200 47.

On 1.6.0:

  • GET /media/../canary_outside.txt with Referer → HTTP 404 (safe_join blocks traversal).
  • GET /media/private_inroot/canary_inroot.txt with Referer → HTTP 302 (no Referer bypass, redirect to login).
  • Authenticated GET /media/private_inroot/canary_inroot.txt → HTTP 200, body = in-root canary (service works).
  • Server log: "GET /media/../canary_outside.txt HTTP/1.1" 404 52013, "GET /media/private_inroot/canary_inroot.txt HTTP/1.1" 302 0, "GET /media/private_inroot/canary_inroot.txt HTTP/1.1" 200 47.

Recommendations / Next Steps

  • Upgrade to 1.6.0 or later: Both defects are fixed in tag 1.6.0. The safe_join() containment and the removal of the Referer-based authorization together close the composed chain.
  • Do not restore Referer-based authorization: The Referer header is attacker-controlled and must not be used as an authorization mechanism. The public_media_prefixes approach in 1.6.0 is the correct pattern.
  • Always use safe_join() for file path containment: Never use os.path.join() to construct paths that must stay within a base directory.
  • Testing recommendations: Add integration tests that send requests with attacker-controlled Referer headers and traversal paths to protected_media(). Verify that unauthenticated requests with any Referer value are denied for non-public media.

Additional Notes

  • Idempotency: The script is idempotent — it cleans up generated files (canaries, SQLite DB) before each ref checkout and uses fresh random canaries for each run. Running it multiple times produces the same pass/fail results.
  • Canary approach: The oracle is a random canary file, never a real secret. No configuration files, databases, /proc entries, password material, credentials, or employee records are read or retained.
  • HTTP client: curl --path-as-is is used to preserve dot segments verbatim. Redirects are not followed automatically (-L not used), so 302 responses are recorded as-is.
  • Modified files: The only startup accommodations are creating canary files and a SQLite database, which are untracked data files. No source files (base/views.py, base/urls.py, routing, middleware, authentication, or file-open behavior) are modified.
  • Dependency note: PyMuPDF==1.24.5 (pinned in requirements.txt) does not build on Python 3.14. A newer PyMuPDF with pre-built wheels is installed instead. This does not affect the protected_media() code path.
  • Out of scope: The 1.6.0 dot-segment prefix-normalization bypass (tracked by HORILLA-PROTECTED-MEDIA-PREFIX-NORMALIZATION-BYPASS) is not tested here and is not used to satisfy or fail any control.

REPRO-2026-00298 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:000:53
0:00
session startedaccounts/fireworks/routers/glm-5p2-fast · HORILLA-PROTECTED-MEDIA-UNAUTH-OUTSIDE-ROOT-CHAIN · REPRO-20
0:04
0:18
0:20
web search
0:22
0:23
0:25
web search
0:40
0:40
extract_facts
no facts extracted
0:41
0:41
0:41
supportclaim_contract
0:46
0:46
0:46
0:46
0:48
0:48
0:48
0:48
0:50
0:50
0:50
0:52
0:52
0:52
0:53
0:53
0:53
0:53

Artifacts and Evidence for REPRO-2026-00298

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

bundle/repro/reproduction_steps.sh20.6 KB
bundle/repro/rca_report.md10.7 KB
bundle/repro/runtime_manifest.json8.5 KB
bundle/logs/reproduction_steps.log5.3 KB
bundle/repro/evidence/run2/1.6.0/checkout.log0.3 KB
bundle/repro/evidence/run2/1.6.0/cookies.txt0.4 KB
bundle/repro/evidence/run2/1.6.0/create_user.log0.1 KB
bundle/repro/evidence/run2/1.6.0/headers_auth_inroot.txt0.5 KB
bundle/repro/evidence/run2/1.6.0/headers_chain_referer.txt0.5 KB
bundle/repro/evidence/run2/1.6.0/headers_inroot_referer.txt0.7 KB
bundle/repro/evidence/run2/1.6.0/inroot_canary_value.txt0.0 KB
bundle/repro/evidence/run2/1.6.0/login_response.txt0.0 KB
bundle/repro/evidence/run2/1.6.0/login_status.txt0.0 KB
bundle/repro/evidence/run2/1.6.0/makemigrations.log0.0 KB
bundle/repro/evidence/run2/1.6.0/media_root_check.txt0.1 KB
bundle/repro/evidence/run2/1.6.0/migrate.log3.8 KB
bundle/repro/evidence/run2/1.6.0/modified_files.txt0.0 KB
bundle/repro/evidence/run2/1.6.0/outside_canary_value.txt0.1 KB
bundle/repro/evidence/run2/1.6.0/pip_install.log0.3 KB
bundle/repro/evidence/run2/1.6.0/request_auth_inroot.txt0.2 KB
bundle/repro/evidence/run2/1.6.0/request_chain_referer.txt0.2 KB
bundle/repro/evidence/run2/1.6.0/request_inroot_referer.txt0.2 KB
bundle/repro/evidence/run2/1.6.0/response_auth_inroot.txt0.0 KB
bundle/repro/evidence/run2/1.6.0/response_chain_referer.txt50.8 KB
bundle/repro/evidence/run2/1.6.0/response_inroot_referer.txt0.0 KB
bundle/repro/evidence/run2/1.6.0/server.log0.4 KB
bundle/repro/evidence/run2/1.6.0/server_observed_paths.txt0.1 KB
bundle/repro/evidence/run2/1.6.0/status_auth_inroot.txt0.0 KB
bundle/repro/evidence/run2/1.6.0/status_chain_referer.txt0.0 KB
bundle/repro/evidence/run2/1.6.0/status_inroot_referer.txt0.0 KB
bundle/repro/evidence/run2/67ac2056/checkout.log0.3 KB
bundle/repro/evidence/run2/67ac2056/headers_chain_referer.txt0.5 KB
bundle/repro/evidence/run2/67ac2056/headers_inroot_referer.txt0.5 KB
bundle/repro/evidence/run2/67ac2056/inroot_canary_value.txt0.0 KB
bundle/repro/evidence/run2/67ac2056/makemigrations.log0.0 KB
bundle/repro/evidence/run2/67ac2056/media_root_check.txt0.1 KB
bundle/repro/evidence/run2/67ac2056/migrate.log3.8 KB
bundle/repro/evidence/run2/67ac2056/modified_files.txt0.0 KB
bundle/repro/evidence/run2/67ac2056/outside_canary_value.txt0.1 KB
bundle/repro/evidence/run2/67ac2056/pip_install.log0.9 KB
bundle/repro/evidence/run2/67ac2056/request_chain_referer.txt0.2 KB
bundle/repro/evidence/run2/67ac2056/request_inroot_referer.txt0.2 KB
bundle/repro/evidence/run2/67ac2056/response_chain_referer.txt50.8 KB
bundle/repro/evidence/run2/67ac2056/response_inroot_referer.txt0.0 KB
bundle/repro/evidence/run2/67ac2056/server.log0.3 KB
bundle/repro/evidence/run2/67ac2056/server_observed_paths.txt0.1 KB
bundle/repro/evidence/run2/67ac2056/status_chain_referer.txt0.0 KB
bundle/repro/evidence/run2/67ac2056/status_inroot_referer.txt0.0 KB
bundle/repro/evidence/run2/1.5.0/checkout.log0.2 KB
bundle/repro/evidence/run2/1.5.0/cookies.txt0.4 KB
bundle/repro/evidence/run2/1.5.0/create_user.log0.1 KB
bundle/repro/evidence/run2/1.5.0/headers_auth_escape.txt0.5 KB
bundle/repro/evidence/run2/1.5.0/headers_chain_no_referer.txt0.7 KB
bundle/repro/evidence/run2/1.5.0/headers_chain_with_referer.txt0.5 KB
bundle/repro/evidence/run2/1.5.0/headers_inroot_referer.txt0.5 KB
bundle/repro/evidence/run2/1.5.0/inroot_canary_value.txt0.0 KB
bundle/repro/evidence/run2/1.5.0/login_response.txt0.0 KB
bundle/repro/evidence/run2/1.5.0/login_status.txt0.0 KB
bundle/repro/evidence/run2/1.5.0/makemigrations.log0.0 KB
bundle/repro/evidence/run2/1.5.0/media_root_check.txt0.1 KB
bundle/repro/evidence/run2/1.5.0/migrate.log3.8 KB
bundle/repro/evidence/run2/1.5.0/modified_files.txt0.0 KB
bundle/repro/evidence/run2/1.5.0/outside_canary_value.txt0.1 KB
bundle/repro/evidence/run2/1.5.0/pip_install.log0.3 KB
bundle/repro/evidence/run2/1.5.0/request_auth_escape.txt0.2 KB
bundle/repro/evidence/run2/1.5.0/request_chain_no_referer.txt0.2 KB
bundle/repro/evidence/run2/1.5.0/request_chain_with_referer.txt0.2 KB
bundle/repro/evidence/run2/1.5.0/request_inroot_referer.txt0.2 KB
bundle/repro/evidence/run2/1.5.0/response_auth_escape.txt0.1 KB
bundle/repro/evidence/run2/1.5.0/response_chain_no_referer.txt0.0 KB
bundle/repro/evidence/run2/1.5.0/response_chain_with_referer.txt0.1 KB
bundle/repro/evidence/run2/1.5.0/response_inroot_referer.txt0.0 KB
bundle/repro/evidence/run2/1.5.0/server.log0.5 KB
bundle/repro/evidence/run2/1.5.0/server_observed_paths.txt0.1 KB
bundle/repro/evidence/run2/1.5.0/status_auth_escape.txt0.0 KB
bundle/repro/evidence/run2/1.5.0/status_chain_no_referer.txt0.0 KB
bundle/repro/evidence/run2/1.5.0/status_chain_with_referer.txt0.0 KB
bundle/repro/evidence/run2/1.5.0/status_inroot_referer.txt0.0 KB
bundle/repro/evidence/run1/1.6.0/checkout.log0.3 KB
bundle/repro/evidence/run1/1.6.0/cookies.txt0.4 KB
bundle/repro/evidence/run1/1.6.0/create_user.log0.1 KB
bundle/repro/evidence/run1/1.6.0/headers_auth_inroot.txt0.5 KB
bundle/repro/evidence/run1/1.6.0/headers_chain_referer.txt0.5 KB
bundle/repro/evidence/run1/1.6.0/headers_inroot_referer.txt0.7 KB
bundle/repro/evidence/run1/1.6.0/inroot_canary_value.txt0.0 KB
bundle/repro/evidence/run1/1.6.0/login_response.txt0.0 KB
bundle/repro/evidence/run1/1.6.0/login_status.txt0.0 KB
bundle/repro/evidence/run1/1.6.0/makemigrations.log0.0 KB
bundle/repro/evidence/run1/1.6.0/media_root_check.txt0.1 KB
bundle/repro/evidence/run1/1.6.0/migrate.log3.8 KB
bundle/repro/evidence/run1/1.6.0/modified_files.txt0.0 KB
bundle/repro/evidence/run1/1.6.0/outside_canary_value.txt0.1 KB
bundle/repro/evidence/run1/1.6.0/pip_install.log0.3 KB
bundle/repro/evidence/run1/1.6.0/request_auth_inroot.txt0.2 KB
bundle/repro/evidence/run1/1.6.0/request_chain_referer.txt0.2 KB
bundle/repro/evidence/run1/1.6.0/request_inroot_referer.txt0.2 KB
bundle/repro/evidence/run1/1.6.0/response_auth_inroot.txt0.0 KB
bundle/repro/evidence/run1/1.6.0/response_chain_referer.txt50.8 KB
bundle/repro/evidence/run1/1.6.0/response_inroot_referer.txt0.0 KB
bundle/repro/evidence/run1/1.6.0/server.log0.4 KB
bundle/repro/evidence/run1/1.6.0/server_observed_paths.txt0.1 KB
bundle/repro/evidence/run1/1.6.0/status_auth_inroot.txt0.0 KB
bundle/repro/evidence/run1/1.6.0/status_chain_referer.txt0.0 KB
bundle/repro/evidence/run1/1.6.0/status_inroot_referer.txt0.0 KB
bundle/repro/evidence/run1/67ac2056/checkout.log0.3 KB
bundle/repro/evidence/run1/67ac2056/headers_chain_referer.txt0.5 KB
bundle/repro/evidence/run1/67ac2056/headers_inroot_referer.txt0.5 KB
bundle/repro/evidence/run1/67ac2056/inroot_canary_value.txt0.0 KB
bundle/repro/evidence/run1/67ac2056/makemigrations.log0.0 KB
bundle/repro/evidence/run1/67ac2056/media_root_check.txt0.1 KB
bundle/repro/evidence/run1/67ac2056/migrate.log3.8 KB
bundle/repro/evidence/run1/67ac2056/modified_files.txt0.0 KB
bundle/repro/evidence/run1/67ac2056/outside_canary_value.txt0.1 KB
bundle/repro/evidence/run1/67ac2056/pip_install.log0.9 KB
bundle/repro/evidence/run1/67ac2056/request_chain_referer.txt0.2 KB
bundle/repro/evidence/run1/67ac2056/request_inroot_referer.txt0.2 KB
bundle/repro/evidence/run1/67ac2056/response_chain_referer.txt50.8 KB
bundle/repro/evidence/run1/67ac2056/response_inroot_referer.txt0.0 KB
bundle/repro/evidence/run1/67ac2056/server.log0.3 KB
bundle/repro/evidence/run1/67ac2056/server_observed_paths.txt0.1 KB
bundle/repro/evidence/run1/67ac2056/status_chain_referer.txt0.0 KB
bundle/repro/evidence/run1/67ac2056/status_inroot_referer.txt0.0 KB
bundle/repro/evidence/run1/1.5.0/checkout.log0.2 KB
bundle/repro/evidence/run1/1.5.0/cookies.txt0.4 KB
bundle/repro/evidence/run1/1.5.0/create_user.log0.1 KB
bundle/repro/evidence/run1/1.5.0/headers_auth_escape.txt0.5 KB
bundle/repro/evidence/run1/1.5.0/headers_chain_no_referer.txt0.7 KB
bundle/repro/evidence/run1/1.5.0/headers_chain_with_referer.txt0.5 KB
bundle/repro/evidence/run1/1.5.0/headers_inroot_referer.txt0.5 KB
bundle/repro/evidence/run1/1.5.0/inroot_canary_value.txt0.0 KB
bundle/repro/evidence/run1/1.5.0/login_response.txt0.0 KB
bundle/repro/evidence/run1/1.5.0/login_status.txt0.0 KB
bundle/repro/evidence/run1/1.5.0/makemigrations.log0.0 KB
bundle/repro/evidence/run1/1.5.0/media_root_check.txt0.1 KB
bundle/repro/evidence/run1/1.5.0/migrate.log3.8 KB
bundle/repro/evidence/run1/1.5.0/modified_files.txt0.0 KB
bundle/repro/evidence/run1/1.5.0/outside_canary_value.txt0.1 KB
bundle/repro/evidence/run1/1.5.0/pip_install.log0.3 KB
bundle/repro/evidence/run1/1.5.0/request_auth_escape.txt0.2 KB
bundle/repro/evidence/run1/1.5.0/request_chain_no_referer.txt0.2 KB
bundle/repro/evidence/run1/1.5.0/request_chain_with_referer.txt0.2 KB
bundle/repro/evidence/run1/1.5.0/request_inroot_referer.txt0.2 KB
bundle/repro/evidence/run1/1.5.0/response_auth_escape.txt0.1 KB
bundle/repro/evidence/run1/1.5.0/response_chain_no_referer.txt0.0 KB
bundle/repro/evidence/run1/1.5.0/response_chain_with_referer.txt0.1 KB
bundle/repro/evidence/run1/1.5.0/response_inroot_referer.txt0.0 KB
bundle/repro/evidence/run1/1.5.0/server.log0.5 KB
bundle/repro/evidence/run1/1.5.0/server_observed_paths.txt0.1 KB
bundle/repro/evidence/run1/1.5.0/status_auth_escape.txt0.0 KB
bundle/repro/evidence/run1/1.5.0/status_chain_no_referer.txt0.0 KB
bundle/repro/evidence/run1/1.5.0/status_chain_with_referer.txt0.0 KB
bundle/repro/evidence/run1/1.5.0/status_inroot_referer.txt0.0 KB
bundle/repro/validation_verdict.json0.7 KB
08 · How to Fix

How to Fix REPRO-2026-00298

Coming soon

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

10 · FAQ

FAQ: REPRO-2026-00298

Is REPRO-2026-00298 exploitable?

Yes. Pruva independently reproduced REPRO-2026-00298 in horilla/horilla-hr and verified the exploit fires end-to-end in a sandboxed environment. A runnable proof-of-concept script and the full agent transcript are on this page (reproduction REPRO-2026-00298).

How severe is REPRO-2026-00298?

REPRO-2026-00298 is rated high severity.

How can I reproduce REPRO-2026-00298?

Pruva provides a verified reproduction script on this page. Download it and run it inside an isolated environment such as a container or virtual machine — never against production. The reproduction was confirmed end-to-end by Pruva's automated agents.

Is the REPRO-2026-00298 reproduction verified?

Yes. Pruva reproduced REPRO-2026-00298 with high confidence in a sandboxed environment, capturing the full agent transcript and artifacts as evidence.
11 · References

References for REPRO-2026-00298

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