Skip to content

Security

github-actions[bot] edited this page Apr 3, 2026 · 20 revisions

Security

The MATLAB MCP server implements security across multiple layers: HTTP authentication, MATLAB code validation, workspace isolation, and file upload protection. This page documents the complete security posture.

Architecture Overview

graph TB
    Client["AI Agent Client"]
    Auth["BearerAuthMiddleware<br/>(HTTP Layer)"]
    MCP["FastMCP Server<br/>(MCP Protocol)"]
    CodeVal["SecurityValidator<br/>(MATLAB Code)"]
    Engine["MATLAB Engine<br/>(Workspace)"]
    
    Client -->|Bearer Token| Auth
    Auth -->|401 if Invalid| Client
    Auth -->|Valid Token| MCP
    MCP -->|execute_code| CodeVal
    CodeVal -->|Blocked?| Client
    CodeVal -->|Safe Code| Engine
    Engine -->|Result| MCP
    MCP -->|Response| Client
Loading

Authentication & Authorization

Bearer Token Authentication

The server enforces HTTP bearer token authentication on all HTTP/SSE transports. Tokens are never stored in config files — only in the MATLAB_MCP_AUTH_TOKEN environment variable.

Token Generation

Generate a new 64-character hex token using the CLI:

matlab-mcp --generate-token

Output:

Generated bearer token: a1b2c3d4e5f6...7z8y9x0w
Export it as:

  BASH/POSIX:
  export MATLAB_MCP_AUTH_TOKEN="a1b2c3d4e5f6...7z8y9x0w"

  Windows CMD:
  set MATLAB_MCP_AUTH_TOKEN=a1b2c3d4e5f6...7z8y9x0w

  Windows PowerShell:
  $env:MATLAB_MCP_AUTH_TOKEN="a1b2c3d4e5f6...7z8y9x0w"

Token Validation

On every HTTP request, the middleware:

  1. Extracts the Authorization header
  2. Checks for the format Bearer <token>
  3. Compares the token using constant-time comparison (hmac.compare_digest) to prevent timing attacks
  4. Returns HTTP 401 with WWW-Authenticate: Bearer realm="MATLAB MCP Server" header if invalid

Invalid requests return:

{
  "error": "unauthorized",
  "message": "Invalid or missing bearer token"
}

Endpoints That Bypass Auth

  • /health — Health check for load balancers (no auth required)
  • OPTIONS * — CORS preflight requests (no auth required)
  • stdio transport — Single-user mode, no HTTP layer, no auth needed

Disabling Authentication

If MATLAB_MCP_AUTH_TOKEN is not set, authentication is disabled:

# No token env var set → auth disabled
matlab-mcp --transport streamablehttp
# Server binds to http://127.0.0.1:8765/mcp with no auth

Warning: This is only safe for single-user, localhost-only deployments.

Recommended Auth Configuration

For secure HTTP deployments:

# Generate and export token
export MATLAB_MCP_AUTH_TOKEN=$(python -c "import secrets; print(secrets.token_hex(32))")

# Start server with auth enabled
matlab-mcp --transport streamablehttp

Agent examples with bearer token:

# Claude Code (claude_desktop_config.json)
{
  "mcpServers": {
    "matlab": {
      "command": "bash",
      "args": ["-c", "MATLAB_MCP_AUTH_TOKEN=$MATLAB_MCP_AUTH_TOKEN matlab-mcp --transport stdio"],
      "env": {
        "MATLAB_MCP_AUTH_TOKEN": "your-token-here"
      }
    }
  }
}
# Codex CLI (mcp.toml)
[[mcpServers]]
name = "matlab"
type = "streamable-http"
url = "http://127.0.0.1:8765/mcp"
headers = { "Authorization" = "Bearer your-token-here" }

MATLAB Code Validation

Function Blocklist

By default, these dangerous MATLAB functions are blocked:

Function Risk Alternative
system() Execute arbitrary OS commands Use MATLAB built-ins instead
unix() Execute Unix commands Use built-ins
dos() Execute DOS/Windows commands Use built-ins
! Shell escape operator Use built-ins
eval() Execute arbitrary string as code Use feval() with safe inputs
feval() Dynamic function calls by name Pre-whitelist function names
evalc() Evaluate and capture output Use explicit output variables
evalin() Evaluate in arbitrary scope Avoid cross-scope execution
assignin() Assign variables in arbitrary scope Use function outputs instead
perl() Execute Perl scripts Not available, skip
python() Execute Python scripts Not available, skip

