internal/delivery/ssrf.go:38-72 hardcodes the blocked ranges with no configuration field. RFC1918, loopback and CGNAT are permanently unreachable as delivery destinations.
That guard is correct as a default and must stay the default — it is what #36, #68 and #69 bought. But webhooker is self-hosted software whose main use is receiving a public webhook and forwarding it to an internal service: a container on the same Docker network, a box on 10.x, a service on 127.0.0.1. All of those are refused today, with no way to permit one.
Concrete evidence of the bite: during the deployability run I could not point a target at a sink on the same host, because every address on it is in the blocklist. The end-to-end test had to use a public internet echo service instead.
Definition of done:
a config value (e.g. ALLOWED_EGRESS_CIDRS, defaulting empty) allows specific CIDRs through the guard
it is a CIDR allowlist, not a boolean off switch: no setting disables SSRF protection wholesale
the link-local metadata range stays blocked unconditionally, even if a supplied CIDR would cover it, since that is credential theft rather than an internal target
set-but-unparseable values abort startup, per #80 and repo policy
the allowlist applies at BOTH target-creation validation and delivery time, so the two paths cannot disagree (that split was the #68 and #69 bug)
startup logs the effective allowlist when non-empty, so an operator can see the hole they opened
tests: a permitted CIDR delivers, a non-permitted private address is still refused, metadata stays refused even when covered by a supplied CIDR
README documents it with the risk stated plainly
`internal/delivery/ssrf.go:38-72` hardcodes the blocked ranges with no configuration field. RFC1918, loopback and CGNAT are permanently unreachable as delivery destinations.
That guard is correct as a default and must stay the default — it is what #36, #68 and #69 bought. But webhooker is self-hosted software whose main use is receiving a public webhook and forwarding it to an internal service: a container on the same Docker network, a box on `10.x`, a service on `127.0.0.1`. All of those are refused today, with no way to permit one.
Concrete evidence of the bite: during the deployability run I could not point a target at a sink on the same host, because every address on it is in the blocklist. The end-to-end test had to use a public internet echo service instead.
Definition of done:
- a config value (e.g. `ALLOWED_EGRESS_CIDRS`, defaulting empty) allows specific CIDRs through the guard
- it is a CIDR allowlist, not a boolean off switch: no setting disables SSRF protection wholesale
- the link-local metadata range stays blocked unconditionally, even if a supplied CIDR would cover it, since that is credential theft rather than an internal target
- set-but-unparseable values abort startup, per #80 and repo policy
- the allowlist applies at BOTH target-creation validation and delivery time, so the two paths cannot disagree (that split was the #68 and #69 bug)
- startup logs the effective allowlist when non-empty, so an operator can see the hole they opened
- tests: a permitted CIDR delivers, a non-permitted private address is still refused, metadata stays refused even when covered by a supplied CIDR
- README documents it with the risk stated plainly
clawbot
added this to the 1.0.0 milestone 2026-08-20 05:47:37 +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.
internal/delivery/ssrf.go:38-72hardcodes the blocked ranges with no configuration field. RFC1918, loopback and CGNAT are permanently unreachable as delivery destinations.That guard is correct as a default and must stay the default — it is what #36, #68 and #69 bought. But webhooker is self-hosted software whose main use is receiving a public webhook and forwarding it to an internal service: a container on the same Docker network, a box on
10.x, a service on127.0.0.1. All of those are refused today, with no way to permit one.Concrete evidence of the bite: during the deployability run I could not point a target at a sink on the same host, because every address on it is in the blocklist. The end-to-end test had to use a public internet echo service instead.
Definition of done:
ALLOWED_EGRESS_CIDRS, defaulting empty) allows specific CIDRs through the guardclawbot referenced this issue2026-08-20 05:56:52 +02:00