Skip to content

feat(mcp): validate Host/Origin headers on MCP HTTP transports#642

Closed
vishal-bala wants to merge 1 commit into
mainfrom
claude/hardcore-robinson-f41813
Closed

feat(mcp): validate Host/Origin headers on MCP HTTP transports#642
vishal-bala wants to merge 1 commit into
mainfrom
claude/hardcore-robinson-f41813

Conversation

@vishal-bala

Copy link
Copy Markdown
Collaborator

Motivation

RedisVL can expose a configured Redis index to MCP clients over HTTP, through the streamable-http and sse transports. Until now, once such a server was listening it would answer any HTTP request that reached its port, without confirming that the request was actually addressed to it. Validating that requests are intended for this server is a standard piece of transport hardening, and one worth having on by default rather than left to each deployment.

This change adds that check: the HTTP transports now confirm, on every request, that it is genuinely addressed to this server before any tool runs.

What changed

The server validates the Host and Origin headers of each HTTP request against allowlists and rejects anything that doesn't match, before the request reaches the search or upsert tools. The protection is on by default and needs no configuration for the common cases — the allowlist is derived automatically from the address the server binds to, so loopback and same-machine clients keep working exactly as before. Requests that carry no Origin (typical of non-browser MCP clients) are unaffected; only cross-site origins are scrutinized.

For deployments where the client-visible host legitimately differs from the bind address — behind a reverse proxy, or bound to 0.0.0.0 and reached by a public hostname — the allowlist can be extended, or the check relaxed, through a new server.transport_security block in the MCP config and matching REDISVL_MCP_* environment variables. This mirrors the existing authentication configuration, so it should feel familiar. Authentication and this check are complementary and independent: auth decides who may call, while this decides which authority a request may claim. The stdio transport has no network surface and is untouched.

Implementation notes

  • A new redisvl/mcp/transport_security.py module holds a small ASGI middleware plus the config resolution, with FastMCP/Starlette imports deferred so the module stays importable without the optional mcp extra.
  • The guard is wired in through RedisVLMCPServer.run_async, so it applies to both the CLI and any programmatic embedder, and runs outermost — ahead of auth and the tool handlers.
  • Defaults are fail-closed: the guard is enabled when unconfigured, and a 0.0.0.0 bind trusts only loopback until the operator names its public hosts.

Tests & docs

Adds unit coverage for the middleware (host/origin matching, port and IPv6 handling, case-insensitivity, enable/disable) and for its config resolution, plus integration tests over real HTTP confirming that a legitimate local client still succeeds while spoofed hosts and cross-site origins are rejected. The MCP how-to and authentication guides gain a "Transport Security" section covering the defaults and the configuration knobs.

🤖 Generated with Claude Code

Harden the MCP server's streamable-http and SSE transports by validating
the Host and Origin request headers against allowlists before any tool
call runs. The guard is on by default and auto-derives a safe allowlist
from the bind address, so loopback and local clients work with no config.

Non-loopback and reverse-proxy deployments can extend the allowlist (or
disable the guard) via a server.transport_security config block and
REDISVL_MCP_* environment variables, mirroring the existing auth pattern.
stdio has no network surface and is unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jit-ci

jit-ci Bot commented Jul 2, 2026

Copy link
Copy Markdown

🛡️ Jit Security Scan Results

CRITICAL HIGH MEDIUM

✅ No security findings were detected in this PR


Security scan by Jit

@vishal-bala vishal-bala closed this Jul 2, 2026
@vishal-bala
vishal-bala deleted the claude/hardcore-robinson-f41813 branch July 2, 2026 12:24
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