Smart String & Comment Stripping

The validator strips string literals and comments before scanning, preventing false positives:

% ✓ SAFE — "system" is in a comment:
% The system() function is dangerous

% ✓ SAFE — "system" is in a string:
msg = 'Operating system type';

% ✗ BLOCKED — actual function call:
system('ls -la')

Custom Blocklist

Override the default blocklist in config.yaml:

security:
  blocked_functions_enabled: true
  blocked_functions:
    - "system"
    - "unix"
    - "dos"
    - "!"
    - "eval"
    - "feval"
    - "evalc"
    - "evalin"
    - "assignin"
    - "perl"
    - "python"
    - "web"          # Add custom entries here
    - "importdata"   # Example: block if needed

Set blocked_functions_enabled: false to disable validation entirely (not recommended for multi-user deployments):

security:
  blocked_functions_enabled: false  # Disables ALL code validation

Workspace Isolation

Per-Session Cleanup

When workspace_isolation: true (default), the server clears variables between sessions:

clear all;           % Remove all local variables
clear global;        % Remove global variables
clear functions;     % Clear function definitions
fclose all;          % Close open files
restoredefaultpath;  % Reset MATLAB search path

This prevents one session's variables, functions, and file handles from leaking to another.

Session-Scoped Temp Directories

  • stdio transport: Single session, single temp directory (shared across all code)
  • HTTP/SSE transport: Each client gets a unique session with its own temp directory
  • Stateless HTTP mode: Each request gets an ephemeral temp directory (deleted after response)

Session Timeout

Sessions expire after session_timeout seconds of inactivity (default 3600 = 1 hour). Expired sessions are cleaned up automatically, and their temp files are deleted if temp_cleanup_on_disconnect: true (default).

File Upload & Download Protection

Upload Size Limits

Configure the maximum upload size in config.yaml:

output:
  max_upload_size_mb: 100  # Default: 100MB

Uploads exceeding this limit are rejected with an error.

Filename Sanitization

Uploaded and downloaded filenames are validated against injection attacks:

  • Allowed characters: [a-zA-Z0-9._-]
  • Path traversal blocked: Filenames like ../../etc/passwd are rejected
  • Absolute paths rejected: Filenames starting with / or C:\ are rejected

Example rejected filenames:

../../etc/passwd     ✗ Path traversal
/etc/passwd          ✗ Absolute path
C:\Windows\System32  ✗ Absolute path
file<script>.mat     ✗ Invalid characters

Allowed filenames:

data.mat             ✓
my-simulation.xlsx   ✓
results_2024_01.csv  ✓

Human-in-the-Loop Approval Gates

When configured, the server can prompt an operator for approval before executing sensitive operations:

hitl:
  approval_gates: true           # Enable HITL
  approve_all_execute: false     # Require approval for every code execution
  approve_protected_functions: true  # Require approval for dangerous ops
  approve_file_operations: true  # Require approval for uploads/deletes

Protected functions include those in the blocklist plus I/O operations (fopen, save, load, etc.).

When approval is required, the MCP server pauses execution and waits for human approval via the HumanApproval elicitation:

{
  "type": "elicit",
  "name": "HumanApproval",
  "title": "Approve Code Execution",
  "description": "Agent wants to execute: clf; plot(x, y); ylabel('Value')",
  "fields": {
    "approved": {
      "type": "boolean",
      "description": "Approve this action?"
    }
  }
}

Configuration Security Practices

Environment Variable Overrides

All sensitive settings can be overridden via environment variables using the MATLAB_MCP_* prefix:

# Override auth token
export MATLAB_MCP_AUTH_TOKEN="your-secret-token"

# Override session timeout
export MATLAB_MCP_SESSION_TIMEOUT=7200

# Override blocked functions
export MATLAB_MCP_BLOCKED_FUNCTIONS="system,eval"

Environment variables always take precedence over config.yaml, so you can commit a safe default config and override it securely at runtime.

Config File Permissions

Store config.yaml with restricted permissions:

chmod 600 config.yaml  # Only owner can read

If the file contains any token-like field (deprecated pattern), the server logs a WARNING at startup:

WARNING: Potential token found in config.yaml. Use MATLAB_MCP_AUTH_TOKEN env var instead.

Deployment Security by Scenario

Personal/Local Development

server:
  transport: "stdio"  # Single process, no auth needed
  host: "127.0.0.1"

