fix(traits): match RFC 9637 documentation /20 in is_public_ipv6#917
fix(traits): match RFC 9637 documentation /20 in is_public_ipv6#917singhlovepreet9 wants to merge 1 commit into
Conversation
The 3fff::/20 documentation guard masked the first hextet with 0xfff0, which matches every first hextet in 0x3ff0..=0x3fff regardless of the second hextet. That covers 3ff0::/16 through 3fff::/16 rather than the intended 3fff::/20, so global-unicast space (3ff0:: through 3ffe::, and 3fff:: past the /20 boundary) is classified as non-routable. The avatar-URL and encrypted-media SSRF validators (reject_non_routable_ipv6) then wrongly reject those legitimately-routable hosts. Match the actual /20 instead: first hextet 0x3fff with the top nibble of the second hextet zero. The guard still fails closed for the real documentation block and never newly accepts a non-routable address.
|
Ready to review this PR? Stage has broken it down into 3 individual chapters for you:
Chapters generated by Stage for commit 56a5074 on Jul 18, 2026 2:13am UTC. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
WalkthroughThe IPv6 classifier now identifies RFC 9637’s ChangesIPv6 documentation-range classification
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Fixes #913
Problem
is_public_ipv6mis-classifies a large slice of global-unicast space as non-routable. The guard meant to exclude the RFC 9637 documentation range3fff::/20was written as:0xfff0masks off only the low nibble of the first hextet, so the condition matches every first hextet in0x3ff0..=0x3fff— i.e.3ff0::/16through3fff::/16— regardless of the second hextet, instead of the intended3fff::/20.Root cause
3fff::/20fixes the full first hextet (0x3fff) plus the top nibble of the second hextet. The masked comparison collapses that to "first hextet in0x3ff0..=0x3fff", over-rejecting:3ff0::through3ffe::(entire hextets of ordinary global unicast), and3fff::addresses past the/20boundary (second hextet>= 0x1000).All of these are inside global-unicast
2000::/3, sois_public_ipv6returnsfalseand the avatar-URL / encrypted-media SSRF validators (reject_non_routable_ipv6) wrongly reject legitimately-routable hosts. It fails closed (no SSRF exposure), but it is a concrete deviation from the stated RFC and the code comment, latent until IANA allocates3xxx::to the RIRs.Fix
Match the actual
/20: first hextet0x3fffwith the top nibble of the second hextet zero.The guard still fails closed for the real documentation block and never newly accepts a non-routable address.
Verification
Toolchain pinned
1.90.0;justisn't installed locally so the equivalent cargo gates were run directly.Added regression coverage in
tests/host_safety_public.rslocking both edges of the/20:3ff0::1,3ffe::1,3fff:1000::1,3fff:ffff::13fff::1(lower edge) and3fff:0fff::1(upper edge)The one existing assertion that depended on the buggy mask —
3fff:ffff::1ingroup_avatar_url_rejects_documentation_ipv6_ranges(it is not documentation space) — was replaced with3fff:0fff::1, a genuine in-range documentation address, so that test keeps asserting exactly what its name says.Scope / risk
Three files, all in
crates/traits. No previously-public address becomes rejected; the change only stops rejecting genuinely-routable space, so there is no new SSRF surface and no public-API change.Summary by CodeRabbit
3fff:0000::/20while accepting adjacent global-unicast ranges.