fix(ssrf): block NAT64 and IPv4-compatible IPv6 literals - #7
Conversation
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 3 included reviews per hour; 1 remains after this review. 📝 WalkthroughWalkthroughIPv6 SSRF validation now parses compressed and embedded forms, applies declarative CIDR rules, blocks invalid addresses, and delegates embedded IPv4 checks to existing IPv4 logic. Tests cover additional blocked ranges and public IPv4 embeddings. ChangesIPv6 SSRF validation
Estimated code review effort: 3 (Moderate) | ~25 minutes Merge Risk: ⚪ Minimal · up to The change blocks additional IPv6 forms that could reach restricted IPv4 destinations while preserving allowed public destinations; no actionable merge-blocking risk remains after normal checks and review. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Summary
Fixes an SSRF blocklist gap:
isBlockedV6decoded embedded IPv4 only for the::ffff:prefix, so NAT64 (64:ff9b::/96) and deprecated IPv4-compatible (::a.b.c.d) literals likehttp://[64:ff9b::7f00:1]passed the guard and — on networks with NAT64/DNS64 translation — could reach internal IPv4 addresses (e.g. 127.0.0.1) that the IPv4 blocklist would refuse.Replaced the ad-hoc regex checks with a canonical parse-then-match approach:
parseV6expands any IPv6 literal (including::compression and trailing dotted-quad) into 8 16-bit words; unparseable input is treated as blocked.BLOCKED_V6_RULESis a CIDR-based blocklist over those words, keeping all previously blocked ranges and adding::/96(IPv4-compatible),64:ff9b::/96(NAT64 well-known),64:ff9b:1::/48(NAT64 local-use), and100::/64(discard-only).embeddedV4: true(::/96,::ffff:0:0/96,64:ff9b::/96) map the embedded IPv4 from the last 32 bits back throughisBlockedV4, so private/reserved embedded addresses are rejected while public ones (e.g.64:ff9b::8.8.8.8) remain allowed.Tests extended with reject cases (
64:ff9b::7f00:1,64:ff9b::127.0.0.1,::127.0.0.1,::7f00:1,::ffff:7f00:1,64:ff9b:1::1,100::1) and public-embedded allow cases.Remediates finding sfind-b7e6add3e60c41d3b096f3c47be16752.
Link to Devin session: https://app.devin.ai/sessions/6206628cc75144ce9f5d3f2c98f05ddd
Requested by: @tinkthemaker
Summary by CodeRabbit