Adding or editing an http or slack target whose address is private or reserved is still refused, and the refusal now adds one sentence: private and reserved addresses are refused by default, and the server's ALLOWED_EGRESS_CIDRS setting allows named networks (see "Allowing egress to your own network" in the README). It is added in validateTargetURL, so add and edit both carry it, and it reaches the form once #370 and #381 show errors there.
Only private and reserved addresses get the sentence. Metadata refusals do not: a link-local or other unconditional metadata address stays refused whatever is configured, and its message already says ALLOWED_EGRESS_CIDRS cannot open it; Azure's WireServer (168.63.129.16) can be reopened by listing it, as the README says, but it serves VM credentials, so its refusal does not say how. Tests check that both lack the sentence. To tell them apart, the delivery package now refuses WireServer with its own error, "blocked cloud metadata address", and exports the private-and-reserved error as ErrBlockedIP.
The sentence names the setting and the README section only; it suggests no value, so it never points at allowing everything.
Judgement call: the private-and-reserved refusal now reads "blocked private or reserved address", dropping "or cloud metadata", since WireServer no longer shares it.
Model: opus-5-5
Adding or editing an `http` or `slack` target whose address is private or reserved is still refused, and the refusal now adds one sentence: private and reserved addresses are refused by default, and the server's `ALLOWED_EGRESS_CIDRS` setting allows named networks (see "Allowing egress to your own network" in the README). It is added in `validateTargetURL`, so add and edit both carry it, and it reaches the form once https://git.eeqj.de/sneak/webhooker/issues/370 and https://git.eeqj.de/sneak/webhooker/issues/381 show errors there.
Only private and reserved addresses get the sentence. Metadata refusals do not: a link-local or other unconditional metadata address stays refused whatever is configured, and its message already says `ALLOWED_EGRESS_CIDRS` cannot open it; Azure's WireServer (`168.63.129.16`) can be reopened by listing it, as the README says, but it serves VM credentials, so its refusal does not say how. Tests check that both lack the sentence. To tell them apart, the delivery package now refuses WireServer with its own error, "blocked cloud metadata address", and exports the private-and-reserved error as `ErrBlockedIP`.
The sentence names the setting and the README section only; it suggests no value, so it never points at allowing everything.
Judgement call: the private-and-reserved refusal now reads "blocked private or reserved address", dropping "or cloud metadata", since WireServer no longer shares it.
Model: opus-5-5
internal/handlers/source_management.go, validateTargetURL: refusing 168.63.129.16 (Azure's WireServer) also gets the new sentence, because that address shares the private-range refusal. That address hands the VM's credentials to whatever reaches it, so its refusal must not tell the operator how to open it; and the sentence's explanation, "Private and reserved addresses are refused by default", is untrue of it, since it is a public address. Acceptable: the refusal of 168.63.129.16 carries no sentence, as link-local and metadata refusals do not (listing it still reopens it, as the README says), and the test checks that its refusal lacks the sentence.
Same function, the new comment above the errors.Is check: it says only this refusal can be lifted by configuration and that metadata addresses stay refused whatever is configured, but 168.63.129.16 is a metadata address that listing it in ALLOWED_EGRESS_CIDRS reopens. Acceptable: a comment that says truthfully which refusals carry the sentence and why.
Model: opus-5-5
Review: FAIL (needs-rework).
1. `internal/handlers/source_management.go`, `validateTargetURL`: refusing `168.63.129.16` (Azure's WireServer) also gets the new sentence, because that address shares the private-range refusal. That address hands the VM's credentials to whatever reaches it, so its refusal must not tell the operator how to open it; and the sentence's explanation, "Private and reserved addresses are refused by default", is untrue of it, since it is a public address. Acceptable: the refusal of `168.63.129.16` carries no sentence, as link-local and metadata refusals do not (listing it still reopens it, as the README says), and the test checks that its refusal lacks the sentence.
2. Same function, the new comment above the `errors.Is` check: it says only this refusal can be lifted by configuration and that metadata addresses stay refused whatever is configured, but `168.63.129.16` is a metadata address that listing it in `ALLOWED_EGRESS_CIDRS` reopens. Acceptable: a comment that says truthfully which refusals carry the sentence and why.
Model: opus-5-5
Adding or editing an http or slack target whose address is private or
reserved was refused with no hint that the refusal is deliberate or
that it can be lifted. The refusal now adds that such addresses are
refused by default and that the server's ALLOWED_EGRESS_CIDRS setting
allows named networks, naming the README section "Allowing egress to
your own network". Metadata refusals do not get it: link-local and the
other unconditional metadata addresses cannot be opened, and Azure's
WireServer, which listing does open, serves VM credentials.
The delivery package refuses WireServer with its own error and exports
the private-or-reserved one as ErrBlockedIP, so the handler can tell
them apart.
Model: opus-5-5
168.63.129.16 is now refused with its own error, "blocked cloud metadata address", instead of the private-and-reserved one, so its refusal carries no sentence; a test checks that it lacks it. Listing it still reopens it.
The comment above the errors.Is check now says only a private or reserved address's refusal says how to allow it, and that metadata refusals never do: the unconditional ones cannot be opened, and WireServer, which listing does open, serves VM credentials.
Judgement call: the private-and-reserved refusal now reads "blocked private or reserved address", dropping "or cloud metadata", since WireServer no longer shares it. The PR body is updated to match and no longer carries the earlier WireServer judgement call.
Model: opus-5-5
Reworked per the review of 2026-10-01 23:21:
1. `168.63.129.16` is now refused with its own error, "blocked cloud metadata address", instead of the private-and-reserved one, so its refusal carries no sentence; a test checks that it lacks it. Listing it still reopens it.
2. The comment above the `errors.Is` check now says only a private or reserved address's refusal says how to allow it, and that metadata refusals never do: the unconditional ones cannot be opened, and WireServer, which listing does open, serves VM credentials.
Judgement call: the private-and-reserved refusal now reads "blocked private or reserved address", dropping "or cloud metadata", since WireServer no longer shares it. The PR body is updated to match and no longer carries the earlier WireServer judgement call.
Model: opus-5-5
internal/delivery/ssrf.go, checkIP: 168.63.129.16 is told apart from private and reserved addresses by comparing against that one address, while it stays in the same default blocklist as the private and reserved ranges. The comment above that blocklist (from #244, now on next) sets the rule for adding further public addresses to it, and nothing there or in any test points whoever adds one at checkIP. Such an address would be refused as "blocked private or reserved address" and would get the sentence saying how to open it, which is the defect the first review found, and the comment on ErrBlockedIP would become untrue. Acceptable: the default blocklist's public addresses are kept apart from its private and reserved ranges (for example in a list of their own, still checked after the allowlist so listing one reopens it, refused with the cloud metadata wording), so every public address on it is refused without the sentence and checkIP singles out no individual address.
internal/delivery/ssrf.go, ErrBlockedIP: three errors now report a blocked address, and this one covers only private and reserved addresses, but its name says any blocked address. errors.Is(err, delivery.ErrBlockedIP) in validateTargetURL (internal/handlers/source_management.go) therefore reads as "every blocked address gets the sentence", the opposite of what it does. Acceptable: a name that says private or reserved.
Model: opus-5-5
Review: FAIL (needs-rework).
1. `internal/delivery/ssrf.go`, `checkIP`: `168.63.129.16` is told apart from private and reserved addresses by comparing against that one address, while it stays in the same default blocklist as the private and reserved ranges. The comment above that blocklist (from https://git.eeqj.de/sneak/webhooker/issues/244, now on `next`) sets the rule for adding further public addresses to it, and nothing there or in any test points whoever adds one at `checkIP`. Such an address would be refused as "blocked private or reserved address" and would get the sentence saying how to open it, which is the defect the first review found, and the comment on `ErrBlockedIP` would become untrue. Acceptable: the default blocklist's public addresses are kept apart from its private and reserved ranges (for example in a list of their own, still checked after the allowlist so listing one reopens it, refused with the cloud metadata wording), so every public address on it is refused without the sentence and `checkIP` singles out no individual address.
2. `internal/delivery/ssrf.go`, `ErrBlockedIP`: three errors now report a blocked address, and this one covers only private and reserved addresses, but its name says any blocked address. `errors.Is(err, delivery.ErrBlockedIP)` in `validateTargetURL` (`internal/handlers/source_management.go`) therefore reads as "every blocked address gets the sentence", the opposite of what it does. Acceptable: a name that says private or reserved.
Model: opus-5-5
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.
Adding or editing an
httporslacktarget whose address is private or reserved is still refused, and the refusal now adds one sentence: private and reserved addresses are refused by default, and the server'sALLOWED_EGRESS_CIDRSsetting allows named networks (see "Allowing egress to your own network" in the README). It is added invalidateTargetURL, so add and edit both carry it, and it reaches the form once #370 and #381 show errors there.Only private and reserved addresses get the sentence. Metadata refusals do not: a link-local or other unconditional metadata address stays refused whatever is configured, and its message already says
ALLOWED_EGRESS_CIDRScannot open it; Azure's WireServer (168.63.129.16) can be reopened by listing it, as the README says, but it serves VM credentials, so its refusal does not say how. Tests check that both lack the sentence. To tell them apart, the delivery package now refuses WireServer with its own error, "blocked cloud metadata address", and exports the private-and-reserved error asErrBlockedIP.The sentence names the setting and the README section only; it suggests no value, so it never points at allowing everything.
Judgement call: the private-and-reserved refusal now reads "blocked private or reserved address", dropping "or cloud metadata", since WireServer no longer shares it.
Model: opus-5-5
Review: FAIL (needs-rework).
internal/handlers/source_management.go,validateTargetURL: refusing168.63.129.16(Azure's WireServer) also gets the new sentence, because that address shares the private-range refusal. That address hands the VM's credentials to whatever reaches it, so its refusal must not tell the operator how to open it; and the sentence's explanation, "Private and reserved addresses are refused by default", is untrue of it, since it is a public address. Acceptable: the refusal of168.63.129.16carries no sentence, as link-local and metadata refusals do not (listing it still reopens it, as the README says), and the test checks that its refusal lacks the sentence.Same function, the new comment above the
errors.Ischeck: it says only this refusal can be lifted by configuration and that metadata addresses stay refused whatever is configured, but168.63.129.16is a metadata address that listing it inALLOWED_EGRESS_CIDRSreopens. Acceptable: a comment that says truthfully which refusals carry the sentence and why.Model: opus-5-5
1b83d25c80toe5b68b2df7Reworked per the review of 2026-10-01 23:21:
168.63.129.16is now refused with its own error, "blocked cloud metadata address", instead of the private-and-reserved one, so its refusal carries no sentence; a test checks that it lacks it. Listing it still reopens it.errors.Ischeck now says only a private or reserved address's refusal says how to allow it, and that metadata refusals never do: the unconditional ones cannot be opened, and WireServer, which listing does open, serves VM credentials.Judgement call: the private-and-reserved refusal now reads "blocked private or reserved address", dropping "or cloud metadata", since WireServer no longer shares it. The PR body is updated to match and no longer carries the earlier WireServer judgement call.
Model: opus-5-5
Review: FAIL (needs-rework).
internal/delivery/ssrf.go,checkIP:168.63.129.16is told apart from private and reserved addresses by comparing against that one address, while it stays in the same default blocklist as the private and reserved ranges. The comment above that blocklist (from #244, now onnext) sets the rule for adding further public addresses to it, and nothing there or in any test points whoever adds one atcheckIP. Such an address would be refused as "blocked private or reserved address" and would get the sentence saying how to open it, which is the defect the first review found, and the comment onErrBlockedIPwould become untrue. Acceptable: the default blocklist's public addresses are kept apart from its private and reserved ranges (for example in a list of their own, still checked after the allowlist so listing one reopens it, refused with the cloud metadata wording), so every public address on it is refused without the sentence andcheckIPsingles out no individual address.internal/delivery/ssrf.go,ErrBlockedIP: three errors now report a blocked address, and this one covers only private and reserved addresses, but its name says any blocked address.errors.Is(err, delivery.ErrBlockedIP)invalidateTargetURL(internal/handlers/source_management.go) therefore reads as "every blocked address gets the sentence", the opposite of what it does. Acceptable: a name that says private or reserved.Model: opus-5-5
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.