Skip to content

Input Validation & Output Sanitization

Overview

ContextForge provides comprehensive input validation and output sanitization to protect against common security vulnerabilities including:

  • Path Traversal: Prevents access to files outside allowed directories
  • Command Injection: Blocks shell metacharacters in parameters
  • SQL Injection: Validates and escapes SQL parameters
  • XSS Attacks: Sanitizes output to remove dangerous content
  • Control Character Injection: Removes ANSI escape sequences and control characters

Configuration

Environment Variables

# Enable experimental validation (default: false)
EXPERIMENTAL_VALIDATE_IO=true

# Enable validation middleware (default: false)
VALIDATION_MIDDLEWARE_ENABLED=true

# Strict mode - reject on violations (default: true)
VALIDATION_STRICT=true

# Sanitize output responses (default: true)
SANITIZE_OUTPUT=true

# Allowed root paths for resource access (JSON array or comma-separated)
ALLOWED_ROOTS='["/srv/data", "/var/app"]'

# Maximum path depth (default: 10)
MAX_PATH_DEPTH=10

# Maximum parameter length (default: 10000)
MAX_PARAM_LENGTH=10000

# Dangerous patterns (regex, JSON array)
DANGEROUS_PATTERNS='["[;&|`$(){}\\[\\]<>]", "\\.\\.[\\\/]", "[\\x00-\\x1f\\x7f-\\x9f]"]'

Roll-out Phases

The validation feature supports a phased roll-out approach:

Phase 0: Feature Flag (Off by Default)

EXPERIMENTAL_VALIDATE_IO=false  # Disabled in production

Phase 1: Log-Only Mode (Dev/Staging)

EXPERIMENTAL_VALIDATE_IO=true
VALIDATION_STRICT=false  # Warn only, don't block

Phase 2: Enforce in Staging

EXPERIMENTAL_VALIDATE_IO=true
VALIDATION_STRICT=true  # Block violations

Phase 3: Production Deployment

EXPERIMENTAL_VALIDATE_IO=true
VALIDATION_STRICT=true
SANITIZE_OUTPUT=true

Validation Rules

Path Traversal Defense

Scenario: Reject resource path traversal

# Configuration
MCP_GW_ROOT="/srv/data"

# Attack attempt
uri = "/srv/data/../../secret.txt"

# Result: 400 "invalid_path: Path traversal detected"
# No files outside "/srv/data" are accessed

Implementation:

  • Normalizes paths using Path.resolve()
  • Checks for .. sequences
  • Validates against ALLOWED_ROOTS
  • Enforces MAX_PATH_DEPTH limit

Command Injection Prevention

Scenario: Prevent command injection via filename

# Tool that shells out with filename parameter
filename = "bobbytables.jpg; cat /etc/passwd"

# Strict mode: Rejects with 422 "validation_failed"
# Non-strict mode: Escapes value using shlex.quote()

Protected Patterns:

  • Shell metacharacters: ; & | \ $ ( ) { } [ ] < >`
  • Command chaining: &&, ||, ;
  • Pipe operators: |
  • Backticks and command substitution

SQL Injection Prevention

Scenario: Validate SQL parameters

# Dangerous input
param = "'; DROP TABLE users; --"

# Strict mode: Rejects with 422 "validation_failed"
# Non-strict mode: Escapes quotes

Protected Patterns:

  • Quote characters: ', "
  • SQL comments: --, /* */
  • SQL keywords: UNION, SELECT, INSERT, UPDATE, DELETE, DROP

Output Sanitization

Scenario: Sanitize tool output

# Tool returns text with control characters
output = "Result: \x1b[31mError\x1b[0m\x00"

# Sanitized output
clean = "Result: Error"

# Control chars removed, Content-Type verified

Sanitization Rules:

  • Removes C0 control characters (0x00-0x1F) except newlines/tabs
  • Removes ANSI escape sequences
  • Removes C1 control characters (0x7F-0x9F)
  • Preserves \n (newline) and \t (tab)
  • Verifies Content-Type matches payload

Tool Description Content Validation

Scenario: MCP server tools whose descriptions contain Markdown syntax fail to register

Blocked patterns: >, <, &&, ||, $(

These shell metacharacters are blocked by default in ToolCreate and ToolUpdate to reduce injection risk from externally-sourced tool metadata. However, they are common in Markdown content (e.g. > blockquote, < input). Note: single pipes (|), semicolons (;), and backticks (`) are explicitly allowed as they commonly appear in natural-language documentation and Markdown tables.

