-
Notifications
You must be signed in to change notification settings - Fork 232
Description
Prompt Endpoint Accepts XSS Content Without Validation Error
Priority: High (Security/Data Integrity)
Description:
The prompt execution endpoint (/prompts/{prompt_name}
) does not validate or reject XSS content in prompt arguments. While the system correctly escapes HTML entities in the output (preventing actual XSS execution), it does not return a validation error for potentially malicious input as expected.
Steps to Reproduce:
-
Start the MCP Gateway server:
make serve
-
Generate authentication token:
export MCPGATEWAY_BEARER_TOKEN=$(python3 -m mcpgateway.utils.create_jwt_token -u admin --secret my-test-key)
-
Create a test prompt with arguments:
curl -X POST http://localhost:4444/prompts \ -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "greeting_prompt", "description": "Personalized greeting template", "template": "Hello {{ name }}, welcome to {{ company }}!", "arguments": [ {"name": "name", "description": "User name", "required": true}, {"name": "company", "description": "Company name", "required": true} ] }'
-
Execute the prompt with XSS content:
curl -X POST http://localhost:4444/prompts/greeting_prompt \ -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Alice<script>alert(1)</script>", "company": "Acme Corp" }'
Expected Behavior:
- Should return HTTP 422 (Unprocessable Entity) status code
- Error message should indicate that prompt arguments contain invalid characters or potential XSS content
- The request should be rejected before template rendering
Actual Behavior:
- Returns HTTP 200 with escaped HTML in the response:
{ "messages": [{ "role": "user", "content": { "type": "text", "text": "Hello Alice<script>alert(1)</script>, welcome to Acme Corp!" } }], "description": "Personalized greeting template" }
- XSS content is escaped but not rejected
Impact:
- While the current behavior prevents actual XSS execution through escaping, it doesn't follow the principle of input validation
- Inconsistent with other endpoints that reject XSS attempts with validation errors
- May allow storage of escaped XSS content in logs or databases
- Could be problematic if the escaped content is later used in contexts where escaping is not applied
Root Cause Analysis:
The prompt execution endpoint likely lacks input validation for the dynamic arguments passed to prompts. The system is relying solely on output escaping rather than input validation.
Suggested Fix:
-
Add input validation to the prompt execution endpoint to check for XSS patterns in argument values
-
Implement validation in the prompt execution handler that checks all argument values:
from mcpgateway.utils.validators import validate_no_xss @router.post("/prompts/{prompt_name}") async def execute_prompt(prompt_name: str, arguments: Dict[str, Any]): # Validate all argument values for key, value in arguments.items(): if isinstance(value, str): try: validate_no_xss(value, f"Prompt argument '{key}'") except ValueError as e: raise HTTPException(status_code=422, detail=str(e)) # Continue with prompt execution...
-
Consider making XSS validation configurable:
- Strict mode: Reject any HTML-like content (current test expectation)
- Escape mode: Allow but escape (current behavior)
- This could be controlled via environment variable
Additional Context:
- This issue was discovered during comprehensive input validation testing
- Other endpoints (tools, resources, gateways) properly reject XSS with validation errors
- The inconsistency in validation behavior across endpoints could confuse API users
- HTML escaping is a good defense-in-depth measure but shouldn't replace input validation
Testing Considerations:
- Test with various XSS patterns:
<script>
,<img src=x onerror=>
,javascript:
, etc. - Test with legitimate use cases that might contain angle brackets: mathematical expressions (
a < b
), email formats - Ensure validation doesn't break legitimate template variables
Related Issues:
- [Security]: Add input validation for main API endpoints (depends on #339 /admin API validation) #340 (Non-admin API input validation implementation)
- Consider whether similar validation is needed for:
- Prompt template content itself
- Resource content when mimeType is text/plain or text/markdown
- Tool input schemas that accept string parameters
RPC Endpoint Accepts Invalid Method Names Without Proper Validation
Priority: High (Security/Input Validation)
Description:
The RPC endpoint (/rpc
) does not properly validate method names before processing, allowing potentially malicious content (including XSS patterns) in method names. Instead of returning a validation error for invalid method name formats, it processes the request and returns a "Tool not found" error, indicating the invalid input reached the tool lookup logic.
Steps to Reproduce:
-
Start the MCP Gateway server:
make serve
-
Generate authentication token:
export MCPGATEWAY_BEARER_TOKEN=$(python3 -m mcpgateway.utils.create_jwt_token -u admin --secret my-test-key)
-
Send an RPC request with XSS content in the method name:
curl -X POST http://localhost:4444/rpc \ -H "Authorization: Bearer $MCPGATEWAY_BEARER_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "method": "<script>alert(1)</script>", "id": 1 }'
Expected Behavior:
- Should return HTTP 422 (Unprocessable Entity) or appropriate JSON-RPC error
- Error response should indicate "Invalid method name format" or similar
- The method name should be validated before any tool lookup occurs
- Valid method names should follow pattern:
[gateway-name]-[tool-name]
ortools/list
,resources/list
, etc.
Actual Behavior:
- Returns HTTP 200 with JSON-RPC error indicating the invalid input was processed:
{ "jsonrpc": "2.0", "error": { "code": -32000, "message": "Internal error", "data": "Tool not found: <script>alert(1)</script>" }, "id": 1 }
- The invalid method name reached the tool lookup logic, indicating lack of input validation
Impact:
- Invalid input is being processed by internal logic rather than rejected at validation layer
- Potential for injection attacks if method names are used in database queries or logging without proper sanitization
- Inconsistent with other endpoints that properly validate input
- Could lead to error messages that leak internal implementation details
Root Cause Analysis:
The RPC handler is not validating the method name format before attempting to process the request. The method name is passed directly to the tool/resource lookup logic without checking if it conforms to expected patterns.
Suggested Fix:
-
Add method name validation to the RPC endpoint handler:
import re from fastapi import HTTPException from mcpgateway.utils.validators import validate_no_xss # Define valid method patterns VALID_METHOD_PATTERNS = [ r'^[a-zA-Z0-9_-]+-[a-zA-Z0-9_-]+$', # gateway-tool pattern r'^(tools|resources|prompts)/(list|get)$', # built-in methods r'^servers/[a-f0-9-]+/(tools|resources|prompts)/list$' # server methods ] def validate_rpc_method(method: str) -> bool: """Validate RPC method name format""" # First check for XSS patterns try: validate_no_xss(method, "RPC method name") except ValueError: return False # Then check against valid patterns for pattern in VALID_METHOD_PATTERNS: if re.match(pattern, method): return True return False @router.post("/rpc") async def handle_rpc(request: dict): method = request.get("method", "") if not validate_rpc_method(method): return { "jsonrpc": "2.0", "error": { "code": -32602, # Invalid params "message": "Invalid method name format", "data": f"Method name must match pattern: [gateway-name]-[tool-name] or built-in methods" }, "id": request.get("id") } # Continue with normal RPC processing...
-
Consider implementing a method registry or enum for valid built-in methods
-
Add strict validation for the gateway-tool separator pattern
Additional Context:
- JSON-RPC 2.0 specification suggests using error code -32602 for invalid parameters
- Method names should be restricted to alphanumeric characters, hyphens, underscores, and forward slashes for paths
- This validation should occur before any database lookups or business logic
Testing Considerations:
- Test with various injection patterns: SQL injection, XSS, command injection
- Test with valid method names to ensure they still work:
time-server-get-system-time
tools/list
servers/[uuid]/tools/list
- Test with edge cases: empty string, very long strings, unicode characters
- Ensure error messages don't leak sensitive information
Security Implications:
- Current behavior could be exploited for error-based information disclosure
- Method names might be logged without sanitization
- Could be part of a larger attack chain if combined with other vulnerabilities
Related Issues:
- [Security]: Add input validation for main API endpoints (depends on #339 /admin API validation) #340 (Non-admin API input validation)
- Consider implementing a global input validation middleware for all endpoints
- Similar validation might be needed for JSON-RPC
params
field