Skip to content

fix(web): block RFC 6890 TEST-NET-3 (192.0.248.0/15) in safeFetch SSRF guard - #236

Open
dirtybits wants to merge 1 commit into
mainfrom
fix/ssrf-testnet-blocklist
Open

dirtybits wants to merge 1 commit into
mainfrom
fix/ssrf-testnet-blocklist

Conversation

@dirtybits

Copy link
Copy Markdown
Owner

Summary

Closes a gap in resolveSafeFetchUrl, the SSRF boundary guard that validates author-controlled skill_uri before the server fetches it (/api/skills/{id}/raw chain-only path and fetchPublicUrl).

ipv4LooksBlocked blocked IANA TEST-NET ranges except 192.0.248.0/15 (TEST-NET-3, RFC 6890). The runtime DNS-layer guard (publicUrlFetch.server.ts blockedV4) already rejected it, so the current fetch path is double-guarded — but safeFetch is the exported, standalone-usable primary SSRF check, its doc comment (IPV4_BLOCKLIST_NOTE) advertised "TEST-NET-3" coverage while omitting this range, and the raw-download route's redirect loop depends on resolveSafeFetchUrl for every hop. This PR adds the range to ipv4LooksBlocked and aligns the doc note with the full code blocklist.

Only adds blocks to reserved/documented special-use ranges; no range is unblocked, so no legitimate public skill URL is affected.

Verified

  • Runtime probe (against current main): 192.0.248.0/15 was allowed (gap); after change it is blocked. Adjacent out-of-range values (192.0.247.255) remain allowed.
  • web/__tests__/lib/safeFetch.test.ts: added RFC 6890 range coverage (block boundaries 248.0/248.1/248.255/249.0/254.0/255.0/255.255) and out-of-range allow-list (247.255, 198.51.101.1, 198.51.99.255, 203.0.112.1).
  • Full local gate: npm run format:check (pass), npm run lint (pass), next typecheck (pass), vitest run (1311 tests pass).
  • next build --webpack failed locally only because DATABASE_URL/web/.env.local are not set in the cron shell (pre-existing env limitation; the failure is in DB-backed prerendering of /sitemap.xml and unrelated to this change). The Vercel build is the authoritative build gate (CI test job does not run next build per AGENTS.md).

Files

  • web/lib/safeFetch.ts: + if (a === 192 && b === 0 && c >= 248) return true; and updated IPV4_BLOCKLIST_NOTE.
  • web/__tests__/lib/safeFetch.test.ts: extended TEST-NET-3 test with RFC 6890 range + boundaries; added out-of-range allow-list cases.

Not verified / caveats

  • GPG: this headless cron shell has no available signing key (gpg --list-secret-keys is empty), so the commit landed unsigned. To sign, run:
    git -C <checkout> commit --amend -S --no-edit && git push --force-with-lease origin fix/ssrf-testnet-blocklist
    after unlocking/providing the signing key (per AGENTS.md signing rule).
  • Web build not run locally due to missing DATABASE_URL (env, not code).

Test Plan

  1. Run the extended safeFetch.test.ts — confirms 192.0.248.0/15 is rejected and boundaries/out-of-range values still pass.
  2. Re-run full web vitest (1311) to confirm no regression to the SSRF/URL guard.
  3. CI: format, lint, typecheck, vitest (test job). Vercel build gate is the authoritative next build.

Related

Supersedes the incomplete TEST-NET-3 coverage from PR #231, which blocked 198.51.100.0/24 + 203.0.113.0/24 (RFC 5737) but missed 192.0.248.0/15 (RFC 6890).

This branch was successfully deployed

1 active deployment
Preview — 754ab400 Deployed Oct 11, 2026 by vercel[bot]
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