Control variables:

Variable Default Effect
TOOL_DESCRIPTION_FORBIDDEN_PATTERNS_ENABLED true Master switch — set to false to disable all pattern checks
TOOL_DESCRIPTION_FORBIDDEN_PATTERNS ["&&", "||", "$(", "> ", "< "] Override the blocked substrings (JSON array)
VALIDATION_STRICT true When false, matched patterns log a warning instead of rejecting

Option 1 — Customize the pattern list (recommended):

# Keep injection checks but allow pipe and redirect syntax in descriptions
TOOL_DESCRIPTION_FORBIDDEN_PATTERNS=["&&", "||", "$("]

Option 2 — Disable pattern checks entirely:

TOOL_DESCRIPTION_FORBIDDEN_PATTERNS_ENABLED=false

Option 3 — Warn-only mode (all patterns checked but never rejected):

VALIDATION_STRICT=false

When VALIDATION_STRICT=false: - The forbidden-pattern check in ToolCreate.validate_description and ToolUpdate.validate_description logs a warning and proceeds instead of raising a validation error. - All other sanitization (XSS, length truncation) still runs.

Upgrade note (v0.9.0 → v1.0.0.Beta2)

The forbidden-pattern check was introduced in v1.0.0.Beta2. If you are upgrading from v0.9.0 and your MCP servers expose tools with Markdown descriptions, set VALIDATION_STRICT=false or customize TOOL_DESCRIPTION_FORBIDDEN_PATTERNS to allow the specific characters your tools use.

JSON Schema Validation

Scenario: Validate tool and prompt schemas during registration

# Tool registration with invalid schema
tool = {
    "name": "invalid_tool",
    "inputSchema": {
        "type": "object",
        "properties": {"arg": {"type": "unknown_type"}} # Invalid type
    }
}

# Strict mode (Default): Rejects with 400 Bad Request
# Non-strict mode: Logs warning but accepts registration

Control variable: JSON_SCHEMA_VALIDATION_STRICT (default: true)

Validation Rules: - Enforces valid JSON Schema 2020-12 (default) - Validates structural integrity of inputSchema for tools - Validates arguments schema for tool prompts - prevents registration of broken tools that would fail at runtime

API Usage

SecurityValidator Class

from mcpgateway.common.validators import SecurityValidator

# Validate shell parameters
safe_param = SecurityValidator.validate_shell_parameter("filename.txt")

# Validate paths
safe_path = SecurityValidator.validate_path("/srv/data/file.txt", ["/srv/data"])

# Validate SQL parameters
safe_sql = SecurityValidator.validate_sql_parameter("user_input")

# Sanitize output
clean_text = SecurityValidator.sanitize_text("Text\x1b[31mwith\x1b[0mcolors")

# Sanitize JSON responses
clean_data = SecurityValidator.sanitize_json_response({
    "message": "Hello\x1bWorld",
    "items": ["test\x00", "clean"]
})

ValidationMiddleware

The middleware automatically validates all incoming requests when enabled:

# In main.py
from mcpgateway.middleware.validation_middleware import ValidationMiddleware

if settings.validation_middleware_enabled:
    app.add_middleware(ValidationMiddleware)

Testing

Unit Tests

import pytest
from mcpgateway.common.validators import SecurityValidator

def test_path_traversal_blocked():
    """Test path traversal is blocked."""
    with pytest.raises(ValueError, match="Path traversal"):
        SecurityValidator.validate_path("../../../etc/passwd")

def test_command_injection_blocked():
    """Test command injection is blocked."""
    with pytest.raises(ValueError, match="shell metacharacters"):
        SecurityValidator.validate_shell_parameter("file; rm -rf /")

def test_output_sanitization():
    """Test output sanitization removes control chars."""
    result = SecurityValidator.sanitize_text("Hello\x1b[31mWorld\x00")
    assert result == "HelloWorld"

Integration Tests