security:
  blocked_functions_enabled: true  # Default blocklist
  workspace_isolation: true

Auth: Not needed (stdio has no HTTP layer).

Team Server (Shared Internal Network)

server:
  transport: "streamablehttp"
  host: "127.0.0.1"  # Loopback only; agents on same machine
  port: 8765

security:
  blocked_functions_enabled: true
  workspace_isolation: true
  max_upload_size_mb: 100

Auth: Recommended. Generate a shared token and distribute via environment variable or secrets manager.

Networking: Place behind a reverse proxy (nginx, Caddy) with TLS if exposing to multiple machines.

Production / Corporate Deployment

server:
  transport: "streamablehttp"
  host: "127.0.0.1"  # Reverse proxy only
  port: 8765         # Not exposed directly

security:
  blocked_functions_enabled: true
  blocked_functions:
    # Extend with company-specific blocks
    - "system"
    - "eval"
    - "fopen"        # Prevent file I/O if not needed
  
  workspace_isolation: true
  max_upload_size_mb: 50

hitl:
  approval_gates: true
  approve_protected_functions: true
  approve_file_operations: true

Auth: Required. Use MATLAB_MCP_AUTH_TOKEN environment variable with a strong, randomly generated token. Rotate tokens periodically by restarting the server with a new token.

Networking:

  • Reverse proxy (nginx/Caddy) with TLS termination
  • Restrict network access to approved subnets
  • Monitor logs for failed auth attempts
  • Use firewall rules to whitelist agent sources

Monitoring:

  • Enable metrics collection (monitoring.enabled: true)
  • Log all code execution (tools.execute_code.log_all: true)
  • Set up alerting on:
    • Blocked function attempts
    • Failed auth attempts (HTTP 401)
    • Sessions exceeding time limits
    • Errors in MATLAB execution

Security Incident Response

Log Locations

  • MATLAB MCP logs: Controlled by server.log_level and printed to stderr
  • HTTP access logs: Captured by reverse proxy (if deployed)
  • Metrics & events: Stored in SQLite at monitoring.database_path (default: .matlab_mcp/metrics.db)

Detecting Attacks

Failed auth attempts:

grep "401\|Unauthorized" /var/log/nginx/access.log

Blocked function attempts:

grep "BlockedFunctionError\|blocked" matlab_mcp.log

Session abuse (many sessions from one IP):

grep "session_id\|Session" matlab_mcp.log | uniq -c | sort -rn

Recovery Steps

  1. Revoke compromised token: Stop the server, generate a new token, restart with new MATLAB_MCP_AUTH_TOKEN
  2. Review logs: Check which code was executed during compromise window
  3. Reset workspace: Restart the server to clear all sessions and temporary files
  4. Update blocklist: Add any functions discovered in the attack to blocked_functions

Security Limitations & Trade-offs

Known Limitations

Limitation Impact Mitigation
Regex-based code validation Sophisticated regex evasion possible (e.g., eval_ aliased via feval) Use in conjunction with reverse proxy auth; assume agents are semi-trusted
No code sandboxing Blocked code can still be executed via workarounds Run on isolated machine; use Linux namespaces / containers if available
Tokens are static Token compromise requires server restart to revoke Rotate tokens regularly; monitor for failed auth attempts
No audit logging Cannot track which agent executed which code Enable metrics (monitoring.enabled: true) for metadata; add syslog integration

Transport Security

Transport Auth TLS Use Case
stdio None (by design) N/A Single-user, local development only
SSE (deprecated) Optional middleware Requires reverse proxy Legacy multi-user, not recommended
Streamable HTTP Bearer token required Requires reverse proxy Multi-user, recommended

Best Practices

  1. Use environment variables for all secrets — Never commit tokens to config.yaml
  2. Require bearer tokens on all HTTP deployments — Set MATLAB_MCP_AUTH_TOKEN before starting
  3. Use a reverse proxy with TLS — Encrypt tokens in transit
  4. Enable workspace isolationworkspace_isolation: true (default)
  5. Monitor blocked function attempts — Log them and investigate
  6. Rotate tokens periodically — At least quarterly; more often if shared across teams
  7. Restrict the blocklist thoughtfully — Over-blocking breaks legitimate use; under-blocking is a security risk
  8. Use HITL approval gates for sensitive operations — Require human sign-off on protected functions in production
  9. Segregate production instances — Don't share a server between teams; use network isolation
  10. Keep MATLAB updated — Security patches are released regularly

See Also

Clone this wiki locally