Now in early access, book a 30-minute demo →
← Back to blog AdvisoryHigh

Gradio SSRF via proxy_url - CVE-2026-28416

Self-hosted AI & Inference·High·CVE-2026-28416·
Affected gradio < 6.6.0 (gr.load proxy_url handling); fixed in 6.6.0

CVE-2026-28416 is a Gradio SSRF in the gr.load() path, rated High and classified as CWE-918 (server-side request forgery). When Gradio loads an external Space's configuration it blindly trusts the Space's proxy_url field, letting an attacker who hosts a malicious Space steer the victim server into proxying requests to internal services and the cloud metadata endpoint. The flaw affects gradio < 6.6.0 and is fixed in 6.6.0 (GHSA-jmh7-g254-2cq9). This advisory covers what the bug exposes, why a Gradio app is an agentic-endpoint problem, and how Anomity surfaces and governs the agents that drive it.

What happened

Gradio is the UI layer that many AI models and agents ship behind - a small web app that wraps a model or pipeline in an interface. Its gr.load() helper lets one app pull in and mount an external Space by fetching that Space's configuration. The configuration is where the trust boundary breaks.

In the affected versions, when gr.load() processes an external Space's configuration it blindly trusts the proxy_url field: the untrusted proxy_url is added directly to self.proxy_urls. The app exposes a /proxy={url_path} endpoint that validates requests only by checking whether the URL host matches an allowlist entry - and the attacker controls that entry, because it came from the Space they host. An attacker who publishes a malicious Space can inject a proxy_url pointing at sensitive endpoints such as the cloud metadata service at http://169.254.169.254/, causing the victim server to proxy arbitrary requests to internal services and cloud infrastructure.

That position is the impact. Because the Gradio server issues the outbound request, the attacker inherits the server's network position rather than their own. The forged request can reach internal services that are not exposed to the internet, cloud instance metadata endpoints that may return short-lived credentials, and hosts inside isolated network segments the attacker could not otherwise touch. Loading a single untrusted Space config is enough to turn a trusted UI layer into a proxy into the environment behind it.

DetailValue
IdentifierCVE-2026-28416 (GHSA-jmh7-g254-2cq9)
TypeServer-side request forgery, CWE-918 (untrusted proxy_url in gr.load)
SeverityHigh
Packagegradio (pip)
Componentgr.load() proxy_url handling / /proxy={url_path} endpoint
Affectedgradio < 6.6.0
Fixed ingradio 6.6.0

Why this is an agentic-endpoint risk

A Gradio app rarely sits alone. Gradio is the UI layer many AI models and agents ship behind, so on a managed endpoint the Gradio process is an AI artifact in its own right - and so are the Claude Code sessions, MCP servers, and command-line agents that stand it up, load Spaces into it, or call it. When an agent can trigger a Space load, it can reach the very gr.load() path this SSRF abuses.

That reachability is the risk, and the artifact-layer tie-in is the config: loading an untrusted Space's configuration is what pulls a hostile proxy_url into the app. An agent or a user who points gr.load() at an attacker's Space - by mistake, through a poisoned tool definition, or as a deliberate attack - hands the server a proxy_url it will trust. Network and EDR controls see the outbound connection, but cannot tell you which agents on which endpoints run a gradio build below 6.6.0, or whether any were allowed to load a Space from outside your trust boundary.

The SSRF-to-cloud-metadata behaviour mirrors the pattern we track across self-hosted AI and gateways, including the Ollama Model Pull API SSRF - CVE-2026-5530 and the LiteLLM api_base SSRF and key leak - CVE-2024-6587: a request-driven primitive that steers a trusted runtime to 169.254.169.254. It sits alongside sibling issues in this cluster such as the MLflow AI Gateway secrets exfiltration - CVE-2026-4035, the MLflow model serving command injection - CVE-2026-0596, the LlamaIndex SQL injection - CVE-2025-1793, and the Flowise Airtable agent code injection - CVE-2026-41265. The runtime is one node in a graph of AI artifacts, and you can't govern what you can't see. A fleet-wide inventory of every AI artifact is the precondition for scoping an SSRF like this one.

How Anomity surfaces and governs it

Anomity inventories eight AI artifact types on every managed endpoint: AI agents, MCP servers, extensions, skills, plugins, secrets, hooks, and CLIs. For CVE-2026-28416 that means the Gradio-hosted app and its gradio version are catalogued alongside the agents and CLIs that drive it, so you can answer "which endpoints run a build below 6.6.0, and what can load a Space into it" from the fleet inventory instead of guessing.

On agents that expose a hook, such as Claude Code PreToolUse, Anomity returns allow, deny, or log on each tool call before it runs. That is the enforcement point in runtime governance: a tool call that loads an untrusted Space config through gr.load() can be denied or logged in line rather than discovered after the forged request has already reached an internal service or the metadata endpoint. Anomity collects metadata only and redacts secrets on the endpoint, so any credentials the SSRF tried to reach never pass through Anomity.