# Test path traversal protection
curl -X POST http://localhost:4444/resources \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"uri": "../../../etc/passwd"}'
# Expected: 400 Bad Request

# Test command injection protection
curl -X POST http://localhost:4444/tools/call \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"name": "convert", "arguments": {"file": "test; cat /etc/passwd"}}'
# Expected: 422 Validation Failed (strict mode)

Metrics & Monitoring

Log Messages

[VALIDATION] Input validation failed: Parameter contains shell metacharacters
[VALIDATION] Path traversal detected: ../../../etc/passwd
[SECURITY] Path validation failed: Path outside allowed roots

Prometheus Metrics

# Validation failures
mcpgateway_validation_failures_total{type="path_traversal"} 5
mcpgateway_validation_failures_total{type="command_injection"} 2
mcpgateway_validation_failures_total{type="sql_injection"} 1

# Sanitization operations
mcpgateway_sanitization_operations_total{type="output"} 1234

Security Best Practices

1. Enable Validation in Production

Always enable validation in production environments:

EXPERIMENTAL_VALIDATE_IO=true
VALIDATION_STRICT=true
SANITIZE_OUTPUT=true

2. Configure Allowed Roots

Restrict resource access to specific directories:

ALLOWED_ROOTS='["/srv/data", "/var/app/uploads"]'

3. Use Strict Mode

Enable strict mode to reject invalid input:

VALIDATION_STRICT=true

4. Monitor Validation Failures

Set up alerts for validation failures:

# Prometheus alert
- alert: HighValidationFailureRate
  expr: rate(mcpgateway_validation_failures_total[5m]) > 10
  annotations:
    summary: "High rate of validation failures detected"

5. Regular Security Audits

Review validation logs regularly:

# Check for validation failures
grep "VALIDATION" /var/log/mcpgateway.log | tail -100

# Check for security warnings
grep "SECURITY" /var/log/mcpgateway.log | tail -100

Troubleshooting

Issue: Legitimate Paths Blocked

Symptom: Valid file paths are rejected

Solution: Add path to ALLOWED_ROOTS:

ALLOWED_ROOTS='["/srv/data", "/var/app", "/opt/resources"]'

Issue: MCP Server Tools Fail to Register with "unsafe characters" Error

Symptom:

All N tools failed validation. First error: Validation failed for tool 'X':
[{'type': 'value_error', 'loc': ('description',),
  'msg': "Value error, Description contains unsafe characters: '> '", ...}]

Cause: The tool's description field contains a shell metacharacter (>, <, &&, ||, $() that is blocked by default. This is common with Markdown-formatted descriptions. Note: single pipes (|), semicolons (;), and backticks (`) are allowed as they commonly appear in natural-language documentation.

Solution (pick one):

# Option 1: Customize the pattern list to allow specific characters
TOOL_DESCRIPTION_FORBIDDEN_PATTERNS=["&&", "||", "$("]

# Option 2: Disable pattern checks entirely
TOOL_DESCRIPTION_FORBIDDEN_PATTERNS_ENABLED=false

# Option 3: Warn-only mode (log but don't reject)
VALIDATION_STRICT=false

Note: EXPERIMENTAL_VALIDATE_IO=false and JSON_SCHEMA_VALIDATION_STRICT=false do not affect this check — only VALIDATION_STRICT and TOOL_DESCRIPTION_FORBIDDEN_PATTERNS_ENABLED do.

Issue: Tool Parameters Escaped

Symptom: Tool receives escaped parameters

Solution: Disable strict mode for specific tools or use non-strict mode:

VALIDATION_STRICT=false  # Escape instead of reject

Issue: Output Appears Corrupted

Symptom: Output missing formatting

Solution: Control characters were sanitized. This is expected behavior for security.

Upstream Spec Proposal

Validation Clause

Servers MUST treat all inbound values as untrusted and validate them against JSON Schema or allow-lists.

Path-Safety Clause

Resource paths MUST resolve inside configured roots; otherwise reject with 400 status.

Dangerous-Sink Clause

Parameters passed to shells/SQL MUST be escaped or rejected to prevent injection attacks.

Output-Sanitization Clause

Before emission, servers SHOULD strip control chars and MUST ensure MIME correctness.

References