Skip to content

Check each address family only against its own allowed ranges - #1240

Merged
nedtwigg merged 4 commits into
mainfrom
local-networks-family-blocklist
Oct 20, 2026
Merged

nedtwigg merged 4 commits into
mainfrom
local-networks-family-blocklist

Conversation

@nedtwigg

Copy link
Copy Markdown
Member

Hardening for the Local networks address check.

Node's BlockList matches an IPv4 address against an IPv6 subnet that covers ::ffff:0:0/96, even when asked to check it as 'ipv4'. allowedAddressTest kept both families in one list, so an allowed IPv6 range such as ::/0, ::/64, or ::ffff:0:0/96 (all of which canonicalCidr and the Settings Add box accept) also admitted every IPv4 address: the Burrow's answer and the phone's offer kept IPv4 candidates outside the allowed networks, and the selected-pair check allowed an IPv4 pair.

  • allowedAddressTest in lib/src/host/remote/network-interfaces.ts now keeps one BlockList per family. An IPv4 address is checked only against the IPv4 ranges, an IPv4-mapped IPv6 address (::ffff:a.b.c.d, however spelled) is unwrapped and checked as that IPv4 address, and any other IPv6 address only against the IPv6 ranges. This mirrors the Relay's push-endpoint check in relay/src/push-endpoint.ts.
  • Every caller goes through this one helper: the strip and the pair check in localNetworksPath, the single-address bind, the private-range test for the reported address, and the interface classifier's tailnet and link-local tests. Their results for ranges of the matching family are unchanged.

Tests

  • lib/src/host/remote/network-interfaces.test.ts → "allowedAddressTest": with ::/0, ::/1, ::/64, ::ffff:0:0/96, or ::ffff:808:0/120 allowed, neither 8.8.8.8 nor ::ffff:8.8.8.8 is admitted; an IPv6 range still admits its IPv6, and an IPv4 range beside it still admits a mapped address inside it.
  • lib/src/host/remote/local-networks.test.ts: under ::/0 or ::ffff:0:0/96, the offer and the answer keep no IPv4 candidate and the pair check refuses an IPv4 pair, plain or mapped.

Both go red with the helper reverted.

Specs

  • docs/specs/remote-network.md → "Local networks": each end is checked against allowed CIDRs of its own family, a mapped address as its IPv4 (rationale added).
  • docs/specs/security-remote.md → "Direct path": S272 widened to require the per-family check in allowedAddressTest (word budget ratcheted).
  • New canary seed .github/audit/canaries/local-networks-mixed-family-blocklist.patch (Rule: S272).

This PR touches .github/, so the owner merges it.

🤖 Generated with Claude Code

nedtwigg and others added 3 commits October 20, 2026 08:15
Node's BlockList matches an IPv4 address against an IPv6 subnet covering
::ffff:0:0/96 even when asked to check it as IPv4, so one list holding both
families let an allowed ::/0, ::/64, or ::ffff:0:0/96 admit every IPv4
address under Local networks. allowedAddressTest now keeps one list per
family and checks an IPv4-mapped IPv6 address as the IPv4 address it carries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e list

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Deploying mouseterm with  Cloudflare Pages  Cloudflare Pages

Latest commit: 960540a
Status: ✅  Deploy successful!
Preview URL: https://5a501ea5.mouseterm.pages.dev
Branch Preview URL: https://local-networks-family-blockl.mouseterm.pages.dev

View logs

@dormouse-bot dormouse-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No findings on the diff. Splitting the BlockList by family and unwrapping mapped addresses closes the ::/0 → IPv4 admission. I reproduced the cross-family match on Node 22.23 as well. The callers' existing ranges (isPrivateAddress, the tailnet and link-local tests) give the same results.

I'm holding approval only because two checks on this head are red, neither from this change:

  • Workflow Lint: zizmor flags ci.yml:403 ("hash pin has mismatched or missing version comment"). This PR doesn't touch that file, and the latest main run of the workflow fails too.
  • Standalone Platform Check (windows-latest): browser-launch-env.test.ts › "runs native PowerShell startup code and exits" hit ETIMEDOUT. That's the intermittent hang tracked in #839, and an earlier run on this branch passed it.

@nedtwigg
nedtwigg merged commit d5435aa into main Oct 20, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants