docs: add DNS rebinding / host authorization note to security section#214
Conversation
|
ActionDispatch::HostAuthorization is probably not available in the Server. We need to add it in the middleware stack. Use the test/dummy app to test it. (you can run it production) |
|
heads up on scope. started as the docs pr, added HostAuthorization after your comment. then i noticed HostAuthorization only checks Host, not Origin. the mcp spec wants Origin specifically. couldn't find anything in rails that does Origin for an ApiController (forgery_protection_origin_check is csrf only), so i ended up writing a verify_origin before_action with an allowed_origins config. that's 980ad4c, 1838f33, 98263a8. that's more than you said yes to on #208. want me to split it out or drop it? or if there's something in rails i missed just point me at it. |
Points to config.hosts / ActionDispatch::HostAuthorization as the Rails-native way to satisfy the MCP spec's Origin validation requirement. Closes seuros#208
- add test/host_authorization_middleware_test.rb with rack-level tests for ActionDispatch::HostAuthorization behavior (blocked hosts, empty list, subdomain patterns, ipv6, port stripping, case-insensitivity) - add test verifying the engine's standalone middleware stack includes HostAuthorization when app.config.hosts is configured - add test/dummy/config/environments/production.rb with config.hosts for running the dummy app in production mode - wire ActionDispatch::HostAuthorization into mcp_vanilla.ru before the JSONRPC validator so the custom standalone stack enforces host checking
The MCP spec (Streamable HTTP, Security) requires servers to validate the Origin header on all incoming connections and return 403 Forbidden when it is present but invalid. - add verify_origin before_action in ApplicationController: - absent Origin is allowed (non-browser clients never send it) - present Origin must match the server's own host (default) - or an explicit config.action_mcp.allowed_origins list (String or Regexp) - 403 response body is JSON-RPC with no id, as the spec specifies - add allowed_origins attribute to ActionMCP::Configuration (default nil) - fix README: remove false claim that HostAuthorization covers Origin validation; document both layers correctly - fix production.rb: remove consider_all_requests_local = true - expand test suite: Origin validation tests via integration tests, engine standalone stack assertion simplified to the actually-run branch
- strip brackets from uri.host before matching so allowed_origins entries like "::1" match Origin headers containing "http://[::1]" (URI.parse returns host as "[::1]" which users would not naturally include in patterns) - apply same normalization to request.host in the default path - add allowed_origins to extract_top_level_settings so it can be set via config/mcp.yml alongside all other configuration keys - add canonical DNS rebinding test: HOST: localhost + Origin: http://evil.com - add localhost same-host allow tests and IPv6 allow/block/normalization tests - add comment explaining why id is nil in the 403 response
Split test coverage into two focused files: - test/host_authorization_middleware_test.rb: single engine stack assertion - test/security/origin_validation_test.rb: 10 integration tests covering same-host allow, foreign/null Origin rejection, JSON-RPC 403 body, allowed_origins list/Regexp, and IPv6 bracket normalization
98263a8 to
9924406
Compare
seuros
left a comment
There was a problem hiding this comment.
Thanks for the PR and the tests.
One issue: verify_origin is a before_action in the controller, but it should be a Rack middleware instead. The rest of this PR already does it right. HostAuthorization is added as middleware. Origin validation should follow the same pattern.
Extract it into ActionMCP::Middleware::OriginValidation and add it to the stack in engine.rb and mcp_vanilla.ru. Everything else looks good.
move verify_origin from ApplicationController before_action into ActionMCP::Middleware::OriginValidation, matching the existing HostAuthorization pattern. rejects invalid origins before routing. wired in engine.rb and mcp_vanilla.ru.
|
done in 31f00d4. extracted into |
Per the discussion in #208 — @seuros noted this is a Rails configuration concern, not something action_mcp should implement itself.
Adds a bullet to the Production Considerations > Security section pointing users at
config.hosts/ActionDispatch::HostAuthorizationas the Rails-native way to satisfy the MCP spec's Origin validation requirement.