Fix SSRF blocklist missing the 10.0.0.0/8 private range#2435
Open
Osamaali313 wants to merge 1 commit into
Open
Fix SSRF blocklist missing the 10.0.0.0/8 private range#2435Osamaali313 wants to merge 1 commit into
Osamaali313 wants to merge 1 commit into
Conversation
`UNSAFE_IPV4_SUBNETS` in `urlSafety.ts` is the sole data behind `isUnsafeIp()`, which backs the whole SSRF boundary (`isValidUrl` for IP-literal hosts and the `ssrfSafeAgent` DNS `lookup` that validates the resolved IP at connect time). It lists loopback, link-local, CGNAT, and two of the three RFC1918 blocks (`172.16/12`, `192.168/16`) — but omits the largest one, `10.0.0.0/8`. As a result `https://10.0.0.1/...` (IP literal) passes `isValidUrl`, and any hostname that resolves to `10.x.x.x` passes the DNS guard, so the server can be made to reach internal `10.0.0.0/8` hosts via the file-fetch proxy (`api/fetch-url`) and MCP URL handling — SSRF into the most common cloud/VPC private range. The client-side sibling validator (`utils/mcpValidation.ts`) already lists `10\.` first in its private-IP regex, confirming `10/8` is meant to be blocked. Add `10.0.0.0/8` to the list (this also covers IPv4-mapped IPv6, since the same list is reused for `::ffff:10.x.x.x`). No behavior change for legitimate public URLs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
UNSAFE_IPV4_SUBNETSinsrc/lib/server/urlSafety.tsis the sole data behindisUnsafeIp(), which backs the entire server-side SSRF boundary:isValidUrl()— validates IP-literal hostnames.assertSafeIp()→ thessrfSafeAgentcustom DNSlookup— validates the resolved IP at connect time (the anti-DNS-rebinding guard).The list includes loopback (
127/8), link-local (169.254/16), CGNAT (100.64/10), and two of the three RFC1918 private blocks (172.16/12,192.168/16) — but omits the largest one,10.0.0.0/8:Because
isValidUrlrequireshttps:, a literalhttps://10.0.0.1/...passes; and independently, any hostname that resolves to10.x.x.xpasses the DNS guard. Either way the server can be induced to reach internal10.0.0.0/8hosts (cloud metadata/VPC services, internal APIs, admin panels) — SSRF via the public file-fetch proxy (api/fetch-url) and MCP URL handling (runMcpFlow,clientPool,mcp/tools,mcp/health).Evidence (sibling proves intent)
The client-side private-IP validator (
src/lib/utils/mcpValidation.ts) lists10\.first:Both validators are meant to cover the same private space; the real security boundary (
urlSafety.ts) is the one that dropped10/8.Fix
Add
10.0.0.0/8to the blocklist (also covers IPv4-mapped IPv6::ffff:10.x.x.x, since the same list is reused there). No behavior change for legitimate public URLs.Reproduction
Faithful CIDR reimplementation of
isUnsafeIp's IPv4 path:10.0.0.1false❌true✅10.255.255.254false❌true✅172.16.0.1truetrue192.168.1.1truetrue8.8.8.8(public)falsefalse