Skip to content

Tool name validation accepts a trailing newline (regex uses $ instead of \Z) #3084

Description

@Otis0408

Describe the bug

TOOL_NAME_REGEX in src/mcp/shared/tool_name_validation.py is end-anchored with $:

TOOL_NAME_REGEX = re.compile(r"^[A-Za-z0-9._-]{1,128}$")

In Python's default (non-MULTILINE) mode, $ matches at end-of-string or immediately before a single trailing \n. So a tool name ending in exactly one newline passes validation, even though \n is not in the allowed character set.

The length guard uses len(), which counts the \n, so "a" * 127 + "\n" (length 128) slips past both the length check and the character check.

Embedded newlines and other trailing control characters are already rejected correctly. Only the single-trailing-newline case leaks.

To Reproduce

from mcp.shared.tool_name_validation import validate_tool_name, validate_and_warn_tool_name

print(validate_tool_name("evil_tool\n").is_valid)   # True  (expected: False)
print(validate_and_warn_tool_name("evil_tool\n"))   # True, and no warning is logged

print(validate_tool_name("a" * 127 + "\n").is_valid)  # True, length 128 passes too

Expected behavior

validate_tool_name("evil_tool\n").is_valid should be False, since \n is not one of the allowed characters.

Additional context

Anchoring the end with \Z (strict end-of-string) instead of $ fixes it, and no valid name is affected: re.match(r"^[A-Za-z0-9._-]{1,128}\Z", "abc") still matches, while "abc\n" correctly fails.

I have an open PR with this fix and a regression test: #3076. Filing this issue to track it, per CONTRIBUTING ("Bug fixes for clear, reproducible issues are welcome—but still create an issue to track the fix").

Metadata

Metadata

Assignees

No one assigned

    Labels

    v2Ideas, requests and plans for v2 of the SDK which will incorporate major changes and fixes

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions