Skip to content

CVE-2026-49119: Verified Reproduction

CVE-2026-49119: Gradio FileExplorer path traversal

CVE-2026-49119 is verified against gradio-app/gradio · github. Affected versions: < 6.16.0. Fixed in 6.16.0. Vulnerability class: Path Traversal. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00246.

REPRO-2026-00246 gradio-app/gradio · github Path Traversal Jul 6, 2026 CVE entry .txt
Severity
HIGH
CVSS
7.5
Confidence
HIGH
Reproduced in
21m 20s
Tool calls
195
Spend
$2.33
01 · Overview

What Is CVE-2026-49119?

CVE-2026-49119 is a high-severity path traversal vulnerability (CWE-22) in Gradio's FileExplorer component that lets an unauthenticated attacker read arbitrary files on the Gradio server host. Pruva reproduced it (reproduction REPRO-2026-00246).

02 · Severity & CVSS

CVE-2026-49119 Severity & CVSS Score

CVE-2026-49119 is rated high severity, with a CVSS base score of 7.5 out of 10.

HIGH threat level
7.5 / 10 CVSS base
Weakness CWE-22 — Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

High — serious impact or readily exploitable. Prioritize remediation.

03 · Affected Versions

Affected gradio-app/gradio Versions

gradio-app/gradio · github versions < 6.16.0 are affected.

How to Reproduce CVE-2026-49119

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

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

FileExplorer payload with ../ traversal segments

Attack chain
  1. /gradio_api/run/predict/ of a running Gradio app with FileExplorer input
How the agent worked 521 events · 195 tool calls · 21 min
21 minDuration
195Tool calls
151Reasoning steps
521Events
Agent activity over 21 min
Support
16
Hypothesis
2
Repro
286
Judge
19
Variant
194
0:0021:20

Root Cause and Exploit Chain for CVE-2026-49119

Versions: Gradio before 6.16.0 (vulnerable code present at commit 0d670adf41a0b510f7fd745495dce1664d38f0e5).Fixed: Gradio 6.16.0 (fix commit 97d541f3d5fd05b2587a69ecc94b68fe5d2d7004).

Gradio before 6.16.0 contains a path-traversal vulnerability in the FileExplorer component's preprocess() method. When a Gradio app exposes a FileExplorer input, an unauthenticated remote attacker can send API requests containing .. segments as the selected file path. The vulnerable preprocess() implementation joins the attacker-controlled segments directly under the configured root_dir using os.path.join + os.path.normpath, producing a resolved path that escapes the intended root directory. The resulting path is passed to the user-defined prediction function, enabling arbitrary file read (CWE-22) from the Gradio server host.

  • Product / component: gradio Python package, specifically gradio/components/file_explorer.py (FileExplorer component).
  • Affected versions: Gradio before 6.16.0 (vulnerable code present at commit 0d670adf41a0b510f7fd745495dce1664d38f0e5).
  • Fixed version: Gradio 6.16.0 (fix commit 97d541f3d5fd05b2587a69ecc94b68fe5d2d7004).
  • Risk / consequences: High. Any unauthenticated user who can reach the Gradio API can read arbitrary files readable by the Gradio process (e.g., /etc/passwd, application secrets, source code). The attacker only needs to know or guess the relative path structure above the configured root_dir.

Impact Parity

  • Disclosed / claimed maximum impact: Information disclosure / arbitrary file read via directory traversal (info_leak).
  • Reproduced impact from this run: The running vulnerable Gradio app returned the contents of a file outside the configured root_dir (/tmp/gradio_secret.txt) in response to an API call with a .. traversal payload. The fixed commit rejected the same payload and did not return the file contents.
  • Parity: full — the reproduction demonstrates the exact info-leak impact claimed by the ticket.
  • Not demonstrated: N/A (full impact was reached through the real API surface).

Root Cause

In the vulnerable FileExplorer.preprocess() implementation:

file_ = os.path.normpath(os.path.join(self.root_dir, *file))

os.path.join simply concatenates root_dir with the attacker-provided path segments, and os.path.normpath then resolves any .. segments. Because there is no validation that the final resolved path remains inside root_dir, a payload such as ["..", "gradio_secret.txt"] resolves to /tmp/gradio_root/../gradio_secret.txt/tmp/gradio_secret.txt, which is outside the configured root. This behavior was inconsistent with the component's ls() method, which already validated paths via _safe_join.

