Skip to content

🛡️ fix: Cover full fe80::/10 link-local range in IPv6 check#12244

Merged
danny-avila merged 3 commits into
devfrom
fix/ipv6-linklocal-range
Mar 15, 2026
Merged

🛡️ fix: Cover full fe80::/10 link-local range in IPv6 check#12244
danny-avila merged 3 commits into
devfrom
fix/ipv6-linklocal-range

Conversation

@danny-avila

Copy link
Copy Markdown
Owner

The isPrivateIP check used startsWith('fe80') which only matched fe80:: but missed fe90::–febf:: (the rest of the RFC 4291 fe80::/10 link-local block). Replace with a proper bitwise hextet check.

The `isPrivateIP` check used `startsWith('fe80')` which only matched
fe80:: but missed fe90::–febf:: (the rest of the RFC 4291 fe80::/10
link-local block). Replace with a proper bitwise hextet check.
Copilot AI review requested due to automatic review settings March 15, 2026 20:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR tightens SSRF protection by correctly detecting the full IPv6 link-local range fe80::/10 (RFC 4291) instead of only matching fe80:: via string prefix.

Changes:

  • Added a dedicated helper to detect fe80::/10 via a bitmask on the first hextet.
  • Updated isPrivateIP() to use the new helper for IPv6 link-local detection.
  • Expanded Jest coverage to include fe90febf and the fec0 boundary case for both isSSRFTarget() and isPrivateIP().

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
packages/api/src/auth/domain.ts Replaces startsWith('fe80') with a bitmask-based fe80::/10 link-local check.
packages/api/src/auth/domain.spec.ts Adds tests to ensure the full fe80::/10 range is blocked and validates boundary behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread packages/api/src/auth/domain.ts
Comment thread packages/api/src/auth/domain.spec.ts
…ames

parseInt('fe90.example.com', 16) stops at the dot and returns 0xfe90,
which passes the bitmask check and false-positives legitimate domains.

Add colon-presence guard (IPv6 literals always contain ':') and a hex
regex validation on the first hextet before parseInt.

Also document why fc/fd use startsWith while fe80::/10 needs bitwise.
- Assert fe90/fea0/febf hostnames are NOT blocked (regression guard)
- Add feb0::1 and bracket form [fe90::1] to isPrivateIP coverage
- Extend resolveHostnameSSRF tests for fe90::1 and febf::1
@danny-avila danny-avila force-pushed the fix/ipv6-linklocal-range branch from 439274e to aae6763 Compare March 15, 2026 20:52
@danny-avila danny-avila changed the title 🛡️ fix: Cover full fe80::/10 link-local range in SSRF IPv6 check 🛡️ fix: Cover full fe80::/10 link-local range in IPv6 check Mar 15, 2026
@danny-avila danny-avila merged commit a0b4949 into dev Mar 15, 2026
7 checks passed
@danny-avila danny-avila deleted the fix/ipv6-linklocal-range branch March 15, 2026 21:07
jcbartle pushed a commit to jcbartle/LibreChat that referenced this pull request May 11, 2026
…ila#12244)

* 🛡️ fix: Cover full fe80::/10 link-local range in SSRF IPv6 check

The `isPrivateIP` check used `startsWith('fe80')` which only matched
fe80:: but missed fe90::–febf:: (the rest of the RFC 4291 fe80::/10
link-local block). Replace with a proper bitwise hextet check.

* 🛡️ fix: Guard isIPv6LinkLocal against parseInt partial-parse on hostnames

parseInt('fe90.example.com', 16) stops at the dot and returns 0xfe90,
which passes the bitmask check and false-positives legitimate domains.

Add colon-presence guard (IPv6 literals always contain ':') and a hex
regex validation on the first hextet before parseInt.

Also document why fc/fd use startsWith while fe80::/10 needs bitwise.

* ✅ test: Harden IPv6 link-local SSRF tests with false-positive guards

- Assert fe90/fea0/febf hostnames are NOT blocked (regression guard)
- Add feb0::1 and bracket form [fe90::1] to isPrivateIP coverage
- Extend resolveHostnameSSRF tests for fe90::1 and febf::1
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