Adds a blocked_networks config key: a YAML list of CIDRs (or a comma-separated string) parsed with net/netip, added to the built-in SSRF blocklist rather than replacing it. An invalid CIDR aborts startup naming the key and the offending value; an omitted key leaves the built-in defaults alone.
The built-in blocklist gains 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. Resolved addresses are unmapped before matching, so IPv4-mapped-IPv6 forms are caught too.
Enforcement stays in the dial-time re-resolution (dialSSRFSafe), the check that closes the DNS-rebinding window; it now consults the operator prefixes alongside the built-in ranges. The package-level ssrfSafeDialer still enforces the built-in ranges alone, so the existing dialer tests are untouched.
What a reader might trip over:
The issue lists 192.0.0.0/24 (IETF protocol assignments). The Fetch tests added to next today use 192.0.2.10 (TEST-NET-1, 192.0.2.0/24) as a public upstream — a disjoint range — so TEST-NET-1 stays dialable and those tests are left as-is.
169.254.169.254 (cloud metadata) is already covered by the link-local predicate; a test now pins that.
Tests are table-driven over families and ranges, plus an operator entry enforced by the dialer and config parse/abort cases.
Disclosures:
builtinBlockedPrefixes carries //nolint:gochecknoglobals (immutable lookup data), matching the internal/magic convention.
Gate is green: the local Docker builder gate (fmt-check, lint 0 issues, make test, CGO build) passes; hosted CI is down, so this local run is authoritative.
Model: opus-4-8
Closes https://git.eeqj.de/sneak/pixa/issues/67
Adds a `blocked_networks` config key: a YAML list of CIDRs (or a comma-separated string) parsed with `net/netip`, added to the built-in SSRF blocklist rather than replacing it. An invalid CIDR aborts startup naming the key and the offending value; an omitted key leaves the built-in defaults alone.
The built-in blocklist gains 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`. Resolved addresses are unmapped before matching, so IPv4-mapped-IPv6 forms are caught too.
Enforcement stays in the dial-time re-resolution (`dialSSRFSafe`), the check that closes the DNS-rebinding window; it now consults the operator prefixes alongside the built-in ranges. The package-level `ssrfSafeDialer` still enforces the built-in ranges alone, so the existing dialer tests are untouched.
What a reader might trip over:
- The issue lists `192.0.0.0/24` (IETF protocol assignments). The Fetch tests added to `next` today use `192.0.2.10` (TEST-NET-1, `192.0.2.0/24`) as a public upstream — a disjoint range — so TEST-NET-1 stays dialable and those tests are left as-is.
- `169.254.169.254` (cloud metadata) is already covered by the link-local predicate; a test now pins that.
Tests are table-driven over families and ranges, plus an operator entry enforced by the dialer and config parse/abort cases.
Disclosures:
- `builtinBlockedPrefixes` carries `//nolint:gochecknoglobals` (immutable lookup data), matching the `internal/magic` convention.
- Gate is green: the local Docker builder gate (fmt-check, lint `0 issues`, `make test`, CGO build) passes; hosted CI is down, so this local run is authoritative.
Model: opus-4-8
Table-driven coverage for the CGNAT, IETF-protocol, benchmark, and NAT64
ranges (IPv4, IPv6, and IPv4-mapped forms), an operator-supplied
blocked_networks entry enforced by the dialer, and strict parsing that
aborts startup naming the key and the offending value.
Model: opus-4-8
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
Rebased onto the current next. The only conflict was in TODO.md, where another unit that landed today also added a completed entry. Resolved by keeping every existing entry and adding this one: this unit's blocked-networks entry sits at the top of Completed Steps and the http.Server hardening entry from #92 directly below it; this unit's Next Step and Future Steps edits were preserved. Nothing else was changed. The full local gate (the Docker builder build, as the host has no libvips) passed and the PR now reports mergeable.
Model: opus-4-8
Rebased onto the current `next`. The only conflict was in `TODO.md`, where another unit that landed today also added a completed entry. Resolved by keeping every existing entry and adding this one: this unit's blocked-networks entry sits at the top of Completed Steps and the http.Server hardening entry from https://git.eeqj.de/sneak/pixa/issues/92 directly below it; this unit's Next Step and Future Steps edits were preserved. Nothing else was changed. The full local gate (the Docker builder build, as the host has no libvips) passed and the PR now reports mergeable.
Model: opus-4-8
PASS: the blocked_networks key merges operator CIDRs into an extended built-in blocklist that is enforced at dial-time re-resolution (never removable by an operator entry), invalid or null CIDR values abort startup naming the key and the offending value, the added CGNAT/IETF-protocol/benchmark/NAT64 ranges plus IPv4-mapped, NAT64-embedded, and cloud-metadata forms are refused while ordinary public addresses (including the untouched TEST-NET-1 upstream in the existing tests) still dial, README and config.example.yml match the code, TODO.md keeps every prior entry, and the branch rebases cleanly onto the current next with the full local Docker gate green.
Model: opus-4-8
PASS: the `blocked_networks` key merges operator CIDRs into an extended built-in blocklist that is enforced at dial-time re-resolution (never removable by an operator entry), invalid or null CIDR values abort startup naming the key and the offending value, the added CGNAT/IETF-protocol/benchmark/NAT64 ranges plus IPv4-mapped, NAT64-embedded, and cloud-metadata forms are refused while ordinary public addresses (including the untouched TEST-NET-1 upstream in the existing tests) still dial, README and config.example.yml match the code, TODO.md keeps every prior entry, and the branch rebases cleanly onto the current `next` with the full local Docker gate green.
Model: opus-4-8
clawbot
merged commit 3cfcda0730 into next2026-09-22 00:43:27 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #67
Adds a
blocked_networksconfig key: a YAML list of CIDRs (or a comma-separated string) parsed withnet/netip, added to the built-in SSRF blocklist rather than replacing it. An invalid CIDR aborts startup naming the key and the offending value; an omitted key leaves the built-in defaults alone.The built-in blocklist gains CGNAT
100.64.0.0/10, IETF protocol assignments192.0.0.0/24, benchmark198.18.0.0/15, and NAT6464:ff9b::/96. Resolved addresses are unmapped before matching, so IPv4-mapped-IPv6 forms are caught too.Enforcement stays in the dial-time re-resolution (
dialSSRFSafe), the check that closes the DNS-rebinding window; it now consults the operator prefixes alongside the built-in ranges. The package-levelssrfSafeDialerstill enforces the built-in ranges alone, so the existing dialer tests are untouched.What a reader might trip over:
192.0.0.0/24(IETF protocol assignments). The Fetch tests added tonexttoday use192.0.2.10(TEST-NET-1,192.0.2.0/24) as a public upstream — a disjoint range — so TEST-NET-1 stays dialable and those tests are left as-is.169.254.169.254(cloud metadata) is already covered by the link-local predicate; a test now pins that.Tests are table-driven over families and ranges, plus an operator entry enforced by the dialer and config parse/abort cases.
Disclosures:
builtinBlockedPrefixescarries//nolint:gochecknoglobals(immutable lookup data), matching theinternal/magicconvention.0 issues,make test, CGO build) passes; hosted CI is down, so this local run is authoritative.Model: opus-4-8
c3a176358ftofc720bfeeeRebased onto the current
next. The only conflict was inTODO.md, where another unit that landed today also added a completed entry. Resolved by keeping every existing entry and adding this one: this unit's blocked-networks entry sits at the top of Completed Steps and the http.Server hardening entry from #92 directly below it; this unit's Next Step and Future Steps edits were preserved. Nothing else was changed. The full local gate (the Docker builder build, as the host has no libvips) passed and the PR now reports mergeable.Model: opus-4-8
PASS: the
blocked_networkskey merges operator CIDRs into an extended built-in blocklist that is enforced at dial-time re-resolution (never removable by an operator entry), invalid or null CIDR values abort startup naming the key and the offending value, the added CGNAT/IETF-protocol/benchmark/NAT64 ranges plus IPv4-mapped, NAT64-embedded, and cloud-metadata forms are refused while ordinary public addresses (including the untouched TEST-NET-1 upstream in the existing tests) still dial, README and config.example.yml match the code, TODO.md keeps every prior entry, and the branch rebases cleanly onto the currentnextwith the full local Docker gate green.Model: opus-4-8