Skip to content

Validate Origin and Host on --http (DNS rebinding) - #46

Merged
csa7mdm merged 2 commits into
mainfrom
feat/http-origin
Sep 24, 2026
Merged

csa7mdm merged 2 commits into
mainfrom
feat/http-origin

Conversation

@csa7mdm

@csa7mdm csa7mdm commented Sep 24, 2026

Copy link
Copy Markdown
Owner

The MCP spec requires Streamable HTTP servers to validate Origin to prevent DNS rebinding. Before this change, --http checked nothing.

Behavior

  • Allowed origins: a request with an Origin header gets 403 unless the value is http://localhost:<port>, http://127.0.0.1:<port> or http://[::1]:<port> on the server's own port, or a value passed with the new repeatable --allowed-origin. Other localhost ports and https are rejected.
  • Host check: a Host header naming anything but localhost, 127.0.0.1 or [::1] gets 403. This is the DNS-rebinding defense.
  • No Origin: requests without an Origin header (non-browser MCP clients) pass through.
  • --allowed-origin validation: values are checked at startup (absolute http/https, no path, query, userinfo, null or *), and a trailing / is normalized away. An invalid value exits with code 2 and a message.
  • No CORS headers: the server sends none, so --allowed-origin doesn't let a browser page call the server directly. The docs say so.
  • Stdio mode is unchanged.

Review

An Opus adversarial review approved it with 0 blockers and 0 majors:

  • About 90 bypass probes were all rejected or harmless: Origin: null, trailing slash, http://localhost:03998, 127.1, localhost., IPv6 long forms, X-Forwarded-Host, userinfo tricks, every method and path, and h2c.
  • Its mutation test (guard removed) was caught by the tests.

Its 6 minor findings are fixed in the second commit:

  • the no-Origin test now does a real initialize and expects 200;
  • real-server tests for Host rebinding and --allowed-origin;
  • no child-process leak when startup fails;
  • a wrong code comment corrected;
  • more precise docs;
  • startup validation of --allowed-origin.

Tests

22 in Integration.Tests (was 0 active), including 3 real-server tests. The solution passes: Build 12, CodeIntelligence 9, Integration 22, Testing 32, Core 67. Verified by the lead session.

🤖 Generated with Claude Code

csa7mdm and others added 2 commits September 24, 2026 11:45
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@csa7mdm
csa7mdm merged commit b619444 into main Sep 24, 2026
6 of 7 checks passed
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