Dozzle: Pre-auth SSRF with response-body reflection via POST /api/notifications/test-webhook (default no-auth deploy)
Date: 2026-05
Affected: go/github.com/amir20/dozzle
Attack vector: ssrf
Category: vulnerability-disclosure
Severity: High
CVE: CVE-2026-45298
CWE: CWE-918
CVSS: 8.6 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N)

## Summary In a default dozzle deploy (the documented quickstart, no `DOZZLE_AUTH_PROVIDER` set), `POST /api/notifications/test-webhook` is reachable without authentication and forwards an attacker-controlled URL into a `WebhookDispatcher` that: - Sends an HTTP POST to the supplied URL with attacker-controlled request headers, and - Returns the response status code AND up to 1MB of the response body to the caller, when the target replies non-2xx. This is a classic full-reflection SSRF, pre-auth, against any IP/port that dozzle's host can route to — including private subnets, link-local cloud metadata, and loopback services. ## Affected versions `internal/notification/dispatcher/webhook.go` and `internal/web/notifications.go` at commit `581bab3a43ead84ea4d009a469a17af98fb3377f` and earlier (the test-webhook handler has been in place since the notifications subsystem was added). ## Default-deploy reachability chain ``` main.go:58-59 → enforces AuthProvider in {none, forward-proxy, simple} support/cli/args.go:18 → AuthProvider default is "none" main.go:231-243 → when AuthProvider == "none", web.AuthProvider stays at NONE internal/web/routes.go:130-132, 137-138 → auth middleware only registered if Provider != NONE internal/web/routes.go:172-188 → /api/notifications/* (incl. /test-webhook) is inside that conditional Group ``` So the default Quickstart deploy ```bash docker run -v /var/run/docker.sock:/var/run/docker.sock -p 8080:8080 amir20/doz


Mitigations:

Architectural layers (MAESTRO):