Skip to content

Reject an orphan Mcp-Name header when the body omits the named param - #3270

Open
hamodywe wants to merge 1 commit into
modelcontextprotocol:mainfrom
hamodywe:fix/mcp-name-orphan-header-validation
Open

Reject an orphan Mcp-Name header when the body omits the named param#3270
hamodywe wants to merge 1 commit into
modelcontextprotocol:mainfrom
hamodywe:fix/mcp-name-orphan-header-validation

Conversation

@hamodywe

Copy link
Copy Markdown

classify_inbound_request's Mcp-Name check only ran when the body carried the name-bearing method's param (name_key). When the body omitted it, a present Mcp-Name header went unvalidated entirely -- an intermediary or client could set it to claim a different tool/prompt/resource than the request body actually names, with no rejection.

validate_mcp_param_headers already treats this shape -- a header present with no matching body value -- as a rejection for Mcp-Param-* headers, on the same reasoning: a conforming client never emits the header unless the body value is present, so a header with nothing to match against did not come from this request. Mcp-Name had no equivalent check.

Mirrors that handling: when the named param is absent, an absent header still passes (the param's own absence is INVALID_PARAMS elsewhere, not this rung's concern), but a present header is now rejected HEADER_MISMATCH.

Adds test_header_rung_rejects_orphan_name_header_when_body_omits_the_named_param, parametrized over all of NAME_BEARING_METHODS. Confirmed it fails against the unpatched code (reverting just inbound.py, keeping the test) and passes with the fix.

AI assistance disclosure: I used Claude to help investigate this issue and implement/test the fix; I've reviewed the change and reasoning above and can answer questions about it.

Fixes#3269

Motivation and Context

How Has This Been Tested?

Breaking Changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

classify_inbound_request's Mcp-Name check only ran when the body carried
the name-bearing method's param (name_key). When the body omitted it, a
present Mcp-Name header went unvalidated entirely -- an intermediary or
client could set it to claim a different tool/prompt/resource than the
request body actually names, with no rejection.
validate_mcp_param_headers already treats this shape -- a header present
with no matching body value -- as a rejection for Mcp-Param-* headers,
on the same reasoning: a conforming client never emits the header unless
the body value is present, so a header with nothing to match against did
not come from this request. Mcp-Name had no equivalent check.
Mirrors that handling: when the named param is absent, an absent header
still passes (the param's own absence is INVALID_PARAMS elsewhere, not
this rung's concern), but a present header is now rejected HEADER_MISMATCH.
Adds test_header_rung_rejects_orphan_name_header_when_body_omits_the_named_param,
parametrized over all of NAME_BEARING_METHODS. Confirmed it fails against
the unpatched code (reverting just inbound.py, keeping the test) and
passes with the fix.
AI assistance disclosure: I used Claude to help investigate this issue
and implement/test the fix; I've reviewed the change and reasoning above
and can answer questions about it.
Fixesmodelcontextprotocol#3269

@cubic-dev-aicubic-dev-aiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Re-trigger cubic

Sign up for freeto 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.

Mcp-Name accepts an orphan header, while Mcp-Param-* rejects it as a routing spoof

1 participant

@hamodywe