Problem
Outbound-webhook SSRF: the webhook URL validator checks the scheme (blocks file:///ftp://) but performs no host validation. An authenticated user can set the webhook URL — and the /notifications/test endpoint fires it immediately — to http://169.254.169.254/... (cloud metadata / IMDS), http://localhost:8000/..., or any internal RFC1918 address. The test endpoint returns the HTTP status code to the caller, giving a blind-to-semi-blind SSRF primitive against internal services and cloud metadata. Especially relevant on cloud VPS deployments with IMDSv1.
Evidence
codeframe/ui/routers/settings_v2.py:447-480 — _validate_webhook_url validates scheme only, no host check
codeframe/notifications/webhook.py:235-291 — send_event POSTs to the URL (5s timeout); test endpoint surfaces status code
Fix
- After parsing, resolve the host and reject loopback, link-local (
169.254.0.0/16), and RFC1918/private ranges (and IPv6 equivalents) unless explicitly opted in.
- Consider pinning the resolved IP through the request to mitigate DNS-rebinding TOCTOU.
Acceptance criteria
Source: release-readiness audit 2026-06-13 (security agent, finding M2).
Problem
Outbound-webhook SSRF: the webhook URL validator checks the scheme (blocks
file:///ftp://) but performs no host validation. An authenticated user can set the webhook URL — and the/notifications/testendpoint fires it immediately — tohttp://169.254.169.254/...(cloud metadata / IMDS),http://localhost:8000/..., or any internal RFC1918 address. The test endpoint returns the HTTP status code to the caller, giving a blind-to-semi-blind SSRF primitive against internal services and cloud metadata. Especially relevant on cloud VPS deployments with IMDSv1.Evidence
codeframe/ui/routers/settings_v2.py:447-480—_validate_webhook_urlvalidates scheme only, no host checkcodeframe/notifications/webhook.py:235-291—send_eventPOSTs to the URL (5s timeout); test endpoint surfaces status codeFix
169.254.0.0/16), and RFC1918/private ranges (and IPv6 equivalents) unless explicitly opted in.Acceptance criteria
Source: release-readiness audit 2026-06-13 (security agent, finding M2).