feat: blocked_networks config and extended SSRF ranges (closes #67)
check / check (push) Successful in 2m28s

Add a blocked_networks config key: a list of CIDRs parsed with net/netip,
added to (not replacing) the built-in SSRF blocklist. An invalid CIDR
aborts startup naming the key and the offending value.

Extend the built-in blocklist to CGNAT 100.64.0.0/10, IETF protocol
assignments 192.0.0.0/24, benchmark 198.18.0.0/15, and NAT64 64:ff9b::/96,
unmapping IPv4-mapped IPv6 so the IPv4 ranges are caught in both forms.
Enforcement stays in the dial-time re-resolution (dialSSRFSafe), which now
also consults the operator-supplied prefixes, so the DNS-rebinding window
remains closed.

Model: opus-4-8
This commit is contained in:
2026-09-21 19:11:01 +00:00
parent a7dfbf4414
commit fc720bfeee
6 changed files with 199 additions and 12 deletions
+11 -3
View File
@@ -25,10 +25,20 @@ The disk cache is now size-bounded with LRU eviction
# Next Step
P1: implement blocked networks configuration to extend SSRF protection
P1: rate limit global concurrent upstream fetches to prevent resource
exhaustion
# Completed Steps
- 2026-09-21 blocked networks configuration extending SSRF protection: a
`blocked_networks` config key taking a list of CIDRs (parsed with
`net/netip`, an invalid entry aborts startup naming the key and value),
added to the built-in blocklist rather than replacing it; the built-in
ranges extended to CGNAT `100.64.0.0/10`, IETF protocol assignments
`192.0.0.0/24`, benchmark `198.18.0.0/15`, and NAT64 `64:ff9b::/96`
(IPv4-mapped forms covered); enforcement stays in the dial-time
re-resolution so the DNS-rebinding window remains closed; documented in
`README.md` and `config.example.yml`.
- 2026-09-21 http.Server hardening (closes #92): added
`HTTPReadHeaderTimeout` (10s, bounds the slowloris header dribble) and
`HTTPIdleTimeout` (120s, bounds keep-alive reuse) alongside the
@@ -130,8 +140,6 @@ P1: implement blocked networks configuration to extend SSRF protection
# Future Steps
- P1: rate limit global concurrent upstream fetches to prevent
resource exhaustion
- P1: strip EXIF and other metadata from processed images (privacy)
- P2: security
- referer blacklist