From bf1b6e3865d709977259d9323935f04901aa9605 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 to whatever can reach them, without the caller presenting any. A provider's other services on public addresses, such as 161.26.0.0/16 and 166.8.0.0/14, are deliberately not on it: 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, 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 | 14 ++++++++++++++ internal/delivery/ssrf.go | 6 ++++++ 2 files changed, 20 insertions(+) diff --git a/README.md b/README.md index f6a682d..b277cc1 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,20 @@ 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 public +addresses that hand credentials to whatever can reach them, without the +caller presenting any. A cloud provider's other services on public +addresses are not refused. IBM Cloud, for example, serves its DNS +resolvers, 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..66e5769 100644 --- a/internal/delivery/ssrf.go +++ b/internal/delivery/ssrf.go @@ -43,6 +43,12 @@ var ( // permit specific blocks out of this set with // ALLOWED_EGRESS_CIDRS; see Guard. // +// A public address belongs here only if it hands credentials to +// whatever can reach it, without the caller presenting any; a +// provider's other services on public addresses, such as its DNS +// resolvers or package mirrors, stay out, 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