Every decision is written to a queryable 90-day audit trail. After a disclosure like this, that trail is what lets responders scope the event: which agents loaded which Spaces, when, and what proxy_url each call carried. Anomity routes those decisions to SIEM, Slack, email, or Jira so the right team sees them in the tool they already use. The result is the timeline and the enforcement record described under outcomes.

Anomity complements your existing Network, EDR, DLP, and GRC controls rather than replacing them. It adds the agentic-endpoint layer those tools cannot see. See how it works and how Anomity compares for where it fits.

What to check across your fleet

  • Identify every endpoint and service running a Gradio app and record the exact gradio version; treat anything below 6.6.0 as affected and upgrade to 6.6.0 or later.
  • Inventory every place your code calls gr.load() and confirm each target Space is one you control or explicitly trust, since the vulnerable path trusts a remote Space's proxy_url.
  • Deny the Gradio runtime egress to the cloud metadata endpoint at 169.254.169.254, internal services, and isolated segments it has no business reaching.
  • Restrict network reachability so Gradio apps are not exposed to untrusted callers, and require authentication in front of the app.
  • Review outbound connection and DNS logs for requests to metadata endpoints or unexpected internal hosts originating from Gradio processes.
  • Enumerate which AI agents, CLIs, and MCP servers can trigger a Space load through an affected Gradio app, using a fleet-wide AI artifact inventory.
  • Confirm hook-based allow/deny/log enforcement is active on agents that drive Gradio, so loading an untrusted Space config can be blocked before it runs.
  • Track remediation to closure by version, so an endpoint that reverts to a gradio build below 6.6.0 is flagged again.

CVE-2026-28416 turns loading one untrusted Space config into a foothold for reaching internal services and cloud metadata, which is exactly why the AI artifact layer needs its own inventory and enforcement. For the full cluster context, see the pillar on securing AI agent frameworks and the related pillar on securing LLM gateways and proxies. To see Anomity inventory your agents, govern tool calls at the hook, and keep a 90-day audit trail, request early access.

Frequently asked questions

What is CVE-2026-28416 in Gradio?

CVE-2026-28416 (GHSA-jmh7-g254-2cq9) is a High-severity server-side request forgery in Gradio, tracked as CWE-918. When Gradio's gr.load() processes an external Space's configuration, it blindly trusts the proxy_url field and adds it directly to self.proxy_urls. The app then exposes a /proxy={url_path} endpoint that validates requests only by checking whether the URL host matches an allowlist entry. An attacker who hosts a malicious Space can inject a proxy_url pointing at sensitive endpoints, such as the cloud metadata service at 169.254.169.254, causing the victim server to proxy arbitrary requests to internal services and cloud infrastructure. The flaw affects gradio < 6.6.0 and is fixed in 6.6.0.

How do I fix the Gradio proxy_url SSRF?

Upgrade the gradio package to 6.6.0 or later, where the proxy_url handling in gr.load() is fixed. Until every endpoint and service is on a fixed build, treat loading an untrusted Space as loading untrusted code: only call gr.load() against Spaces you control or explicitly trust, since the vulnerable path adds a remote Space's proxy_url straight into self.proxy_urls. Constrain the runtime's egress so a Gradio process cannot reach the cloud metadata endpoint at 169.254.169.254 or internal services it has no reason to contact, and review which agents and CLIs can trigger a Space load across your fleet so a pull of a poisoned config cannot happen unnoticed.

What can an attacker reach through this Gradio SSRF?

Because the Gradio server makes the outbound request, the attacker inherits the server's network position rather than their own. The /proxy={url_path} endpoint validates only that the URL host matches an allowlist entry, and the attacker controls that entry through the injected proxy_url. That lets the forged request reach internal services not exposed to the internet, cloud instance metadata endpoints such as 169.254.169.254 that can return short-lived credentials, and hosts inside isolated network segments. It is the same SSRF-to-metadata pattern seen in the Ollama Model Pull API and LiteLLM api_base cases: a request-driven primitive that turns a trusted AI runtime into a proxy into the environment behind it.

How does Anomity reduce exposure when a Gradio app is at risk?

Anomity treats the Gradio-hosted app as an AI artifact on the endpoint, so it inventories the process, its version, and the agents and CLIs that drive it. That answers which endpoints run a gradio build below 6.6.0 and what can trigger a Space load against it. On agents that expose a hook, such as Claude Code PreToolUse, Anomity returns allow, deny, or log on each tool call before it runs, so a call that loads an untrusted Space config can be denied or logged in line. Every decision lands in a queryable 90-day audit trail, giving responders the timeline to scope an SSRF event across the fleet.

Ask AI about Anomity
ChatGPT Claude Perplexity Google AI Grok