From 5a81d23dfe19496d1f8f3f056dd4aeda9a4aa922 Mon Sep 17 00:00:00 2001 From: clawbot <35+clawbot@noreply.example.org> Date: Tue, 29 Sep 2026 08:43:59 +0000 Subject: [PATCH] State what the default blocklist covers (closes #244) The default blocklist covers the IPv4 private and reserved ranges, IPv6 loopback, unique local and link-local addresses, and public addresses that hand credentials, user data or bootstrap material to whatever can reach them, without the caller presenting anything. A provider's other public addresses, such as 161.26.0.0/16 and 166.8.0.0/14, are not refused: they hand out no credentials that way, reaching them can be legitimate, and every cloud has some, so a partial list would promise coverage it does not give. The README's egress section and the comment above blockedNetworks now state this rule, naming the same material as the rule above alwaysBlockedNetworks, so nobody infers wider coverage and a future candidate can be accepted or refused against it. No list change. Model: opus-5-5 --- README.md | 15 +++++++++++++++ internal/delivery/ssrf.go | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/README.md b/README.md index 9af5688..93e2684 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,21 @@ public cloud metadata addresses: currently only `168.63.129.16`, Azure's WireServer, which serves an Azure VM its credentials. Because it is a public address, listing it in `ALLOWED_EGRESS_CIDRS` reopens it. +That is all the default blocklist covers: the IPv4 private and reserved +ranges; of IPv6, only loopback (`::1`), unique local addresses +(`fc00::/7`) and link-local addresses (`fe80::/10`); and certain public +addresses. A public address belongs on the default blocklist only if it +hands credentials, user data or bootstrap material to whatever can reach +it, without the caller presenting anything. A provider's other public +addresses are not refused. IBM Cloud, for example, serves its package +mirrors, time servers and object storage on `161.26.0.0/16`, and the +private endpoints of its own cloud services on `166.8.0.0/14`. Neither +range hands out credentials that way: the token service among those +endpoints issues a token only in exchange for something the caller +presents, such as an API key. Reaching these services can be a +legitimate delivery, and every cloud has some, so a partial list would +promise coverage it does not give. + That default is also inconvenient for the thing webhooker is mostly for: taking a public webhook and forwarding it to something on your own network. A container on the same Docker network, a box on `10.x`, a diff --git a/internal/delivery/ssrf.go b/internal/delivery/ssrf.go index 0fa73b3..547c1e6 100644 --- a/internal/delivery/ssrf.go +++ b/internal/delivery/ssrf.go @@ -43,6 +43,13 @@ var ( // permit specific blocks out of this set with // ALLOWED_EGRESS_CIDRS; see Guard. // +// A public address belongs on the default blocklist only if it +// hands credentials, user data or bootstrap material to whatever +// can reach it, without the caller presenting anything. A +// provider's other public addresses are not refused, since +// reaching them can be legitimate and no list of them could be +// complete. +// //nolint:gochecknoglobals // package-level network list is appropriate here var blockedNetworks []*net.IPNet