The fix commit 97d541f3d5fd05b2587a69ecc94b68fe5d2d7004 (PR #13437) routes both preprocess branches through the same _safe_join helper used by ls(). _safe_join raises InvalidPathError when the combined path is absolute or escapes root_dir, blocking the traversal.

Reproduction Steps

  1. Run bundle/repro/reproduction_steps.sh. The script is self-contained and works from any directory; it sets PRUVA_ROOT automatically if not provided.
  2. What the script does:
    • Clones or reuses the Gradio repository in the durable project cache (/data/pruva/project-cache/.../repo).
    • Creates a Python venv in the project cache and installs Gradio as an editable package from the repo.
    • Checks out the vulnerable commit (0d670adf41a0b510f7fd745495dce1664d38f0e5), starts a small Gradio app with a FileExplorer input rooted at /tmp/gradio_root, and uses _frontend=False so the server can run without a built frontend.
    • Waits until the /gradio_api/info health endpoint responds, then sends a crafted POST to /gradio_api/run/predict/ with payload {"data": [[["..", "gradio_secret.txt"]]]}.
    • Verifies that the response contains the secret string PRUVA_SECRET_12345 read from /tmp/gradio_secret.txt, confirming the info leak.
    • Repeats the same test against the fixed commit (97d541f3d5fd05b2587a69ecc94b68fe5d2d7004) and verifies that the secret is no longer returned (the API returns a 500 error with no secret data).
  3. Expected evidence: The vulnerable run logs a 200 response with {"data": ["PRUVA_SECRET_12345"]}. The fixed run logs a 500 response with {"error": "", "visible": true} and no secret content.

Evidence

  • bundle/logs/reproduction_steps.log — full console output from both runs.
  • bundle/logs/server_vuln.log — Gradio server logs for the vulnerable commit.
  • bundle/logs/server_fixed.log — Gradio server logs for the fixed commit (contains the InvalidPathError traceback).
  • bundle/repro/runtime_manifest.json — structured runtime evidence (service started, healthcheck passed, target endpoint reached, proof artifacts listed).
  • bundle/repro/validation_verdict.json — structured verdict confirming the claim.

Key excerpt from the vulnerable run:

{
  "data": ["PRUVA_SECRET_12345"],
  "is_generating": false,
  "duration": 0.0002281665802001953,
  ...
}

Key excerpt from the fixed run:

{
  "error": "",
  "visible": true
}

Recommendations / Next Steps

  • Upgrade to Gradio 6.16.0 or later, which includes the _safe_join validation in FileExplorer.preprocess().
  • Validate all user-provided paths against a known-safe root directory before using them for filesystem operations. Prefer library helpers such as safe_join over raw os.path.join/os.path.normpath for user input.
  • Regression tests should be added that exercise preprocess() with .. and absolute-path payloads, asserting that InvalidPathError (or equivalent) is raised.
  • Defense in depth: run the Gradio service with minimal file-system permissions and avoid placing sensitive files in locations readable by the process.

Additional Notes

  • Idempotency: The reproduction script was run twice consecutively and produced the same confirmed result both times.
  • Environment: The script runs in a clean sandbox using only Python 3.14 and the tools available there. It installs Gradio from source into a project-cache venv, so subsequent runs reuse the build environment while still performing fresh current-run proofs.
  • Limitations: The reproduction uses _frontend=False because the checked-out source repository does not contain the built frontend assets. This is a deployment convenience and does not affect the API surface under test; the real /gradio_api/run/predict/ endpoint is exercised and the vulnerable FileExplorer.preprocess() code path is reached.

CVE-2026-49119 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:00
0:00
session startedaccounts/fireworks/models/kimi-k2p7-code · CVE-2026-49119 · REPRO-20
0:01
0:03
web search
0:05
0:07
0:09
web search
0:15
0:16
web search
0:28
0:28
extract_facts
no facts extracted
0:29
0:29
0:29
supportrepro
0:44
0:45
0:45
0:46
0:46
0:47
0:47
0:47
0:49
0:49
0:52
0:52
0:56
0:58
web search
1:00
08 · How to Fix

How to Fix CVE-2026-49119

Upgrade gradio-app/gradio · github to 6.16.0 or later.

Coming soon

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

10 · FAQ

FAQ: CVE-2026-49119

How does the CVE-2026-49119 path traversal work?

An unauthenticated remote attacker who can reach the Gradio API sends an API request containing .. segments as the selected FileExplorer path; the vulnerable preprocess() implementation resolves the path outside root_dir and passes it to the user-defined prediction function, letting the attacker read files such as /etc/passwd or application secrets that are readable by the Gradio process.

Which Gradio versions are affected by CVE-2026-49119, and where is it fixed?

Gradio before 6.16.0 is affected (vulnerable code present at commit 0d670adf41a0b510f7fd745495dce1664d38f0e5); it is fixed in 6.16.0 (fix commit 97d541f3d5fd05b2587a69ecc94b68fe5d2d7004).

How severe is CVE-2026-49119?

It is rated high severity: any unauthenticated user who can reach a Gradio app exposing a FileExplorer input can read arbitrary files readable by the Gradio process, without needing credentials.

How can I reproduce CVE-2026-49119?

Download the verified script from this page and run it in an isolated environment against a Gradio app before 6.16.0 that exposes a FileExplorer input. It sends a request with directory traversal segments and shows a file outside the configured root directory being read, then confirms 6.16.0 blocks the escape.
11 · References

References for CVE-2026-49119

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