fix(devframe): reject non-loopback DNS origins beginning with 127. - #319
Open
antfubot wants to merge 1 commit into
Open
fix(devframe): reject non-loopback DNS origins beginning with 127.#319antfubot wants to merge 1 commit into
antfubot wants to merge 1 commit into
Conversation
isLoopbackHostname classified any hostname starting with '127.' as loopback, so an attacker-controlled DNS name like 127.attacker.example passed the loopback origin gate that guards the RPC/MCP surface. Because every WS/SSE/MCP transport and the origin registry funnel through this check, a cross-origin browser page could defeat the DNS-rebinding / cross-site WebSocket-hijacking mitigation and reach privileged RPC. Match the IPv4 loopback case structurally instead: the whole hostname must be a canonical dotted-decimal literal in 127.0.0.0/8. Genuine loopback addresses (127.0.0.1, 127.5.5.5) stay allowed; 127.* DNS names are rejected. CWE-346, CWE-1385
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
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.
Summary
Devframe's WebSocket/SSE/MCP origin gate treated any hostname beginning with
127.as loopback, so an attacker-controlled DNS name such as127.attacker.exampleor127.0.0.1.attacker.exampleslipped past the loopback trust boundary. Because every transport (ws-server,ws-bun,ws-deno,sse-server, the MCP fetch handler) and the external-viewer origin registry all funnel their origin check throughisLoopbackHostname, a cross-origin browser page could defeat the DNS-rebinding / cross-site WebSocket-hijacking mitigation and reach the privileged RPC surface (e.g. build-mode DevTools where accepted clients are auto-trusted, then the terminals RPC → shell command execution).The root cause was a prefix test:
which never verified the hostname was an IPv4 literal.
Fix
Classify the IPv4 loopback case structurally: the whole hostname must be a canonical dotted-decimal literal in
127.0.0.0/8. Genuine loopback addresses (127.0.0.1,127.5.5.5) stay allowed while127.*DNS names are rejected. Thelocalhost/*.localhost/::1branches are unchanged.The fix lives in the single shared classifier, so it closes the bypass for the WS Node/Bun/Deno transports, the SSE transport, the route-based MCP endpoint, and the origin registry at once.
Tests
Extended the origin-check unit test with regression cases:
localhost,foo.localhost,127.0.0.1,127.5.5.5,::1127.attacker.example,127.0.0.1.attacker.example,127.0.0,127.0.0.256,1270.0.0.1,evil.exampleisAllowedOriginis likewise checked to accepthttp://127.0.0.1:5173and rejecthttp://127.attacker.example.Audit
Confirmed
isLoopbackHostnameis the only place this classification is implemented; all other origin gates delegate to it. The public API surface is unchanged (only private helpers were added), so the tsnapi snapshot is unaffected.This PR was created with the help of an agent.