CVE-2025-53366
MCP Python SDK < 1.9.4 crashes on malformed requests, causing potential DoS.
- CVSS 8.7
- CWE-248
- Input Validation and Sanitization
- Remote
The MCP Python SDK, called `mcp` on PyPI, is a Python implementation of the Model Context Protocol (MCP). Prior to version 1.9.4, a validation error in the MCP SDK can cause an unhandled exception when processing malformed requests, resulting in service unavailability (500 errors) until manually restarted. Impact may vary depending on the deployment conditions, and presence of infrastructure-level resilience measures. Version 1.9.4 contains a patch for the issue.
- CWE
- CWE-248
- CVSS base score
- 8.7
- Published
- 2025-07-04
- OWASP
- A01 Broken Access Control
- Orthogonal defect classification
- Checking
- Code defect classification
- Incorrect Functionality
- Category
- Input Validation and Sanitization
- Subcategory
- Inadequate Error Handling
- Accessibility scope
- Remote
- Impact
- Denial of Service (DoS)
- Affected component
- Python
- Fixed by upgrading
- Yes
Solution
Upgrade to version 1.9.4 or later.
Vulnerable code sample
# This code is a simplified representation of the vulnerability.
# It does not represent the actual MCP library or CVE-2025-53366 exactly.
# It is intended to demonstrate a potential validation error leading to a 500 error.
def process_request(request_data):
"""
Processes a request containing model context data.
Prior to the fix, malformed requests could cause an unhandled exception.
"""
try:
model_id = request_data['model_id']
context_data = request_data['context_data']
# Simulate validation logic. In a real-world scenario, this
# would involve checking the structure, types, and values of
# 'context_data' against a defined schema or expectations.
if not isinstance(model_id, int):
raise ValueError("Model ID must be an integer.")
if not isinstance(context_data, dict):
raise ValueError("Context data must be a dictionary.")
# Simulate a potential validation error. Prior to the fix, a missing key
# or incorrect data type within 'context_data' might not be handled
# properly.
try:
feature_1 = context_data['feature_1']
if not isinstance(feature_1, float):
raise TypeError("feature_1 must be a float")
except KeyError:
#Before the fix, it is possible this error would cause a 500 error by not catching it here
print ("KeyError")
return
# Simulate further processing (e.g., using the model and context).
print(f"Processing request for model {model_id} with context data.")
# In a real system, this might involve loading a model, applying
# transformations based on 'context_data', and performing inference.
return {"status": "success", "message": "Request processed."}
except ValueError as e:
# Simulate an unhandled exception. Before the fix, specific validation
# errors might not be caught, resulting in a 500 error rather than
# a graceful error message.
print(f"Error processing request: {e}")
#Before the fix, the code would likely raise an unhandled exception here,
#instead of returning an error to the user.
# Simulate the 500 error by not handling the exception
#raise #Remove this line if you want to see the print statement, but this line simulates the 500
return {"status": "error", "message": str(e)}, 500 # Correct way to handle the error
except TypeError as e:
print(f"Error processing request: {e}")
return {"status": "error", "message": str(e)}, 500
# Example usage with a malformed request.
malformed_request = {
"model_id": "abc", # Invalid model ID (should be an integer)
"context_data": {"feature_1": "hello"}
}
result = process_request(malformed_request)
print(result)
# Example of proper use
correct_request = {
"model_id": 123,
"context_data": {"feature_1": 0.5}
}
result = process_request(correct_request)
print(result)Patched code sample
def process_mcp_request(request_data):
"""
Processes an MCP request, handling potential validation errors.
"""
try:
# Simulate the parsing and validation logic that might raise exceptions.
# In a real-world scenario, this would involve deserializing the
# request_data according to the MCP specification and validating
# its contents. We simulate that with a few checks here.
if not isinstance(request_data, dict):
raise ValueError("Request data must be a dictionary.")
if "model_name" not in request_data:
raise ValueError("Request must contain 'model_name'.")
if not isinstance(request_data["model_name"], str):
raise ValueError("Model name must be a string.")
# Simulate a vulnerable validation condition. This could be
# any specific check that throws an exception in the original
# vulnerable code. For example, an invalid numerical value.
if "param1" in request_data:
try:
param1_value = float(request_data["param1"])
if param1_value < 0:
raise ValueError("Param1 must be non-negative.") # Example validation
except (ValueError, TypeError) as e:
raise ValueError(f"Invalid value for param1: {e}")
# If we get here, validation passed (at least our simulated version)
print("Request validated successfully.")
# Simulate actual request processing (e.g., interaction with the model)
print(f"Processing request for model: {request_data['model_name']}")
# Add actual business logic here
return {"status": "success", "message": "Request processed"}
except ValueError as e:
# Catch specific validation errors and return a graceful error response
print(f"Validation error: {e}")
return {"status": "error", "message": str(e)}
except Exception as e: # Catch unexpected errors to prevent crashes.
print(f"Unexpected error: {e}") # log unexpected errors.
return {"status": "error", "message": "Internal server error"}
if __name__ == '__main__':
# Example usage with valid and invalid requests:
valid_request = {"model_name": "my_model", "param1": "1.5"}
invalid_request_1 = "not a dictionary"
invalid_request_2 = {"param1": "-1"}
invalid_request_3 = {"model_name": 123}
invalid_request_4 = {"model_name": "another_model", "param1": "abc"}
print("Processing valid request:")
print(process_mcp_request(valid_request))
print("\nProcessing invalid request (not a dictionary):")
print(process_mcp_request(invalid_request_1))
print("\nProcessing invalid request (negative param1):")
print(process_mcp_request(invalid_request_2))
print("\nProcessing invalid request (invalid model_name type):")
print(process_mcp_request(invalid_request_3))
print("\nProcessing invalid request (invalid param1 type):")
print(process_mcp_request(invalid_request_4))Payload
b'\x08\x01\x12\x00'
Cite this entry
@misc{vaitp:cve202553366,
title = {{MCP Python SDK < 1.9.4 crashes on malformed requests, causing potential DoS.
}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2025},
note = {VAITP Python Vulnerability Dataset, entry CVE-2025-53366},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-53366/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
