Skip to content

fix: DNS rebinding protection checks AAAA (IPv6) records too#744

Open
Gonzih wants to merge 1 commit intogarrytan:mainfrom
Gonzih:fix/dns-rebinding-ipv6-aaaa
Open

fix: DNS rebinding protection checks AAAA (IPv6) records too#744
Gonzih wants to merge 1 commit intogarrytan:mainfrom
Gonzih:fix/dns-rebinding-ipv6-aaaa

Conversation

@Gonzih
Copy link
Copy Markdown

@Gonzih Gonzih commented Apr 1, 2026

The Gap

`resolvesToBlockedIp()` in `url-validation.ts` only called `resolve4()` (A records). A DNS rebinding attack using AAAA-only records pointing to IPv6 metadata endpoints (e.g. `fe80::1`, GCP's IPv6 metadata endpoint) bypassed the check completely.

Issue #668 documented this. Here's the fix.

Changes

  • Check both `resolve4` and `resolve6` in parallel via `Promise.all`
  • Block the entire `fe80::/10` link-local range (not just one address)
  • Add `::ffff:169.254.169.254` (IPv4-mapped IPv6) to the blocklist
  • Each record family handles its own errors — `ENODATA` on AAAA doesn't suppress the A record check

The DNS calls were already async and run in parallel, so no performance regression.


sent from mStack

resolvesToBlockedIp() was only calling resolve4() — an attacker could
host a DNS entry with only AAAA records pointing to a blocked IPv6
metadata endpoint (fe80::, fd00::, etc.) and bypass the check entirely.

Fix:
- Check both A and AAAA records in parallel (Promise.all)
- Block entire fe80::/10 link-local range, not just a single address
- Add ::ffff:169.254.169.254 (IPv4-mapped IPv6) to the blocklist
- Independent error handling per record family — ENODATA on one type
  doesn't suppress the other

Closes garrytan#668
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.

1 participant