Files
dashcaddy/dashcaddy-api
Hermes 0fb2d68af9 fix(sites): SSRF hardening — validateUpstream() blocks private/reserved upstreams in /site and /site/external (DC-074) [glm-grade=A]
Pre-fix: POST /api/v1/site accepted upstreams matching /^[a-z0-9.-]+:\d{1,5}$/i
with no private-IP gate. POST /api/v1/site/external called validateURL()
WITHOUT blockPrivate:true. An authenticated dashboard operator (TOTP + CSRF)
could register upstream=10.0.0.1:80 and have Caddy reverse_proxy public
traffic to an internal host. Caddy runs on DNS2, same network as the targets —
the SSRF lands.

Post-fix: new module helper validateUpstream() in fleet-validation.js
reuses the existing resolveAndCheckAddress() private-range gate (14 IPv4
reserved CIDR ranges, 6 IPv6 reserved ranges including CGNAT/multicast/
IMDS). Async, lastIndexOf(':')-split for bracketed IPv6, port 1..65535
validation, DNS resolution with rebinding defense. Opt-in via
SITES_ALLOW_PRIVATE_UPSTREAMS=true for operators who intentionally proxy
to private targets.

Routes sites.js:184 and :250 throw ValidationError [DC-074] BEFORE
caddy.read()/caddy.modify() is called. 60/60 new tests pass (helper unit,
route integration per private range, regression on canonical SSRF payloads,
helper exports unchanged). Full repo npm test: 4 unrelated billing suites
fail due to missing pdfkit module — pre-existing, not caused by this diff.
2026-08-18 15:47:06 -07:00
..
2026-03-05 02:26:12 -08:00
2026-07-24 05:14:56 -07:00