Skip to content

fix(security): block IPv4-compatible IPv6 and NAT64 SSRF bypasses in validateGitUrl#1148

Merged
magyargergo merged 3 commits into
abhigyanpatwari:mainfrom
aaronjmars:security/fix-ipv6-ssrf-bypass
May 4, 2026
Merged

fix(security): block IPv4-compatible IPv6 and NAT64 SSRF bypasses in validateGitUrl#1148
magyargergo merged 3 commits into
abhigyanpatwari:mainfrom
aaronjmars:security/fix-ipv6-ssrf-bypass

Conversation

@aaronjmars

Copy link
Copy Markdown
Contributor

Security Vulnerability Report

Type: SSRF — IPv6 forms that embed IPv4 addresses bypass the private-address blocklist
Severity: High
Location: gitnexus/src/server/git-clone.tsassertNotPrivateIPv6

Description

validateGitUrl() is the gate that protects /api/analyze and the cloneOrPull path from SSRF when a caller supplies a clone URL. It already blocks IPv4-mapped IPv6 (::ffff:127.0.0.1 / ::ffff:7f00:1), but two related forms still slip through and remain routable to the embedded IPv4 on common stacks:

  1. IPv4-compatible IPv6 (RFC 4291 § 2.5.5.1, deprecated form: ::w.x.y.z).
    Node's URL parser collapses http://[::127.0.0.1]/ to hostname ::7f00:1. There is no ::ffff: marker, so the existing :ffff: checks miss it. The Linux kernel and many other stacks still route this to 127.0.0.1.

  2. NAT64 well-known prefix (RFC 6052: 64:ff9b::/96, plus RFC 8215's local 64:ff9b:1::/48).
    On any host with NAT64 resolution enabled, 64:ff9b::7f00:1 translates to 127.0.0.1 and 64:ff9b::a9fe:a9fe translates to 169.254.169.254 (cloud metadata).

Reproduction

Before this patch, all of the following pass validateGitUrl:

validateGitUrl('http://[::127.0.0.1]/repo.git');     // ::7f00:1 — loopback
validateGitUrl('http://[::a9fe:a9fe]/repo.git');     // ::169.254.169.254 — metadata
validateGitUrl('http://[64:ff9b::7f00:1]/repo.git'); // NAT64 → 127.0.0.1
validateGitUrl('http://[64:ff9b:1::1]/repo.git');    // NAT64 local prefix

Any caller that can reach /api/analyze (CORS allows localhost, RFC 1918 LAN, and https://gitnexus.vercel.app) could submit one of these URLs, and on any host with the right kernel/NAT64 config the underlying git clone would attempt to connect to the embedded private IPv4. stderr is suppressed, but timing side-channels and redirect-based probes against the clone target remain viable.

Fix

Extend assertNotPrivateIPv6 with two additional checks:

  • Reject any address compressed to ::xxxx or ::xxxx:yyyy — the only legitimate addresses in that range (::1, ::) are already blocked by the loopback/unspecified checks above, and every remaining value in that compressed range is either IPv4-compatible IPv6 (deprecated, embeds an IPv4 in the last 32 bits) or extremely low-numbered IPv6 that no public host should be hosted on.
  • Reject any address starting with 64:ff9b: (covers RFC 6052 well-known and RFC 8215 local NAT64 prefixes).

Tests

Added cases in gitnexus/test/unit/git-clone.test.ts for IPv4-compatible IPv6 (::127.0.0.1, ::7f00:1, ::a9fe:a9fe) and NAT64 (64:ff9b::7f00:1, 64:ff9b::a9fe:a9fe, 64:ff9b:1::1). Verified manually that legitimate public IPv6 (e.g. 2606:4700:4700::1111, 2001:db8::1) still passes.

Impact

Without this fix, a caller able to submit clone URLs to /api/analyze (or use cloneOrPull directly) can direct git clone at loopback (127.0.0.1) or link-local cloud metadata (169.254.169.254) via IPv6 forms. Combined with the recently fixed ::ffff: IPv4-mapped form, this closes the IPv6-side bypass surface to known-routable embedded-IPv4 representations.


Found by Aeon — automated security scanner

Vulnerability: SSRF via IPv6 forms that embed IPv4 addresses
Severity: high
Location: gitnexus/src/server/git-clone.ts:assertNotPrivateIPv6

validateGitUrl() blocks ::ffff:x.x.x.x (IPv4-mapped) but two related
forms still slipped through — both routable to the embedded IPv4 on
common stacks:

1. IPv4-compatible IPv6 (RFC 4291 § 2.5.5.1, deprecated):
   http://[::127.0.0.1]/  — Node's URL parser collapses this to
   "::7f00:1" with no ::ffff: marker, so the existing check missed it.

2. NAT64 well-known prefix (RFC 6052: 64:ff9b::/96, plus RFC 8215's
   64:ff9b:1::/48 local prefix): a host with NAT64 enabled translates
   64:ff9b::7f00:1 to 127.0.0.1, reaching loopback.

Impact: an attacker who can submit a clone URL to /api/analyze (any
caller in the CORS-allowlisted origin set — localhost, RFC 1918 LAN,
or gitnexus.vercel.app) could direct git clone at loopback or cloud
metadata addresses (169.254.169.254 → ::a9fe:a9fe, 64:ff9b::a9fe:a9fe).

Fix: extend assertNotPrivateIPv6 to reject any address compressed to
::xxxx[:yyyy] and any address starting with the NAT64 prefix
64:ff9b:. Tests added for both forms plus the cloud-metadata variants.
@vercel

vercel Bot commented Apr 28, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the NexusCore Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions

github-actions Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

Claude finished @magyargergo's task in 4m 39s —— View job


Security Review — PR #1148: fix(security): block IPv4-compatible IPv6 and NAT64 SSRF bypasses

Review tasks:

  • Post initial comment
  • Read DoD.md, GUARDRAILS.md and key reference docs
  • Inspect gitnexus/src/server/git-clone.ts (full file)
  • Inspect gitnexus/test/unit/git-clone.test.ts (full file)
  • Verify validateGitUrl() boundary in analyze endpoint and cloneOrPull path
  • Check CI status
  • Analyze IPv4-compatible IPv6 regex correctness (expanded form risk)
  • Analyze NAT64 startsWith precision
  • Assess existing IPv6 private-range coverage (6to4, Teredo gaps)
  • Assess public IPv6 false-positive risk
  • Assess test coverage completeness
  • Evaluate error behavior and SSRF completeness
  • Produce structured findings and final verdict

Review bar for this PR

  • validateGitUrl() blocks IPv4-compatible IPv6 forms that embed private IPv4 addresses
  • validateGitUrl() blocks NAT64 addresses that can map to loopback, link-local, RFC1918, multicast, or otherwise private IPv4 ranges
  • Existing IPv4, IPv4-mapped IPv6, loopback, link-local, unique-local, multicast, and unspecified checks remain intact and unregressed
  • Legitimate public IPv4 and public IPv6 clone URLs continue to pass (verified by tests)
  • Tests cover normalized, compressed, expanded, and mixed IPv6 spellings where Node accepts them
  • The implementation is explicit, maintainable, and does not over-block unrelated public IPv6 ranges without justification
  • The /api/analyze and cloneOrPull URL validation boundary remains correctly enforced
  • CI, typecheck, and focused security tests are green before approval

Issue and PR context considered

  • SSRF bypass class: IPv4-compatible IPv6 (::w.x.y.z / ::/96) and NAT64 (64:ff9b::/96, 64:ff9b:1::/48) — both carry private IPv4 addresses in their last 32 bits and route to them on common network stacks/kernels, but neither contains the ::ffff: marker caught by the existing IPv4-mapped check.
  • Affected function: assertNotPrivateIPv6() in gitnexus/src/server/git-clone.ts, called by validateGitUrl().
  • Changed files: gitnexus/src/server/git-clone.ts (+17 lines), gitnexus/test/unit/git-clone.test.ts (+19 lines).
  • CI status: Pending/in-progress. "CI" and "Docker Build & Push" workflows are still running as of this review. Merge is blocked until both complete green.
  • Scope: Strictly limited to literal IPv6 host forms in user-supplied clone URLs. DNS, redirect, and scp-syntax SSRF classes are explicitly out of scope for this PR.

Understanding of the change

The existing assertNotPrivateIPv6() already blocked IPv4-mapped addresses (::ffff:x.x.x.x) by checking for the ::ffff: prefix. Two closely related forms lacked coverage:

  1. IPv4-compatible (::w.x.y.z, RFC 4291 § 2.5.5.1 — deprecated). Node's WHATWG URL parser normalizes http://[::127.0.0.1]/ to hostname ::7f00:1. There is no ::ffff: marker, so the existing prefix check misses it. Linux and many other stacks still route ::7f00:1 to 127.0.0.1.

  2. NAT64 (RFC 6052 64:ff9b::/96, RFC 8215 64:ff9b:1::/48). A host with NAT64 resolves 64:ff9b::7f00:1 to 127.0.0.1 and 64:ff9b::a9fe:a9fe to 169.254.169.254. This would allow silent probing of loopback and cloud metadata endpoints via git clone.

The fix adds two checks inside assertNotPrivateIPv6():

  • A regex /^::[0-9a-f]{1,4}(:[0-9a-f]{1,4})?$/ matching the compressed forms Node emits after parsing IPv4-compatible addresses.
  • A startsWith('64:ff9b:') prefix check covering both NAT64 RFC ranges.

validateGitUrl() sits at the entry to cloneOrPull(), which is the only path from the /api/analyze endpoint to an actual git clone using a user-supplied URL.


Findings

[high] Expanded IPv4-compatible IPv6 forms have no test coverage confirming Node normalization

  • Category: Test coverage / correctness assumption

  • Files: gitnexus/test/unit/git-clone.test.ts

  • Issue: The regex /^::[0-9a-f]{1,4}(:[0-9a-f]{1,4})?$/ correctly matches the compressed forms Node emits (::7f00:1), but relies entirely on the WHATWG URL parser normalizing expanded inputs before the check is applied. The following inputs are not tested:

    • http://[0:0:0:0:0:0:7f00:1]/repo.git (expanded zero-padded hex groups)
    • http://[0000:0000:0000:0000:0000:0000:7f00:0001]/repo.git (fully zero-padded)
    • http://[0:0:0:0:0:0:127.0.0.1]/repo.git (expanded mixed notation)

    The WHATWG URL specification mandates compressed serialization, and the PR description demonstrates that ::127.0.0.1 normalizes correctly. However, without tests for the expanded variants, any future Node version anomaly would silently regress. For a security-sensitive URL parser, the assumption must be verified, not implied.

  • Why it matters here: git clone accepts a broader range of URL forms than the Node URL parser may normalize uniformly. If an expanded form is not compressed to ::xxxx:yyyy by new URL(), it passes the regex and reaches git clone intact.

  • Recommended fix: Add three test cases asserting that expanded inputs throw private/internal:

    expect(() => validateGitUrl('http://[0:0:0:0:0:0:7f00:1]/repo.git')).toThrow('private/internal');
    expect(() => validateGitUrl('http://[0000:0000:0000:0000:0000:0000:7f00:0001]/repo.git')).toThrow('private/internal');
    expect(() => validateGitUrl('http://[0:0:0:0:0:0:127.0.0.1]/repo.git')).toThrow('private/internal');

    If any of these fail, it reveals a genuine bypass that requires fallback logic (e.g. segment-level CIDR check for ::/96). Fix this →

  • Blocks merge: Yes — without these tests, there is no evidence the expanded bypass path is actually closed.


[high] 6to4 (2002::/16) and Teredo (2001::/32) embed IPv4 and are not blocked

  • Category: SSRF coverage gap (pre-existing, not introduced by this PR)

  • Files: gitnexus/src/server/git-clone.ts

  • Issue: Two additional IPv6 transition mechanisms embed private IPv4 addresses and are currently unblocked:

    • 6to4 (2002::/16): 2002:7f00:0001::1 encodes 127.0.0.1 in bits 17–48. Routable to the embedded IPv4 on 6to4-capable stacks.
    • Teredo (2001::/32): Encodes the IPv4 address (obfuscated by XOR) in the last 32 bits.

    These were not blocked before this PR and remain unblocked after it. This PR does not claim to address all IPv6 bypass classes, so this is a pre-existing gap rather than a regression.

  • Why it matters here: The PR description states this "closes the IPv6-side bypass surface to known-routable embedded-IPv4 representations," but 6to4 is a known embedded-IPv4 form. The claim of closing the surface is therefore overstated. On 6to4-capable hosts (common in data centers), http://[2002:7f00:0001::1]/repo.git would still pass validateGitUrl.

  • Recommended fix: Either:

    1. Add lower.startsWith('2002:') to assertNotPrivateIPv6() to block 6to4 (Teredo is harder to block precisely due to XOR obfuscation). This makes the PR description accurate. Fix this →
    2. Or update the PR description to explicitly document 6to4/Teredo as out of scope and file a follow-up issue.
  • Blocks merge: No if explicitly documented as out of scope with a follow-up filed. Yes if the PR description claims full closure of IPv6-embedded-IPv4 bypass surface.


[medium] No public IPv6 positive test — false-positive risk unverified

  • Category: Test coverage

  • Files: gitnexus/test/unit/git-clone.test.ts

  • Issue: The "does not block valid public IPs" test only covers 140.82.121.4 (IPv4). No test asserts that a real public IPv6 address passes:

    • https://[2606:4700:4700::1111]/repo.git (Cloudflare DNS)
    • https://[2001:4860:4860::8888]/repo.git (Google DNS)

    While the logic is correct (these addresses don't match ::xxxx or 64:ff9b: patterns), the absence of a positive test means there is no regression guard if the checks are widened in a future refactor. For security validation, false positives (blocking legitimate public repos) matter as much as false negatives.

  • Why it matters here: A user cloning from a GitHub-alternative hosted on IPv6-only infrastructure would silently fail. Without a test, no CI run would catch it.

  • Recommended fix: Add to the "does not block valid public IPs" test:

    expect(() => validateGitUrl('https://[2606:4700:4700::1111]/repo.git')).not.toThrow();
    expect(() => validateGitUrl('https://[2001:4860:4860::8888]/repo.git')).not.toThrow();

    Fix this →

  • Blocks merge: No, but strongly recommended before approval.


[medium] NAT64 check is broader than the two cited RFC ranges without justification comment

  • Category: Maintainability / precision
  • Files: gitnexus/src/server/git-clone.ts:156
  • Issue: lower.startsWith('64:ff9b:') will block anything starting with 64:ff9b:, which extends beyond the two RFC-specified ranges to hypothetical future assignments like 64:ff9b:2::1, 64:ff9b:abcd::1, etc. The code comment cites RFC 6052 and RFC 8215 but does not explain why the broader prefix is intentionally blocked. A future reviewer who looks up only those RFCs will see a mismatch. IANA currently shows 64:ff9b::/32 as reserved for translation use cases, so broad blocking is defensively sound — but this should be stated.
  • Why it matters here: An uninformed change that narrows the check to strict CIDR matching (64:ff9b::/96 only) would silently re-open the 64:ff9b:1:: bypass.
  • Recommended fix: Extend the comment: // The entire 64:ff9b::/32 block is IANA-reserved for translation (RFC 6052, RFC 8215, and future use); broad prefix blocking is intentionally conservative.
  • Blocks merge: No.

[medium] CI is still pending — merge is blocked

  • Category: Validation
  • Files: CI workflows
  • Issue: Both the "CI" workflow and "Docker Build & Push" are in_progress as of this review. Typecheck, unit tests, and the focused security test command have not completed on the PR head.
  • Why it matters here: DoD §4.2 requires npx tsc --noEmit and npm test to pass. The new regex and NAT64 check could have a TypeScript type error, test collision, or unexpected test failure that is only visible after CI completes.
  • Recommended fix: Wait for CI to complete green on the current head (bcd3cc1).
  • Blocks merge: Yes.

[medium] Missing NAT64 RFC1918 embedded-IP test variants

  • Category: Test coverage
  • Files: gitnexus/test/unit/git-clone.test.ts
  • Issue: The NAT64 test block only covers 127.0.0.1 and 169.254.169.254 as embedded addresses. RFC 1918 ranges embedded via NAT64 (10.0.0.164:ff9b::a00:1, 172.16.0.164:ff9b::ac10:1, 192.168.1.164:ff9b::c0a8:101) are untested. The check is a prefix match so these are logically covered, but tests are missing.
  • Why it matters here: An SSRF fix that covers only the most visible examples (loopback, metadata) and not the RFC1918 range provides incomplete assurance for a security reviewer.
  • Recommended fix: Add:
    expect(() => validateGitUrl('http://[64:ff9b::a00:1]/repo.git')).toThrow('private/internal');    // 10.0.0.1
    expect(() => validateGitUrl('http://[64:ff9b::ac10:1]/repo.git')).toThrow('private/internal');   // 172.16.0.1
    expect(() => validateGitUrl('http://[64:ff9b::c0a8:101]/repo.git')).toThrow('private/internal'); // 192.168.1.1
  • Blocks merge: No, but expected for a complete security fix.

Definition of Done check

DoD item Status
validateGitUrl() blocks IPv4-compatible IPv6 forms that embed private IPv4 addresses partially satisfied — compressed forms blocked; expanded forms untested
validateGitUrl() blocks NAT64 addresses that can map to loopback, link-local, RFC1918 partially satisfied — check correct; RFC1918 embedded variants untested
Existing IPv4, IPv4-mapped IPv6, loopback, link-local, unique-local, multicast, unspecified checks remain intact satisfied — no regressions observed
Legitimate public IPv4 and public IPv6 clone URLs continue to pass partially satisfied — logic is correct; no public IPv6 positive test
Tests cover normalized, compressed, expanded, and mixed IPv6 spellings not satisfied — only compressed forms tested; no expanded/padded/mixed tests
Implementation is explicit, maintainable, does not over-block without justification partially satisfied — NAT64 prefix breadth needs a comment
/api/analyze and cloneOrPull URL validation boundary correctly enforced satisfiedvalidateGitUrl is called inside cloneOrPull before first clone; pull path uses stored remote, not re-supplied URL
CI, typecheck, and focused security tests green before approval not satisfied — CI in progress

SSRF validation assessment

IPv4-compatible IPv6 handling: The regex /^::[0-9a-f]{1,4}(:[0-9a-f]{1,4})?$/ correctly blocks compressed Node-normalized forms. Its correctness for expanded inputs depends on WHATWG URL normalization, which the spec mandates but tests do not confirm.

NAT64 handling: startsWith('64:ff9b:') is correct for all currently assigned NAT64 ranges and is defensively broad for the unassigned rest of 64:ff9b::/32. The RFC citation in the comment should be extended to explain the intentional breadth.

Existing private IPv4/IPv6 handling: Loopback, unspecified, ULA (fc/fd), link-local (fe80feb), IPv4-mapped (::ffff:), and expanded mapped (0:0:0:0:0:ffff:) forms all remain blocked and are unmodified by this PR.

Public IPv6 false-positive behavior: Logically correct — public IPv6 (e.g. 2606:4700:4700::1111) does not match any block pattern. Not test-verified.

Redirect/DNS scope: Not addressed. validateGitUrl() only checks the literal host in the supplied URL. DNS rebinding, DNS resolution to private IPs, and HTTP redirects from public to private hosts are existing limitations not in scope for this PR. This is acceptable for a literal-IP fix, but it means the overall SSRF posture is defense-in-depth, not complete.

Validation boundary for /api/analyze and cloneOrPull:

  • POST /api/analyzecloneOrPull(repoUrl, targetPath)validateGitUrl(url) (only on first clone). Confirmed correct.
  • On subsequent git pull, validateGitUrl is not re-called. git pull --ff-only uses the remote URL from .git/config, which was validated at clone time. The user-supplied repoUrl does not control the pull destination. Not an SSRF bypass in the current architecture.
  • Unblocked gap (pre-existing): 6to4 addresses (2002::/16) embed IPv4 and are not caught by any existing or new check.

Test assessment

Tests added:

  • IPv4-compatible: ::127.0.0.1 (mixed notation), ::7f00:1 (hex), ::a9fe:a9fe (cloud metadata)
  • NAT64: 64:ff9b::7f00:1, 64:ff9b::a9fe:a9fe, 64:ff9b:1::1

Missing variants:

  • Expanded IPv4-compatible: [0:0:0:0:0:0:7f00:1], [0000:0000:0000:0000:0000:0000:7f00:0001], [0:0:0:0:0:0:127.0.0.1] — absence means expanded bypass is unconfirmed
  • NAT64 with RFC1918 embedded addresses: 64:ff9b::a00:1, 64:ff9b::ac10:1, 64:ff9b::c0a8:101
  • Zero-byte compressed form: [::2], [::a] (to confirm the regex correctly blocks low-numbered addresses)

Positive public-IP tests: Only 140.82.121.4 (IPv4). No public IPv6 positive test.

Regression coverage: Existing tests for all prior block categories are present and unmodified. New tests would fail before the patch (the patterns they test only throw due to the new checks).

Would tests fail before the patch? Yes — the three new it blocks would fail without the added regex and NAT64 check.


Validation assessment

  • CI status: "CI" and "Docker Build & Push" workflows are in_progress for PR head bcd3cc1. Typecheck and unit tests not yet confirmed green.
  • Focused test command: cd gitnexus && npx vitest run test/unit/git-clone.test.ts — not run in this review (CI pending).
  • Typecheck: Not confirmed (npx tsc --noEmit not run).
  • Anything not verified: Expanded IPv6 normalization behavior (requires running Node); CI results.
  • Pending CI blocks approval: Yes, per DoD §4.2 and review instructions.

Final verdict

not production-ready

CI is still in-progress, which is an unconditional merge blocker per both the DoD and the explicit instructions for this review. Beyond CI, the PR does not include tests for expanded IPv4-compatible IPv6 forms (0:0:0:0:0:0:7f00:1, zero-padded), leaving the core correctness assumption about WHATWG URL normalization unverified by tests — for a security-sensitive parser fix this is insufficient. There is also no positive test confirming legitimate public IPv6 clone URLs are unaffected. Finally, the 6to4 gap (2002::/16) is a known IPv4-embedding mechanism that the PR description implies is covered but is not. The core logic (regex + NAT64 prefix) is directionally correct and the compressed forms are properly blocked; the PR needs test additions and CI green before it clears the DoD bar.


· PR branch

@magyargergo

Copy link
Copy Markdown
Collaborator

@aaronjmars Can you please look into these findings? 🙏

@github-actions

github-actions Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

CI Report

All checks passed

Pipeline Status

Stage Status Details
✅ Typecheck success tsc --noEmit
✅ Tests success unit tests, 3 platforms
✅ E2E success gitnexus-web changes only

Test Results

Tests Passed Failed Skipped Duration
7801 7800 0 1 348s

✅ All 7800 tests passed

1 test(s) skipped — expand for details
  • buildTypeEnv > known limitations (documented skip tests) > Ruby block parameter: users.each { |user| } — closure param inference, different feature

Code Coverage

Tests

Metric Coverage Covered Base Delta Status
Statements 77.27% 23090/29879 77.02% 📈 +0.2 🟢 ███████████████░░░░░
Branches 66.14% 14797/22370 65.97% 📈 +0.2 🟢 █████████████░░░░░░░
Functions 82.31% 2271/2759 81.86% 📈 +0.5 🟢 ████████████████░░░░
Lines 80.16% 20835/25989 79.89% 📈 +0.3 🟢 ████████████████░░░░

📋 View full run · Generated by CI

…n tests

Address review findings on PR #1148:

- Block 6to4 (2002::/16, RFC 3056). The prefix encodes an IPv4 address in
  bits 17-48, so 2002:7f00:0001::* routes to 127.0.0.1 on 6to4-capable
  stacks. RFC 7526 deprecated the protocol and the public relay anycast
  has been retired, so broad-blocking has near-zero false-positive cost.

- Expand the NAT64 comment to justify the broader-than-CIDR check: the
  whole 64:ff9b::/32 block is IANA-reserved for IPv4-IPv6 translation, so
  a future narrower CIDR refactor would silently re-open the bypass for
  64:ff9b:1::/48 or any new translation range.

- Add tests for expanded / zero-padded IPv4-compatible IPv6 forms
  ([0:0:0:0:0:0:7f00:1], fully zero-padded, mixed [0:...:127.0.0.1]).
  These pin the assumption that the WHATWG URL parser collapses these
  inputs to ::xxxx[:yyyy]; without them, a future Node anomaly would
  silently regress the bypass.

- Add public IPv6 positive tests (Cloudflare 2606:4700::, Google
  2001:4860::). Regression guard against over-blocking.

- Add NAT64 + RFC1918 embedded-IP tests (10/8, 172.16/12, 192.168/16) to
  document SSRF coverage explicitly rather than relying on the prefix
  check.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@aaronjmars

Copy link
Copy Markdown
Contributor Author

@magyargergo Thanks for the review — pushed bffc4c8 addressing the findings:

Source (gitnexus/src/server/git-clone.ts):

  • 6to4 (2002::/16) now blocked. RFC 3056 encodes IPv4 in bits 17-48, so 2002:7f00:1::1 routes to 127.0.0.1 on 6to4-capable stacks. RFC 7526 deprecated the protocol and the relay anycast (192.88.99.1) has been retired, so broad-blocking has near-zero false-positive cost. Teredo (2001::/32) is left out — XOR-obfuscated IPv4 is impractical to block precisely; documented as out of scope in the source comment.
  • NAT64 prefix breadth now justified inline: the whole 64:ff9b::/32 block is IANA-reserved for IPv4-IPv6 translation, so the broader check (vs. strict CIDR) prevents a future refactor from silently re-opening the bypass for 64:ff9b:1::/48 or any new translation range.

Tests (gitnexus/test/unit/git-clone.test.ts):

  • Expanded / zero-padded IPv4-compatible IPv6[0:0:0:0:0:0:7f00:1], [0000:0000:0000:0000:0000:0000:7f00:0001], mixed [0:0:0:0:0:0:127.0.0.1]. Pins the WHATWG URL normalisation assumption.
  • Public IPv6 positive tests2606:4700:4700::1111 (Cloudflare DNS) and 2001:4860:4860::8888 (Google DNS). Regression guard against over-blocking.
  • NAT64 + RFC1918 embedded10.0.0.1, 172.16.0.1, 192.168.1.1 mappings. Documents the full private-IPv4 surface explicitly.
  • 6to4 block — three cases covering 127.0.0.1, 169.254.169.254, 192.168.1.1 mappings.

29/29 unit tests passing locally; tsc --noEmit clean.

@magyargergo magyargergo merged commit 9581484 into abhigyanpatwari:main May 4, 2026
18 of 19 checks passed
@magyargergo magyargergo mentioned this pull request May 10, 2026
4 tasks
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