Factory.ai

Open-Source Wikis

/

Stable Diffusion WebUI

/

Security

AUTOMATIC1111/stable-diffusion-webui

Security

The webui is designed for single-user, local use. Most of its security posture follows from that assumption: the API is unauthenticated by default, the Extensions tab can install arbitrary code, and the launcher pip-installs without sandboxing. Running it in a multi-tenant or internet-exposed setting requires extra care.

Trust boundaries

Boundary Default posture Hardening
Network Listens on 127.0.0.1:7860 --listen, --port, reverse proxy, TLS
HTTP / browser No auth, very permissive Gradio CORS removed (see below) --gradio-auth, --api-auth, --cors-allow-origins
Extensions tab Can install any URL the user pastes; runs install.py afterwards --enable-insecure-extension-access=false (default outside of localhost)
Custom code script Disabled Don't enable --allow-code on shared deployments
Pickle deserialisation of .ckpt Restricted unpickler --disable-safe-unpickle removes the restriction
Image URLs in API extras Optional api_enable_requests / api_forbid_local_requests

CORS

By default Gradio enables an extremely permissive CORS policy. The webui explicitly strips the middleware in webui.py:

# gradio uses a very open CORS policy via app.user_middleware, which makes it possible for
# an attacker to trick the user into opening a malicious HTML page, which makes a request to the
# running web ui and do whatever the attacker wants, including installing an extension and
# running its code. We disable this here. Suggested by RyotaK.
app.user_middleware = [x for x in app.user_middleware if x.cls.__name__ != 'CORSMiddleware']

If you need cross-origin access (e.g., a frontend on a different host calling the API), use --cors-allow-origins=https://my.frontend.example or --cors-allow-origins-regex=^https://(.*)\\.mycompany\\.com$. These are wired into modules/initialize_util.py setup_middleware().

Authentication

  • Gradio UI auth--gradio-auth user:password,user2:password2 enables HTTPBasic on the UI. --gradio-auth-path file.txt reads from a file (one entry per line).
  • API auth--api-auth user:password,... and --api-auth-file cover /sdapi/v1/*. Implementation in Api.auth() (modules/api/api.py) uses secrets.compare_digest to avoid timing leaks.
  • The two flags are independent; you can have a public UI and a locked-down API or vice versa, but for any public deployment both should be set.

There is no role-based access control. Any authenticated user can change settings, install extensions (if allowed), and trigger arbitrary generations.

Extensions are arbitrary code

The Extensions tab installs git repositories from URLs the user pastes. After cloning, it runs the extension's install.py (if present) and imports its scripts/*.py at boot. There is no sandboxing.

For shared deployments:

  • Set --enable-insecure-extension-access=false (the default when the webui isn't on 127.0.0.1).
  • Optionally combine with --disable-all-extensions all (lock to a known-good set).
  • Audit extensions in extensions/ periodically; treat them as full process privileges.

Pickle safety

Stable Diffusion checkpoints distributed in .ckpt format are pickle archives — they execute Python on load if not contained. modules/safe.py provides a restricted unpickler that only allows a known list of types (torch.nn.Parameter, basic Python builtins, numpy arrays, …). This is enabled by default.

--disable-safe-unpickle turns the restriction off — only do this when you trust the checkpoint absolutely. Prefer .safetensors files, which use a safe binary format and bypass pickle entirely.

Image URL fetching

/sdapi/v1/extra-single-image accepts an image as base64 or as a URL. Two settings gate the URL path:

  • api_enable_requests (default true) — allows URL inputs at all.
  • api_forbid_local_requests (default true) — blocks URLs that resolve to private IP space, preventing trivial SSRF.

verify_url() in modules/api/api.py does the IP-resolution check using ipaddress.ip_address.is_global. It is a best-effort defence and assumes the resolver isn't lying; in hostile networks set api_enable_requests=false and require base64 inputs.

Custom code

scripts/custom_code.py runs user-supplied Python with the full webui in scope. It is disabled by default and requires --allow-code on the command line. The Settings page warns when the flag is set.

For any non-localhost deployment, do not enable this flag.

Localhost vs LAN vs Internet

Topology Settings Comments
Localhost only Defaults are fine The address bar shows 127.0.0.1.
LAN sharing --listen --port 7860 --gradio-auth ... --api-auth ... --enable-insecure-extension-access=false Add HTTPS via a reverse proxy.
Internet-exposed All of the above + --cors-allow-origins, lock down extensions, consider --disable-all-extensions extra The extensions registry can be poisoned in principle; review before enabling new ones.
--share (Gradio tunnel) Adds a public *.gradio.live URL Useful for one-off demos; auth is required because the tunnel is open.

Reporting vulnerabilities

The README does not list a security contact. Issues affecting the project's security can be filed in private to the maintainer (@AUTOMATIC1111). Embargoed disclosure is informal — high-impact issues have historically been patched within days through a regular PR (the credit string for "Security advice — RyotaK" stems from this exact loop in late 2022).

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Security – Stable Diffusion WebUI wiki | Factory