Skip to content

Security

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

Security

The MATLAB MCP Server implements multiple security layers to prevent misuse while keeping MATLAB accessible to AI agents. This page documents authentication, authorization, input validation, secure deployment practices, and vulnerability reporting.

Architecture

graph TD
    A["HTTP Request / stdio Message"] -->|Bearer Token| B["BearerAuthMiddleware"]
    B -->|Validation via HMAC| C{"Token Valid?"}
    C -->|No| D["401 Unauthorized"]
    C -->|Yes| E["MCP Layer"]
    E -->|Code Submission| F["SecurityValidator"]
    F -->|Blocked Fn Check| G{"Function Safe?"}
    G -->|No| H["BlockedFunctionError"]
    G -->|Yes| I["SessionManager"]
    I -->|Workspace Isolation| J["EnginePoolManager"]
    J -->|Acquire Engine| K["Execute in Session"]
    K -->|Result| L["ResultFormatter"]
    L -->|Sanitize Output| M["Send Response"]
    
    style A fill:#e1f5ff
    style B fill:#fff3e0
    style F fill:#f3e5f5
    style I fill:#e8f5e9
    style M fill:#fce4ec
Loading

Authentication and Authorization

Bearer Token Authentication

The server enforces HTTP Bearer token authentication on HTTP and SSE transports. The stdio transport does not use HTTP and therefore bypasses HTTP-level auth (suitable for local, single-user, or containerized scenarios where network isolation is provided externally).

Token Configuration

Tokens are read exclusively from the MATLAB_MCP_AUTH_TOKEN environment variable at server startup:

# Generate a 64-character random token
MATLAB_MCP_AUTH_TOKEN=$(python -c "import secrets; print(secrets.token_hex(32))")

# Export for the server process
export MATLAB_MCP_AUTH_TOKEN

# Start the server
python -m matlab_mcp --transport streamablehttp

Or use the built-in --generate-token flag:

$ python -m matlab_mcp --generate-token

Generated token (copy to your environment):

  MATLAB_MCP_AUTH_TOKEN=a7f3e2c5b9d1f4a6e8c2b7f1d4a6c9e2

For Bash/Zsh:
  export MATLAB_MCP_AUTH_TOKEN=a7f3e2c5b9d1f4a6e8c2b7f1d4a6c9e2

For Windows PowerShell:
  $env:MATLAB_MCP_AUTH_TOKEN='a7f3e2c5b9d1f4a6e8c2b7f1d4a6c9e2'

For Windows Command Prompt:
  set MATLAB_MCP_AUTH_TOKEN=a7f3e2c5b9d1f4a6e8c2b7f1d4a6c9e2

Request Validation

Every HTTP request must include the token in the Authorization header:

GET /mcp HTTP/1.1
Host: 127.0.0.1:8765
Authorization: Bearer a7f3e2c5b9d1f4a6e8c2b7f1d4a6c9e2
Content-Type: application/json

Token Comparison: Uses constant-time comparison (hmac.compare_digest) to prevent timing attacks.

Bypassed Endpoints:

  • /health — Health checks do not require auth (allows monitoring tools to verify server status)
  • OPTIONS requests — CORS pre-flight requests bypass auth

Disabled-by-Default: When MATLAB_MCP_AUTH_TOKEN is not set, auth middleware is disabled and all requests are accepted (suitable for development or when network-level auth is provided externally).

Responses

Valid token:

HTTP/1.1 200 OK
Content-Type: application/json

(MCP response body)

Invalid/missing token:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="MATLAB MCP Server"
Content-Type: application/json

{"error": "Invalid or missing Authorization header"}

CORS Configuration (HTTP/SSE Transports)

For browser-based agents and cross-origin requests:

server:
  cors_origins: "*"          # Allow any origin
  cors_methods: ["GET", "POST", "OPTIONS"]
  cors_allow_credentials: false

All HTTP and SSE transports automatically wire CORS middleware (Starlette CORSMiddleware) to handle preflight requests.


Input Validation and Sanitization

MATLAB Code Validation

Before executing any MATLAB code, the SecurityValidator performs static analysis:

Function Blocklist

By default, these MATLAB functions are blocked to prevent privilege escalation, code injection, and system compromise:

Function Risk Example Block
system() Execute arbitrary OS commands system('rm -rf /')
unix() Execute Unix shell commands unix('curl malicious.com')
dos() Execute DOS/Windows commands dos('del C:\Windows\System32')
! Shell escape operator !shutdown /s
eval() Execute arbitrary string as code eval(['delete(' file ')'])
feval() Call function by name (dynamic) feval(user_input)
evalc() Evaluate and capture output evalc(user_input)
evalin() Evaluate in caller/base workspace evalin('base', code)
assignin() Assign variables in other workspaces assignin('base', 'x', user_var)
perl() Execute Perl scripts perl('system("ls -la")')
python() Execute Python scripts `python('os.system("...")')
web() Open external browser (SSRF risk) web('http://internal-server')

Smart String/Comment Stripping

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

% These are SAFE and will NOT be blocked:
title('The system is great')             % "system" inside a string
msg = "unix-based";                      % "unix" inside string literal
% system('ls')                           % "system" inside comment
disp('Running: system(''id'')')          % Nested quotes, still a string

% This WILL be blocked:
result = system('whoami')                % Actual function call
cmd = '!ls'; eval(cmd)                   % Indirect eval of shell command

Customizing the Blocklist

In config.yaml:

security:
  blocked_functions_enabled: true       # Set false to disable entirely
  blocked_functions:                    # Override defaults
    - "system"
    - "unix"
    - "dos"
    - "!"
    - "eval"
    - "feval"
    - "evalc"
    - "evalin"
    - "assignin"
    - "perl"
    - "python"
    - "web"

Or via environment variable:

# Disable blocking entirely (not recommended for production)
export MATLAB_MCP_SECURITY_BLOCKED_FUNCTIONS_ENABLED=false

# Or set a custom list (JSON array)
export MATLAB_MCP_SECURITY_BLOCKED_FUNCTIONS='["system", "eval"]'

File Upload and Filename Sanitization

Size Limits

security:
  max_upload_size_mb: 100               # Default: 100 MB per file

Uploads exceeding this limit are rejected before writing to disk.

Filename Sanitization

Filenames are restricted to alphanumeric characters, dots, hyphens, and underscores to prevent:

  • Path traversal: ../../etc/passwd → rejected
  • Control character injection: NULL bytes, newlines → rejected
  • OS-specific attacks: : in Windows, leading - in shell commands → rejected

Allowed characters: [a-zA-Z0-9._-]

Examples:

% These are ALLOWED:
upload_data('measurement_2024-03-15.csv')
upload_data('signal-processing_v1.0.mat')

% These are BLOCKED:
upload_data('../../../etc/passwd')       % Path traversal
upload_data('data\nmalicious')           % Newline injection
upload_data('file\x00.mat')              % Null byte injection

Workspace Isolation

Each session runs in an isolated MATLAB workspace. Between sessions (when workspace_isolation: true, the default), the server executes:

clear all;          % Clear all variables
clear global;       % Clear global variables
clear functions;    % Clear persistent function state
fclose all;         % Close all file handles
restoredefaultpath; % Reset MATLAB path to defaults

This ensures one user's variables, loaded functions, and file handles do not leak to another user in a multi-user deployment.

execution:
  workspace_isolation: true  # Always keep this enabled in shared deployments

Security-Related Configuration Options

Authentication and Transport

server:
  transport: "streamablehttp"  # "stdio" | "sse" | "streamablehttp"
  host: "127.0.0.1"           # Default: localhost only (prevents Windows Firewall popups)
  port: 8765                    # Any port > 1024 (no admin needed on Windows)

security:
  require_proxy_auth: false    # Set true if behind a reverse proxy with auth
Option Default Purpose
transport "stdio" Transport mode (see best practices below)
host "127.0.0.1" Bind address (loopback = no firewall issues on Windows)
require_proxy_auth false Suppress warning if auth is handled by reverse proxy

Code Safety

security:
  blocked_functions_enabled: true
  blocked_functions: [...]
  
execution:
  workspace_isolation: true
  sync_timeout: 5.0                      # Seconds (prevents hung jobs)
  
pool:
  health_check_interval: 30               # Seconds (detect crashed engines)

File Operations

security:
  max_upload_size_mb: 100                 # Prevent disk exhaustion
  
execution:
  temp_dir: "/tmp/matlab_mcp"            # Session-isolated subdirectories

Session Management

sessions:
  max_sessions: 100                       # Prevent resource exhaustion
  session_timeout: 3600                   # 1 hour idle timeout
  temp_cleanup_on_disconnect: true        # Delete session files when session ends

Monitoring and Audit

monitoring:
  enabled: true
  metrics_db: "monitoring/metrics.db"    # SQLite backend
  
server:
  log_level: "INFO"                       # Set "DEBUG" for detailed audit logs

Best Practices for Secure Deployment

1. Local Development (stdio transport)

Suitable when the developer runs the server and agent on the same machine:

server:
  transport: "stdio"

Security profile:

  • ✅ No network exposure
  • ✅ No auth needed (OS-level isolation)
  • ✅ Simplest setup

Recommended for: Claude Code desktop, Cursor, personal projects


2. Team Server Behind Reverse Proxy (HTTP/streamablehttp transport)

Suitable when multiple team members need access via a shared server:

server:
  transport: "streamablehttp"
  host: "127.0.0.1"
  port: 8765

security:
  require_proxy_auth: true              # Acknowledge reverse proxy handles auth

Network setup:

[Agent on Engineer's Machine]
            ↓ (HTTPS)
      [Reverse Proxy (nginx/Caddy)]
      ├─ TLS termination
      ├─ Authentication (OAuth 2.0, OIDC, Basic Auth)
      ├─ Rate limiting
      └─ Logging/audit
            ↓ (HTTP, localhost only)
      [MATLAB MCP Server (127.0.0.1:8765)]

Reverse proxy example (nginx):

server {
    listen 443 ssl;
    server_name matlab-mcp.company.com;
    ssl_certificate /etc/ssl/certs/cert.pem;
    ssl_certificate_key /etc/ssl/private/key.pem;

    auth_request /oauth2/auth;  # Your auth handler

    location / {
        proxy_pass http://127.0.0.1:8765;
        proxy_set_header Authorization $http_authorization;
        proxy_read_timeout 300s;  # Jobs may take time
        proxy_http_version 1.1;
    }
}

Security profile:

  • ✅ TLS encryption in transit
  • ✅ User authentication at proxy layer
  • ✅ Bearer token auth inside server (defense-in-depth)
  • ✅ No firewall exceptions needed
  • ⚠️ Proxy must trust the server (use internal network or VPN)

Recommended for: Team deployments, CI/CD integration, Codex CLI


3. Public Internet (HTTP + Streamable HTTP + Bearer Tokens)

For agents that need remote access via untrusted networks:

server:
  transport: "streamablehttp"
  host: "0.0.0.0"              # Only if using reverse proxy with TLS
  port: 8765

security:
  max_upload_size_mb: 50       # Stricter limits for untrusted clients
  blocked_functions_enabled: true
  blocked_functions: [...]     # Review for your use case

Network setup:

[Remote Agent]
        ↓ (HTTPS via TLS Terminator)
   [Cloudflare / AWS API Gateway / nginx]
   ├─ TLS encryption (mandatory)
   ├─ OAuth 2.0 / OIDC (mandatory)
   ├─ Rate limiting
   ├─ DDoS protection
   └─ IP whitelisting (if possible)
        ↓ (HTTP, internal network)
   [MATLAB MCP Server]

Environment:

# Set strong token (64+ characters of random data)
export MATLAB_MCP_AUTH_TOKEN=$(python -c "import secrets; print(secrets.token_hex(32))")

# Minimal engine pool (fewer engines = fewer resource risks)
export MATLAB_MCP_POOL_MIN_ENGINES=1
export MATLAB_MCP_POOL_MAX_ENGINES=4

# Short timeouts (prevent hung jobs consuming resources)
export MATLAB_MCP_EXECUTION_SYNC_TIMEOUT=10

# Aggressive session cleanup
export MATLAB_MCP_SESSIONS_SESSION_TIMEOUT=600  # 10 minutes
export MATLAB_MCP_SESSIONS_TEMP_CLEANUP_ON_DISCONNECT=true

Security profile:

  • ✅✅✅ TLS encryption (mandatory)
  • ✅✅✅ OAuth 2.0 user authentication (mandatory)
  • ✅ Bearer token server-side auth (defense-in-depth)
  • ⚠️ High-trust infrastructure required
  • ⚠️ Monitor for abuse

Recommended for: Enterprise integrations with external parties, public APIs, SaaS deployments


4. Windows 10 No-Admin Deployment

The server defaults to 127.0.0.1 binding to avoid Windows Firewall UAC prompts when running without admin rights:

server:
  host: "127.0.0.1"    # Never change this to "0.0.0.0" unless absolutely needed
  port: 8765

Why loopback?

  • ✅ No Firewall exception required
  • ✅ No UAC prompts
  • ✅ No admin rights needed
  • ⚠️ Only accessible from the same machine

If you need remote access on Windows, use a reverse proxy on a higher-privilege host that connects back to 127.0.0.1:8765.


5. Docker Containerized Deployment

FROM python:3.11-slim

# Install MATLAB Engine (or skip for inspect-only mode)
COPY matlab-engine.whl /tmp/
RUN pip install /tmp/matlab-engine.whl

# Install MCP server
RUN pip install matlab-mcp-python[monitoring]

# Copy config
COPY config.yaml /app/config.yaml

# Run with bearer token from env
ENV MATLAB_MCP_AUTH_TOKEN=${AUTH_TOKEN}
ENV MATLAB_MCP_POOL_MIN_ENGINES=2
ENV MATLAB_MCP_POOL_MAX_ENGINES=8

EXPOSE 8765

CMD ["python", "-m", "matlab_mcp", "--config", "/app/config.yaml", "--transport", "streamablehttp"]

Kubernetes secret:

kubectl create secret generic matlab-mcp-auth \
  --from-literal=token=$(python -c "import secrets; print(secrets.token_hex(32))")

# Reference in pod spec:
# env:
# - name: MATLAB_MCP_AUTH_TOKEN
#   valueFrom:
#     secretKeyRef:
#       name: matlab-mcp-auth
#       key: token

Vulnerability Reporting

If you discover a security vulnerability in the MATLAB MCP Server, please report it responsibly:

DO NOT:

  • ❌ Open a public GitHub issue with vulnerability details
  • ❌ Post in discussions or forums
  • ❌ Email the maintainer's personal account (no guarantee of response)

DO:

  • ✅ Email security@example.com with:

    • Description of the vulnerability
    • Steps to reproduce
    • Potential impact
    • Suggested fix (optional)
  • ✅ Allow 7–14 days for a response

  • ✅ Expect an acknowledgment, timeframe, and patch schedule

  • ✅ Coordinate public disclosure with the maintainers after a fix is available

Response Timeline

  • Day 1–3: Acknowledgment and initial triage
  • Day 7–14: Fix verified in development branch
  • Day 14–21: Fix released in a patch version
  • Day 21: Public disclosure (GitHub advisory, release notes)

Supported Versions

Version Status Security Updates
2.x (current) Active Yes, security patches released within 7 days
1.x Maintenance Critical issues only, no minor fixes
0.x EOL No updates

Security Checklist

Use this checklist before deploying to production:

  • Authentication

    • MATLAB_MCP_AUTH_TOKEN is set to a 64+ character random value
    • Token is stored securely (K8s secret, env var, not in config file)
    • All HTTP/SSE endpoints behind TLS (reverse proxy or mTLS)
  • Authorization

    • Reverse proxy authenticates users before routing to server
    • Session timeout is set appropriately for your use case
    • Max sessions limit prevents resource exhaustion
  • Code Safety

    • blocked_functions_enabled: true (default)
    • Blocklist reviewed for your MATLAB use case
    • workspace_isolation: true (always in multi-user)
  • File Operations

    • max_upload_size_mb set to a sensible limit
    • Session temp directories cleaned up on disconnect
    • No world-writable paths in temp_dir
  • Deployment

    • Server bound to 127.0.0.1 (unless behind reverse proxy)
    • TLS enabled on reverse proxy (HTTPS, not HTTP)
    • Rate limiting configured at proxy layer
    • Monitoring/alerting enabled for failed authentications
  • Monitoring

    • monitoring.enabled: true
    • SQLite metrics database on a persistent volume
    • Alerts configured for:
      • High error rates
      • Engine pool exhaustion
      • Repeated failed authentications
      • Large uploads
  • Documentation

    • Deployment architecture documented
    • Incident response plan in place
    • Maintainers aware of production deployments

References

Clone this wiki locally