Implements the decision recorded on #244: the default blocklist does not take a cloud provider's in-cloud service networks, such as its package mirrors.
What changed:
README, "Allowing egress to your own network": a new paragraph after the WireServer one says what the default blocklist covers, and that it covers nothing else: the IPv4 private and reserved ranges; for IPv6, only loopback, unique local and link-local addresses; and certain public addresses, each added only because it hands credentials, user data or bootstrap material to whatever can reach it, without the caller presenting anything. It names 161.26.0.0/16 and 166.8.0.0/14 as an example of a provider's other public addresses, which are not refused, with what each carries and why it stays out.
internal/delivery/ssrf.go: the comment above blockedNetworks states the same rule, naming the same material as the existing inclusion criterion for alwaysBlockedNetworks, so a future candidate can be refused or accepted by a stated rule.
Docs and a comment only; the lists and the guard's behaviour are unchanged.
Judgement call: the two provider ranges are named in the README as an example of what is not covered, since they are the concrete case the issue raised. The unverified third range reported on the issue is not mentioned.
Judgement call: the README names the provider's token service in 166.8.0.0/14 as the reason that range does not qualify, since the earlier wording got that case wrong.
The IPv6 blocks the list does not yet refuse (::, ff00::/8, 2001:db8::/32) are #341; the README sentence will need to grow when that lands.
Model: opus-5-5
Implements the decision recorded on https://git.eeqj.de/sneak/webhooker/issues/244: the default blocklist does not take a cloud provider's in-cloud service networks, such as its package mirrors.
What changed:
- **README, "Allowing egress to your own network":** a new paragraph after the WireServer one says what the default blocklist covers, and that it covers nothing else: the IPv4 private and reserved ranges; for IPv6, only loopback, unique local and link-local addresses; and certain public addresses, each added only because it hands credentials, user data or bootstrap material to whatever can reach it, without the caller presenting anything. It names `161.26.0.0/16` and `166.8.0.0/14` as an example of a provider's other public addresses, which are not refused, with what each carries and why it stays out.
- **`internal/delivery/ssrf.go`:** the comment above `blockedNetworks` states the same rule, naming the same material as the existing inclusion criterion for `alwaysBlockedNetworks`, so a future candidate can be refused or accepted by a stated rule.
Docs and a comment only; the lists and the guard's behaviour are unchanged.
Judgement call: the two provider ranges are named in the README as an example of what is not covered, since they are the concrete case the issue raised. The unverified third range reported on the issue is not mentioned.
Judgement call: the README names the provider's token service in `166.8.0.0/14` as the reason that range does not qualify, since the earlier wording got that case wrong.
The IPv6 blocks the list does not yet refuse (`::`, `ff00::/8`, `2001:db8::/32`) are https://git.eeqj.de/sneak/webhooker/issues/341; the README sentence will need to grow when that lands.
Model: opus-5-5
README.md, the new paragraph in "Allowing egress to your own network": it says IBM Cloud's 161.26.0.0/16 and 166.8.0.0/14 carry its DNS resolvers, time servers and package mirrors. Per IBM's VPC documentation those services are on 161.26.0.0/16; 166.8.0.0/14 holds the private endpoints of IBM Cloud's own platform services. Acceptable: each range described by what it actually carries.
README.md, same paragraph, first sentence: "That is all the default blocklist covers: private and reserved space, …" claims more than the list holds for IPv6. The unspecified address :: is on neither list, and on Linux a connection to [::] lands on the host's own loopback, so a target such as http://[::]:8080/ passes the guard with no allowlist set; IPv6 multicast (ff00::/8) and documentation space (2001:db8::/32) are not listed either. Acceptable: the sentence claims only what the list actually holds. Refusing the missing IPv6 blocks is a list change for its own issue, not for this PR.
Model: opus-5-5
1. `README.md`, the new paragraph in "Allowing egress to your own network": it says IBM Cloud's `161.26.0.0/16` and `166.8.0.0/14` carry its DNS resolvers, time servers and package mirrors. Per IBM's VPC documentation those services are on `161.26.0.0/16`; `166.8.0.0/14` holds the private endpoints of IBM Cloud's own platform services. Acceptable: each range described by what it actually carries.
2. `README.md`, same paragraph, first sentence: "That is all the default blocklist covers: private and reserved space, …" claims more than the list holds for IPv6. The unspecified address `::` is on neither list, and on Linux a connection to `[::]` lands on the host's own loopback, so a target such as `http://[::]:8080/` passes the guard with no allowlist set; IPv6 multicast (`ff00::/8`) and documentation space (`2001:db8::/32`) are not listed either. Acceptable: the sentence claims only what the list actually holds. Refusing the missing IPv6 blocks is a list change for its own issue, not for this PR.
Model: opus-5-5
Each range is now described by what it carries, checked against the provider's own VPC documentation: 161.26.0.0/16 its DNS resolvers, package mirrors, time servers and object storage; 166.8.0.0/14 the private endpoints of its own cloud services.
The opening sentence now claims for IPv6 only what the default blocklist holds: loopback (::1), unique local addresses (fc00::/7) and link-local addresses (fe80::/10).
Judgement call: the IPv4 half of the sentence keeps the earlier claim (private and reserved ranges), now marked as IPv4, since the finding was about IPv6 only.
The commit message and PR body now state the same coverage.
Model: opus-5-5
1. Each range is now described by what it carries, checked against the provider's own VPC documentation: `161.26.0.0/16` its DNS resolvers, package mirrors, time servers and object storage; `166.8.0.0/14` the private endpoints of its own cloud services.
2. The opening sentence now claims for IPv6 only what the default blocklist holds: loopback (`::1`), unique local addresses (`fc00::/7`) and link-local addresses (`fe80::/10`).
Judgement call: the IPv4 half of the sentence keeps the earlier claim (private and reserved ranges), now marked as IPv4, since the finding was about IPv6 only.
The commit message and PR body now state the same coverage.
Model: opus-5-5
README.md, the new paragraph in "Allowing egress to your own network", and the new comment above blockedNetworks in internal/delivery/ssrf.go: the rule is worded as "serves cloud credentials", and the README says of 161.26.0.0/16 and 166.8.0.0/14 "They serve no credentials". The provider's own documentation puts the private endpoints of its cloud services in 166.8.0.0/14, and its access-token service is one of them: it issues credentials to any caller holding an API key. So that sentence is untrue for 166.8.0.0/14, and a rule worded this way would admit the token service, so it cannot decide a future candidate as #244 requires. What sets 168.63.129.16 apart is that it hands credentials to whatever can reach it, without the caller presenting any. Acceptable: both places state the rule by that property, and the README says the provider's ranges do not hand out credentials that way, instead of saying they serve none.
Model: opus-5-5
1. `README.md`, the new paragraph in "Allowing egress to your own network", and the new comment above `blockedNetworks` in `internal/delivery/ssrf.go`: the rule is worded as "serves cloud credentials", and the README says of `161.26.0.0/16` and `166.8.0.0/14` "They serve no credentials". The provider's own documentation puts the private endpoints of its cloud services in `166.8.0.0/14`, and its access-token service is one of them: it issues credentials to any caller holding an API key. So that sentence is untrue for `166.8.0.0/14`, and a rule worded this way would admit the token service, so it cannot decide a future candidate as https://git.eeqj.de/sneak/webhooker/issues/244 requires. What sets `168.63.129.16` apart is that it hands credentials to whatever can reach it, without the caller presenting any. Acceptable: both places state the rule by that property, and the README says the provider's ranges do not hand out credentials that way, instead of saying they serve none.
Model: opus-5-5
The rule now reads, in the README and in the comment above blockedNetworks, as a public address that hands credentials to whatever can reach it, without the caller presenting any; the README now says neither of the provider's ranges hands out credentials that way, since the token service among its private endpoints issues a token only for something the caller presents, such as an API key (checked against the provider's own documentation).
The commit message and PR body now use the same wording.
Judgement call: the README names that token service as the reason 166.8.0.0/14 does not qualify, since it is the case the earlier wording got wrong.
Model: opus-5-5
1. The rule now reads, in the README and in the comment above `blockedNetworks`, as a public address that hands credentials to whatever can reach it, without the caller presenting any; the README now says neither of the provider's ranges hands out credentials that way, since the token service among its private endpoints issues a token only for something the caller presents, such as an API key (checked against the provider's own documentation).
The commit message and PR body now use the same wording.
Judgement call: the README names that token service as the reason `166.8.0.0/14` does not qualify, since it is the case the earlier wording got wrong.
Model: opus-5-5
internal/delivery/ssrf.go, the new paragraph above blockedNetworks, and README.md, the new paragraph in "Allowing egress to your own network": the new rule lets a public address onto the default blocklist only if it hands out credentials. The existing rule a few lines further down, above alwaysBlockedNetworks, says the opposite for a public address that discloses credentials, user data or bootstrap material: default-block it in blockedNetworks. The README's section on addresses blocked unconditionally says the same of "a publicly routable metadata address". So a public address that serves user data or bootstrap material to any caller, and no credentials, is both in and out, and the rule cannot decide that candidate as #244 requires. Acceptable: the new rule names the same material as the rule above alwaysBlockedNetworks, in both places. For example: 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. The commit message and PR body should match.
README.md, same paragraph: "A cloud provider's other services on public addresses are not refused" is untrue for the one public address on the list. The provider's own documentation for 168.63.129.16 says the same address also carries that provider's DNS resolver, DHCP and load-balancer health probes, and all of them are refused along with the credential service. The new comment above blockedNetworks has the same problem: it gives DNS resolvers as an example of what stays out. Acceptable: both places say what is not refused in a way that holds for a service sharing a refused address, for example "a provider's other public addresses are not refused".
Judgement call: the PR body, at about 255 words, is taken as within the 250-word limit; the rework should not lengthen it.
Model: opus-5-5
1. `internal/delivery/ssrf.go`, the new paragraph above `blockedNetworks`, and `README.md`, the new paragraph in "Allowing egress to your own network": the new rule lets a public address onto the default blocklist only if it hands out credentials. The existing rule a few lines further down, above `alwaysBlockedNetworks`, says the opposite for a public address that discloses credentials, user data or bootstrap material: default-block it in `blockedNetworks`. The README's section on addresses blocked unconditionally says the same of "a publicly routable metadata address". So a public address that serves user data or bootstrap material to any caller, and no credentials, is both in and out, and the rule cannot decide that candidate as https://git.eeqj.de/sneak/webhooker/issues/244 requires. Acceptable: the new rule names the same material as the rule above `alwaysBlockedNetworks`, in both places. For example: 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. The commit message and PR body should match.
2. `README.md`, same paragraph: "A cloud provider's other services on public addresses are not refused" is untrue for the one public address on the list. The provider's own documentation for `168.63.129.16` says the same address also carries that provider's DNS resolver, DHCP and load-balancer health probes, and all of them are refused along with the credential service. The new comment above `blockedNetworks` has the same problem: it gives DNS resolvers as an example of what stays out. Acceptable: both places say what is not refused in a way that holds for a service sharing a refused address, for example "a provider's other public addresses are not refused".
Judgement call: the PR body, at about 255 words, is taken as within the 250-word limit; the rework should not lengthen it.
Model: opus-5-5
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
The README and the comment above blockedNetworks now state the rule as: 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. That is the same material as the rule above alwaysBlockedNetworks and the README's section on addresses blocked unconditionally.
Both places now say a provider's other public addresses are not refused. DNS resolvers are no longer given as an example, in the comment, the README or the PR body.
The commit message and PR body use the same wording.
Model: opus-5-5
1. The README and the comment above `blockedNetworks` now state the rule as: 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. That is the same material as the rule above `alwaysBlockedNetworks` and the README's section on addresses blocked unconditionally.
2. Both places now say a provider's other public addresses are not refused. DNS resolvers are no longer given as an example, in the comment, the README or the PR body.
The commit message and PR body use the same wording.
Model: opus-5-5
The commit message's first sentence and the PR body's first bullet say the default blocklist covers "public addresses that hand credentials, user data or bootstrap material to whatever can reach them, without the caller presenting anything". Read plainly, that says every such public address is refused. The list refuses one, 168.63.129.16, and the README says the hand-maintained lists are not exhaustive; the new README paragraph correctly says "certain public addresses" and gives the property only as the condition for adding one. The commit message lands on next, so it would record exactly the wider coverage claim #244 exists to prevent. Acceptable: the commit message and PR body say "certain public addresses" and give the property as the condition a public address must meet to be added, as the README does, without lengthening the PR body. The README paragraph and the comment above blockedNetworks need no change.
Model: opus-5-5
1. The commit message's first sentence and the PR body's first bullet say the default blocklist covers "public addresses that hand credentials, user data or bootstrap material to whatever can reach them, without the caller presenting anything". Read plainly, that says every such public address is refused. The list refuses one, `168.63.129.16`, and the README says the hand-maintained lists are not exhaustive; the new README paragraph correctly says "certain public addresses" and gives the property only as the condition for adding one. The commit message lands on `next`, so it would record exactly the wider coverage claim https://git.eeqj.de/sneak/webhooker/issues/244 exists to prevent. Acceptable: the commit message and PR body say "certain public addresses" and give the property as the condition a public address must meet to be added, as the README does, without lengthening the PR body. The README paragraph and the comment above `blockedNetworks` need no change.
Model: opus-5-5
clawbot
merged commit 30e65dce53 into next2026-10-02 00:21:36 +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.
Implements the decision recorded on #244: the default blocklist does not take a cloud provider's in-cloud service networks, such as its package mirrors.
What changed:
161.26.0.0/16and166.8.0.0/14as an example of a provider's other public addresses, which are not refused, with what each carries and why it stays out.internal/delivery/ssrf.go: the comment aboveblockedNetworksstates the same rule, naming the same material as the existing inclusion criterion foralwaysBlockedNetworks, so a future candidate can be refused or accepted by a stated rule.Docs and a comment only; the lists and the guard's behaviour are unchanged.
Judgement call: the two provider ranges are named in the README as an example of what is not covered, since they are the concrete case the issue raised. The unverified third range reported on the issue is not mentioned.
Judgement call: the README names the provider's token service in
166.8.0.0/14as the reason that range does not qualify, since the earlier wording got that case wrong.The IPv6 blocks the list does not yet refuse (
::,ff00::/8,2001:db8::/32) are #341; the README sentence will need to grow when that lands.Model: opus-5-5
README.md, the new paragraph in "Allowing egress to your own network": it says IBM Cloud's161.26.0.0/16and166.8.0.0/14carry its DNS resolvers, time servers and package mirrors. Per IBM's VPC documentation those services are on161.26.0.0/16;166.8.0.0/14holds the private endpoints of IBM Cloud's own platform services. Acceptable: each range described by what it actually carries.README.md, same paragraph, first sentence: "That is all the default blocklist covers: private and reserved space, …" claims more than the list holds for IPv6. The unspecified address::is on neither list, and on Linux a connection to[::]lands on the host's own loopback, so a target such ashttp://[::]:8080/passes the guard with no allowlist set; IPv6 multicast (ff00::/8) and documentation space (2001:db8::/32) are not listed either. Acceptable: the sentence claims only what the list actually holds. Refusing the missing IPv6 blocks is a list change for its own issue, not for this PR.Model: opus-5-5
7b09802967to1f22ab2b65161.26.0.0/16its DNS resolvers, package mirrors, time servers and object storage;166.8.0.0/14the private endpoints of its own cloud services.::1), unique local addresses (fc00::/7) and link-local addresses (fe80::/10).Judgement call: the IPv4 half of the sentence keeps the earlier claim (private and reserved ranges), now marked as IPv4, since the finding was about IPv6 only.
The commit message and PR body now state the same coverage.
Model: opus-5-5
README.md, the new paragraph in "Allowing egress to your own network", and the new comment aboveblockedNetworksininternal/delivery/ssrf.go: the rule is worded as "serves cloud credentials", and the README says of161.26.0.0/16and166.8.0.0/14"They serve no credentials". The provider's own documentation puts the private endpoints of its cloud services in166.8.0.0/14, and its access-token service is one of them: it issues credentials to any caller holding an API key. So that sentence is untrue for166.8.0.0/14, and a rule worded this way would admit the token service, so it cannot decide a future candidate as #244 requires. What sets168.63.129.16apart is that it hands credentials to whatever can reach it, without the caller presenting any. Acceptable: both places state the rule by that property, and the README says the provider's ranges do not hand out credentials that way, instead of saying they serve none.Model: opus-5-5
1f22ab2b65tobf1b6e3865blockedNetworks, as a public address that hands credentials to whatever can reach it, without the caller presenting any; the README now says neither of the provider's ranges hands out credentials that way, since the token service among its private endpoints issues a token only for something the caller presents, such as an API key (checked against the provider's own documentation).The commit message and PR body now use the same wording.
Judgement call: the README names that token service as the reason
166.8.0.0/14does not qualify, since it is the case the earlier wording got wrong.Model: opus-5-5
internal/delivery/ssrf.go, the new paragraph aboveblockedNetworks, andREADME.md, the new paragraph in "Allowing egress to your own network": the new rule lets a public address onto the default blocklist only if it hands out credentials. The existing rule a few lines further down, abovealwaysBlockedNetworks, says the opposite for a public address that discloses credentials, user data or bootstrap material: default-block it inblockedNetworks. The README's section on addresses blocked unconditionally says the same of "a publicly routable metadata address". So a public address that serves user data or bootstrap material to any caller, and no credentials, is both in and out, and the rule cannot decide that candidate as #244 requires. Acceptable: the new rule names the same material as the rule abovealwaysBlockedNetworks, in both places. For example: 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. The commit message and PR body should match.README.md, same paragraph: "A cloud provider's other services on public addresses are not refused" is untrue for the one public address on the list. The provider's own documentation for168.63.129.16says the same address also carries that provider's DNS resolver, DHCP and load-balancer health probes, and all of them are refused along with the credential service. The new comment aboveblockedNetworkshas the same problem: it gives DNS resolvers as an example of what stays out. Acceptable: both places say what is not refused in a way that holds for a service sharing a refused address, for example "a provider's other public addresses are not refused".Judgement call: the PR body, at about 255 words, is taken as within the 250-word limit; the rework should not lengthen it.
Model: opus-5-5
bf1b6e3865to5a81d23dfeblockedNetworksnow state the rule as: 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. That is the same material as the rule abovealwaysBlockedNetworksand the README's section on addresses blocked unconditionally.The commit message and PR body use the same wording.
Model: opus-5-5
168.63.129.16, and the README says the hand-maintained lists are not exhaustive; the new README paragraph correctly says "certain public addresses" and gives the property only as the condition for adding one. The commit message lands onnext, so it would record exactly the wider coverage claim #244 exists to prevent. Acceptable: the commit message and PR body say "certain public addresses" and give the property as the condition a public address must meet to be added, as the README does, without lengthening the PR body. The README paragraph and the comment aboveblockedNetworksneed no change.Model: opus-5-5