Skip to content

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

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

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

@hamodywe hamodywe commented Aug 8, 2026

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.

Fixes modelcontextprotocol#3269

@cubic-dev-ai cubic-dev-ai Bot 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

@github-actions github-actions Bot added the missing-issue-link Auto-closed: PR needs a linked issue assigned to its author (see CONTRIBUTING.md) label Aug 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for the contribution. This repository only keeps pull requests open when they're linked to an issue that a maintainer has assigned to the author — CONTRIBUTING.md explains why and how we work. This PR has been closed for now because you aren't currently assigned to #3269.

If a maintainer would like this change as a PR from you, they'll assign you to #3269 and this PR will reopen automatically — there's nothing more you need to do. (If you opened the issue, this PR already shows up on its timeline.)

There's no need to open a new PR — this one will be reopened. While it's closed, please push any updates as new commits rather than force-pushing, since GitHub can't reopen a PR whose branch has been rewritten.

Maintainers: reopening this PR, removing the missing-issue-link label, or adding bypass-issue-check bypasses the check.

@github-actions github-actions Bot closed this Aug 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

missing-issue-link Auto-closed: PR needs a linked issue assigned to its author (see CONTRIBUTING.md)

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