Where: internal/httpfetcher/httpfetcher.go, the built-in blocked ranges and isBlockedIP, on next after #298. Found by the review of #298.
What is wrong:
64:ff9b:1::/48, the local-use NAT64 range (RFC 8215), passes the check that keeps pixa from fetching internal addresses; on a network that runs NAT64 on that range, such an address reaches the IPv4 address it holds, internal ones included.
isBlockedIP matches the operator's blocked_networks list after converting only the ::ffff: mapped form to IPv4, so with 203.0.113.0/24 listed, ::ffff:203.0.113.5 is refused but ::203.0.113.5 is not.
Severity: medium (both weaken the check that blocks fetching addresses pixa must not reach).
Definition of done:
64:ff9b:1::/48 is blocked as 64:ff9b::/96 is.
An address in ::/96 is matched against blocked_networks by the IPv4 address it holds, as the mapped form already is.
Tests first, through both image routes: [64:ff9b:1::a00:1] is refused, and [::203.0.113.5] is refused when blocked_networks lists 203.0.113.0/24; make check green.
Package: internal/httpfetcher.
Model: opus-5-5
Where: `internal/httpfetcher/httpfetcher.go`, the built-in blocked ranges and `isBlockedIP`, on `next` after https://git.eeqj.de/sneak/pixa/pulls/298. Found by the review of https://git.eeqj.de/sneak/pixa/pulls/298.
What is wrong:
- `64:ff9b:1::/48`, the local-use NAT64 range (RFC 8215), passes the check that keeps pixa from fetching internal addresses; on a network that runs NAT64 on that range, such an address reaches the IPv4 address it holds, internal ones included.
- `isBlockedIP` matches the operator's `blocked_networks` list after converting only the `::ffff:` mapped form to IPv4, so with `203.0.113.0/24` listed, `::ffff:203.0.113.5` is refused but `::203.0.113.5` is not.
Severity: medium (both weaken the check that blocks fetching addresses pixa must not reach).
Definition of done:
1. `64:ff9b:1::/48` is blocked as `64:ff9b::/96` is.
2. An address in `::/96` is matched against `blocked_networks` by the IPv4 address it holds, as the mapped form already is.
3. Tests first, through both image routes: `[64:ff9b:1::a00:1]` is refused, and `[::203.0.113.5]` is refused when `blocked_networks` lists `203.0.113.0/24`; `make check` green.
Package: `internal/httpfetcher`.
Model: opus-5-5
clawbot
self-assigned this 2026-10-16 05:32:07 +02:00
Add 64:ff9b:1::/48 to the built-in blocked ranges, beside 64:ff9b::/96.
In isBlockedIP, read an address in ::/96 as the IPv4 address in its last four bytes before matching it against blocked_networks, next to where the ::ffff: mapped form is already unmapped. The code #298 added to isPrivateIP for this moves into one small function that both call, so there is one way of reading it.
Failing tests first, on /v1/image/ with a signature and on an encrypted URL, with the fetcher pixad builds from the config: [64:ff9b:1::a00:1] answers 403; [::203.0.113.5] answers 403 when blocked_networks lists 203.0.113.0/24, and is not refused when the list is empty. No existing test changes.
Model: opus-5-5
Plan:
- Add `64:ff9b:1::/48` to the built-in blocked ranges, beside `64:ff9b::/96`.
- In `isBlockedIP`, read an address in `::/96` as the IPv4 address in its last four bytes before matching it against `blocked_networks`, next to where the `::ffff:` mapped form is already unmapped. The code https://git.eeqj.de/sneak/pixa/pulls/298 added to `isPrivateIP` for this moves into one small function that both call, so there is one way of reading it.
- Failing tests first, on `/v1/image/` with a signature and on an encrypted URL, with the fetcher pixad builds from the config: `[64:ff9b:1::a00:1]` answers 403; `[::203.0.113.5]` answers 403 when `blocked_networks` lists `203.0.113.0/24`, and is not refused when the list is empty. No existing test changes.
Model: opus-5-5
Judgement call: the route test with an empty blocked_networks lets the fetcher try to connect to ::203.0.113.5, since only the connection step checks that list; it checks only that the answer is not 403.
Model: opus-5-5
Built as planned in https://git.eeqj.de/sneak/pixa/pulls/300.
Judgement call: the route test with an empty `blocked_networks` lets the fetcher try to connect to `::203.0.113.5`, since only the connection step checks that list; it checks only that the answer is not 403.
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.
Where:
internal/httpfetcher/httpfetcher.go, the built-in blocked ranges andisBlockedIP, onnextafter #298. Found by the review of #298.What is wrong:
64:ff9b:1::/48, the local-use NAT64 range (RFC 8215), passes the check that keeps pixa from fetching internal addresses; on a network that runs NAT64 on that range, such an address reaches the IPv4 address it holds, internal ones included.isBlockedIPmatches the operator'sblocked_networkslist after converting only the::ffff:mapped form to IPv4, so with203.0.113.0/24listed,::ffff:203.0.113.5is refused but::203.0.113.5is not.Severity: medium (both weaken the check that blocks fetching addresses pixa must not reach).
Definition of done:
64:ff9b:1::/48is blocked as64:ff9b::/96is.::/96is matched againstblocked_networksby the IPv4 address it holds, as the mapped form already is.[64:ff9b:1::a00:1]is refused, and[::203.0.113.5]is refused whenblocked_networkslists203.0.113.0/24;make checkgreen.Package:
internal/httpfetcher.Model: opus-5-5
Plan:
64:ff9b:1::/48to the built-in blocked ranges, beside64:ff9b::/96.isBlockedIP, read an address in::/96as the IPv4 address in its last four bytes before matching it againstblocked_networks, next to where the::ffff:mapped form is already unmapped. The code #298 added toisPrivateIPfor this moves into one small function that both call, so there is one way of reading it./v1/image/with a signature and on an encrypted URL, with the fetcher pixad builds from the config:[64:ff9b:1::a00:1]answers 403;[::203.0.113.5]answers 403 whenblocked_networkslists203.0.113.0/24, and is not refused when the list is empty. No existing test changes.Model: opus-5-5
Built as planned in #300.
Judgement call: the route test with an empty
blocked_networkslets the fetcher try to connect to::203.0.113.5, since only the connection step checks that list; it checks only that the answer is not 403.Model: opus-5-5
clawbot referenced this issue2026-10-16 06:26:33 +02:00