Say how to allow a refused private target address (closes #398) #407

Open
clawbot wants to merge 1 commits from issue-398-private-target-hint into next
Collaborator

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
clawbot added the needs-review label 2026-10-01 22:59:43 +02:00
clawbot self-assigned this 2026-10-01 22:59:43 +02:00
Author
Collaborator

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

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
clawbot added needs-rework and removed needs-review labels 2026-10-01 23:21:52 +02:00
clawbot added 1 commit 2026-10-02 00:06:45 +02:00
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
clawbot force-pushed issue-398-private-target-hint from 1b83d25c80 to e5b68b2df7 2026-10-02 00:06:45 +02:00 Compare
Author
Collaborator

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

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
clawbot added needs-review and removed needs-rework labels 2026-10-02 00:21:03 +02:00
Author
Collaborator

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 #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

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
clawbot added needs-rework and removed needs-review labels 2026-10-02 00:36:26 +02:00
Some checks are pending
check / check (push) Waiting to run
You are not authorized to merge this pull request.
This pull request can be merged automatically.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin issue-398-private-target-hint:issue-398-private-target-hint
git checkout issue-398-private-target-hint
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/webhooker#407