Skip to content

fix: close SSRF IPv6 bypass and replace Math.random() session IDs with crypto.randomUUID()#1

Merged
HugoWong528 merged 1 commit intomainfrom
copilot/check-data-security-issues
Mar 23, 2026
Merged

fix: close SSRF IPv6 bypass and replace Math.random() session IDs with crypto.randomUUID()#1
HugoWong528 merged 1 commit intomainfrom
copilot/check-data-security-issues

Conversation

Copy link

Copilot AI commented Mar 23, 2026

Summary

Two security vulnerabilities in the SSRF guard and session ID generation. The SSRF filter missed IPv4-mapped IPv6 addresses entirely, and session IDs relied on Math.random() — a non-CSPRNG source.

Related Issues

Changes

  • lib/server/ssrf-guard.ts

    • Added extractIPv4FromMappedIPv6() to unwrap both dotted-decimal (::ffff:127.0.0.1) and hex-encoded (::ffff:7f00:1) IPv4-mapped IPv6 addresses, then validates the embedded IPv4 against existing private-range rules
    • Scoped all IPv6 range checks (unique-local fc00::/7, link-local fe80::/10, loopback) to hostnames containing : — prevents false-positive blocks on domain names like fdomain.com
    • Split isBlockedHostname into isBlockedIPv4 + isBlockedHostname for clarity and reuse
  • components/chat/use-chat-sessions.ts

    • Replaced all three \session-${Date.now()}-${Math.random()...}`session ID patterns with`session-${crypto.randomUUID()}``
// Before — predictable
const sessionId = `session-${Date.now()}-${Math.random().toString(36).slice(2)}`;

// After — CSPRNG-backed
const sessionId = `session-${crypto.randomUUID()}`;
// Before — missed IPv4-mapped IPv6
hostname === '::1' || hostname === 'localhost' || ...

// After — unwraps ::ffff:7f00:1 → 127.0.0.1 before range checks
const embeddedIPv4 = extractIPv4FromMappedIPv6(hostname);
if (embeddedIPv4 !== null) {
  if (isBlockedIPv4(embeddedIPv4)) return 'Local/private network URLs are not allowed';
  return null;
}

Type of Change

  • Bug fix (non-breaking change that fixes an issue)

Verification

Steps to reproduce / test

  1. Supply http://[::ffff:127.0.0.1]/ as a custom base URL — previously bypassed the SSRF guard, now blocked
  2. Supply http://[::ffff:7f00:1]/ — same bypass, now blocked
  3. Supply https://api.openai.com — passes through correctly
  4. Supply http://fdomain.com — passes through (no false positive on fd-prefixed domain)

What you personally verified

  • SSRF guard correctly blocks all private-range IPv4-mapped IPv6 variants
  • No false positives on legitimate domain names starting with fd, fc, fe80, etc.
  • crypto.randomUUID() is available in both browser and Node.js (Next.js) runtimes

Evidence

  • CI passes (pnpm check && pnpm lint && npx tsc --noEmit)
  • Manually tested locally
  • Screenshots / recordings attached (if UI changes)

Checklist

  • My code follows the project's coding style
  • I have performed a self-review of my code
  • I have added/updated documentation as needed
  • My changes do not introduce new warnings

…ssion IDs with crypto.randomUUID()

Co-authored-by: HugoWong528 <267603037+HugoWong528@users.noreply.github.com>
Agent-Logs-Url: https://github.com/HugoWong528/OpenMAIC/sessions/11d0af47-a7c4-419c-bb94-639f2f7b95cb
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