How API Security Works in AUTOMATIC1111: Authentication and Request Validation
AUTOMATIC1111 secures its FastAPI-based REST API through optional HTTP Basic Authentication configured via --api-auth and request validation that filters sensitive parameters and blocks local network requests using runtime flags.
The AUTOMATIC1111/stable-diffusion-webui repository exposes a REST API at /sdapi/v1/... for programmatic access to Stable Diffusion generation features. Understanding how API security works in AUTOMATIC1111 is essential before exposing the service to networks beyond localhost, as the implementation combines credential-based access control with strict input sanitization to prevent unauthorized usage and server-side request forgery (SSRF).
Authentication Layer
The WebUI implements HTTP Basic Authentication as an optional but recommended security boundary. When enabled, every API endpoint requires valid credentials passed in the Authorization header, with passwords validated using constant-time comparison to prevent timing attacks.
Enabling HTTP Basic Authentication
Authentication is configured at startup using command-line arguments defined in modules/cmd_args.py. You can pass credentials directly or load them from a file:
# Single user
python webui.py --api-auth username:password
# Multiple users
python webui.py --api-auth user1:pass1,user2:pass2
# From file
python webui.py --api-auth-path /path/to/credentials.txt
In modules/api/api.py, the Api class constructor parses these credentials into a dictionary during initialization:
if shared.cmd_opts.api_auth:
for auth in shared.cmd_opts.api_auth.split(","):
user, password = auth.split(":")
self.credentials[user] = password
The Authentication Flow
When --api-auth is present, the add_api_route method registers every endpoint with a FastAPI dependency on self.auth:
if shared.cmd_opts.api_auth:
return self.app.add_api_route(path, endpoint,
dependencies=[Depends(self.auth)], **kwargs)
The auth method itself, implemented in modules/api/api.py, uses FastAPI's HTTPBasic scheme and secrets.compare_digest for secure comparison:
def auth(self, credentials: HTTPBasicCredentials = Depends(HTTPBasic())):
if credentials.username in self.credentials:
if secrets.compare_digest(credentials.password,
self.credentials[credentials.username]):
return True
raise HTTPException(
status_code=401,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Basic"}
)
If no --api-auth flag is provided, the API operates in open mode, suitable only for trusted local networks.
Request Validation and Input Sanitization
Beyond authentication, the API validates incoming payloads to prevent parameter injection and restricts external HTTP requests to mitigate SSRF vulnerabilities.
Pydantic Model Whitelisting
The API dynamically generates Pydantic models from internal processing classes (StableDiffusionProcessingTxt2Img, StableDiffusionProcessingImg2Img) but explicitly excludes dangerous fields. In modules/api/models.py, the API_NOT_ALLOWED list defines prohibited parameters:
API_NOT_ALLOWED = [
"self", "kwargs", "sd_model", "outpath_samples", "outpath_grids",
"sampler_index", "extra_generation_params", "overlay_images",
"do_not_reload_embeddings", "seed_enable_extras", "prompt_for_display",
"sampler_noise_scheduler_override", "ddim_discretize"
]
During model generation, the PydanticModelGenerator skips these fields, ensuring API consumers cannot override internal file paths, change model storage locations, or access restricted generation parameters.
Image URL Validation and SSRF Protection
When processing base64-encoded images or remote URLs in modules/api/api.py, the decode_base64_to_image function implements two critical runtime checks stored in the global opts object (modules/shared.py):
opts.api_enable_requests: Master switch for all external HTTP GET requests (defaultTrue)opts.api_forbid_local_requests: Blocks requests to private IP ranges whenTrue(defaultTrue)
The validation logic resolves hostnames and rejects non-global addresses:
def decode_base64_to_image(encoding):
if encoding.startswith("http://") or encoding.startswith("https://"):
if not opts.api_enable_requests:
raise HTTPException(500, "Requests not allowed")
if opts.api_forbid_local_requests and not verify_url(encoding):
raise HTTPException(500, "Request to local resource not allowed")
# ... proceed with request
The verify_url helper ensures every resolved IP is global (not private, loopback, or link-local), preventing attackers from using the API to probe internal network services.
Security Configuration Options
All security parameters are configurable via CLI flags at startup:
| Flag | Purpose | Default |
|---|---|---|
--api-auth |
Sets username:password pairs for Basic Auth | None (open) |
--api-auth-path |
Loads credentials from a file | None |
--api-enable-requests |
Allows external HTTP requests for images | True |
--api-forbid-local-requests |
Blocks requests to local/private IPs | True |
These values persist in shared.opts and are accessible throughout the application lifecycle.
Practical Implementation Examples
Authenticated Text-to-Image Request
Call the txt2img endpoint with Basic Auth credentials:
curl -X POST "http://127.0.0.1:7860/sdapi/v1/txt2img" \
-u alice:SecretPass \
-H "Content-Type: application/json" \
-d '{
"prompt": "a cyberpunk city at sunset",
"steps": 30,
"cfg_scale": 7,
"width": 512,
"height": 512,
"sampler_index": "Euler",
"send_images": true
}' | jq .
The -u flag generates the Authorization: Basic header that the auth method validates against the credentials supplied via --api-auth.
Submitting Remote Images with URL Validation
For img2img operations using external images:
curl -X POST "http://127.0.0.1:7860/sdapi/v1/img2img" \
-u admin:Pass123 \
-H "Content-Type: application/json" \
-d '{
"init_images": ["https://example.com/public/photo.jpg"],
"prompt": "portrait in the style of Van Gogh",
"denoising_strength": 0.6,
"steps": 20
}' | jq .
Under the hood, decode_base64_to_image checks opts.api_enable_requests and opts.api_forbid_local_requests, then calls verify_url to ensure example.com resolves to a global IP address before fetching the resource.
Hardening Against External Requests
To completely disable remote image fetching and prevent SSRF attacks:
python webui.py --api-auth admin:StrongPwd \
--api-enable-requests=False \
--api-forbid-local-requests=True
Any request containing an external URL now returns:
{
"error": "HTTPException",
"detail": "Requests not allowed"
}
Summary
- Authentication is opt-in: Use
--api-authto enable HTTP Basic Authentication viamodules/api/api.py, storing credentials inself.credentialsand validating withsecrets.compare_digest. - Parameter filtering is automatic: The
API_NOT_ALLOWEDwhitelist inmodules/api/models.pyprevents API consumers from setting internal paths or restricted generation parameters. - SSRF protection is runtime-configurable: The
decode_base64_to_imagefunction inmodules/api/api.pyusesverify_urlandopts.api_forbid_local_requeststo block requests to local network resources. - Security flags are centralized: All settings are defined in
modules/cmd_args.pyand stored inmodules/shared.py's globaloptsobject.
Frequently Asked Questions
Is the AUTOMATIC1111 API open by default?
Yes. Unless you explicitly provide the --api-auth command-line argument, the REST API endpoints in modules/api/api.py do not require authentication, making them accessible to any client that can reach the server. You should only run without authentication on trusted local networks.
How does the API prevent server-side request forgery (SSRF)?
The decode_base64_to_image function checks opts.api_forbid_local_requests (default True) and calls verify_url to resolve hostnames and validate that target IPs are global addresses. Requests to private ranges (10.0.0.0/8, 192.168.0.0/16), loopback (127.0.0.1), or link-local addresses are rejected with a 500 error before any HTTP request is executed.
Which internal parameters are blocked from API access?
The API_NOT_ALLOWED list in modules/api/models.py excludes sensitive fields such as sd_model, outpath_samples, outpath_grids, sampler_index, and sampler_noise_scheduler_override from the dynamically generated Pydantic models. This prevents API users from changing model storage paths or overriding internal generation settings.
Can I load authentication credentials from a file instead of the command line?
Yes. Use the --api-auth-path flag to specify a text file containing username:password pairs. The startup logic in modules/api/api.py reads this file and populates self.credentials identically to the --api-auth flag, keeping sensitive credentials out of process lists and shell history.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →