# stable-diffusion-webui — SSRF via `urllib.request.urlopen()` in Extensions tab (access-control bypass) STATUS: ALMOST_REPORT (needs investigation; do not submit) readiness: NEEDS_INVESTIGATION program: stable-diffusion-webui | platform: huntr | repo: AUTOMATIC1111/stable-diffusion-webui | commit: 82a973c ```` Repository URL: https://github.com/AUTOMATIC1111/stable-diffusion-webui Package Manager: pip Version Affected: v1.10.1 (commit 82a973c) Vulnerability Type: Server-Side Request Forgery (SSRF) CVSS: Attack Vector: Network Attack Complexity: Low Privileges Required: Low User Interaction: None Scope: Changed Confidentiality: High Integrity: None Availability: None Title: SSRF via unvalidated URL in Extensions "Load from" (refresh_available_extensions) Impact: A remote user with Gradio UI access can force the server to issue attacker-chosen requests (blind SSRF), potentially reaching internal services (e.g., cloud metadata) even when extension actions are otherwise disabled for non-local deployments. Description: # Description `modules/ui_extensions.py` exposes an Extensions tab that includes an "Available" view with a "Load from" button. That button calls `refresh_available_extensions(url, ...)`. `refresh_available_extensions()` performs: ```py import urllib.request with urllib.request.urlopen(url) as response: text = response.read() available_extensions = json.loads(text) ``` The `url` is user-controlled via the "Extension index URL" text input. Other extension operations in this module call `check_access()`, which asserts `not shared.cmd_opts.disable_extension_access`. In non-local deployments (`--listen`, `--share`, `--ngrok`, etc.) `disable_extension_access` is enabled by default unless `--enable-insecure-extension-access` is explicitly set. However, `refresh_available_extensions()` does not call `check_access()`, so the network request is still performed even when extension access is otherwise disabled. Even if `json.loads()` fails on non-JSON responses, the outbound request is still made, enabling blind SSRF to internal services (and potentially instance metadata endpoints on cloud hosts). # Proof of Concept Precondition: attacker has access to the Gradio UI over the network (for example the operator started the server with `--listen` or `--share`). 1. Navigate to `Extensions` -> `Available`. 2. In "Extension index URL", set one of the following: ```text http://169.254.169.254/latest/meta-data/ http://127.0.0.1:2375/version http://localhost:8080/ ``` 3. Click "Load from:". Expected behavior: the server issues a request to the supplied URL; JSON parsing may fail, but the request is still performed. ### Impact Blind SSRF to internal services reachable from the server network context; on cloud deployments this may reach instance metadata endpoints and lead to credential exposure depending on environment and error handling. ### Occurrences ``` Permalink: https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/82a973c04367123ae98bd9abdf80d9eda9b910e2/modules/ui_extensions.py#L407-L415 Description: refresh_available_extensions() calls urllib.request.urlopen() on attacker-controlled URL without access control or SSRF protections. Permalink: https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/82a973c04367123ae98bd9abdf80d9eda9b910e2/modules/shared_cmd_options.py#L18-L18 Description: disable_extension_access is enabled for non-local deployments unless --enable-insecure-extension-access; refresh_available_extensions bypasses this control by not calling check_access(). ``` ### References ``` URL: https://cwe.mitre.org/data/definitions/918.html Name: CWE-918: Server-Side Request Forgery (SSRF) URL: https://docs.python.org/3/library/urllib.request.html#urllib.request.urlopen Name: Python urllib.request.urlopen() ``` Occurrences: Permalink: https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/82a973c04367123ae98bd9abdf80d9eda9b910e2/modules/ui_extensions.py#L407-L415 Description: refresh_available_extensions() calls urllib.request.urlopen(url) on a user-provided URL without calling check_access() or doing SSRF protection. Permalink: https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/82a973c04367123ae98bd9abdf80d9eda9b910e2/modules/shared_cmd_options.py#L18-L18 Description: disable_extension_access is enabled by default for non-local deployments unless --enable-insecure-extension-access is set; refresh_available_extensions bypasses this control by not calling check_access(). References: URL: https://cwe.mitre.org/data/definitions/918.html Name: CWE-918: Server-Side Request Forgery (SSRF) URL: https://docs.python.org/3/library/urllib.request.html#urllib.request.urlopen Name: Python urllib.request.urlopen() ````