Skip to content

Security

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

Security

The MATLAB MCP server implements multi-layered security controls to enable safe code execution while protecting against misuse. This page covers authentication, authorization, code validation, and operational hardening.

graph TB
    subgraph "Client Layer"
        Agent["AI Agent<br/>(Claude, Codex, Cursor)"]
        HTTP["HTTP/SSE Request<br/>with Bearer Token"]
    end
    
    subgraph "Authentication Layer"
        Auth["BearerAuthMiddleware<br/>(Starlette ASGI)"]
        AuthDB["Token Validation<br/>(MATLAB_MCP_AUTH_TOKEN)"]
    end
    
    subgraph "Session & Authorization"
        Session["Session Manager<br/>(Workspace Isolation)"]
        Scope["Tool Scope Check<br/>(execute vs admin)"]
    end
    
    subgraph "Code Security Layer"
        Validator["SecurityValidator<br/>(MATLAB Code Analysis)"]
        Blocklist["Blocked Functions<br/>(system, unix, eval, ...)"]
        StringStrip["String Literal Stripping<br/>(Avoid False Positives)"]
    end
    
    subgraph "Execution & Output"
        Executor["JobExecutor<br/>(Sandboxed Execution)"]
        Output["Result Formatting<br/>(No Code Leakage)"]
    end
    
    subgraph "Infrastructure"
        Cleanup["Session Cleanup<br/>(Temp Dir Removal)"]
        Audit["Audit Logging<br/>(Events & Metrics)"]
    end
    
    Agent -->|Plain HTTP| HTTP
    HTTP -->|401 if missing/invalid| Auth
    Auth --> AuthDB
    AuthDB -->|Valid token| Session
    Session --> Scope
    Scope -->|Check tool access| Validator
    Validator --> Blocklist
    Blocklist --> StringStrip
    StringStrip -->|Approved code| Executor
    Executor --> Output
    Output --> Agent
    Executor --> Cleanup
    Validator --> Audit
    Audit --> Cleanup
Loading

Authentication and Authorization

Bearer Token Authentication

All HTTP-based transports (streamable HTTP and SSE) enforce bearer token authentication via the BearerAuthMiddleware class.

How It Works

  1. Client sends request with Authorization: Bearer <token> header
  2. Middleware validates token against the configured secret (from MATLAB_MCP_AUTH_TOKEN environment variable)
  3. Valid token → request proceeds to MCP layer
  4. Invalid/missing token → server returns HTTP 401 JSON response

Configuration

# Generate a secure token
matlab-mcp --generate-token

# Output:
# Bearer Token: 1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p
#
# Add to your shell:
# export MATLAB_MCP_AUTH_TOKEN=1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p

Token Source

  • Environment variable (recommended): MATLAB_MCP_AUTH_TOKEN

    • Set once per deployment; rotation requires updating env vars
    • Works in Docker, K8s, systemd, supervisord, CI/CD pipelines
    • Example:
      export MATLAB_MCP_AUTH_TOKEN="your-64-char-hex-token"
      matlab-mcp --transport streamable-http
  • Never in config files: Config files can be accidentally committed. Always use environment variables.

Token Format

  • Type: 64-character hex string (256 bits of entropy)
  • Generated via: secrets.token_hex(32) (cryptographically secure)
  • Comparison: Constant-time comparison using hmac.compare_digest() (prevents timing attacks)

Exempt Endpoints

The following endpoints bypass authentication to support health checks and monitoring:

  • GET /health — health status (HTTP 200 or 503)
  • OPTIONS * — CORS pre-flight (allows browser-based clients)

All other endpoints require a valid bearer token.

Scope-Based Authorization

(Planned for v2.1)

Tools will be grouped into two scopes:

Scope Tools Use Case
execute execute_code, check_code, get_workspace, upload_data, delete_file, list_files, read_*, custom tools AI agents executing code
admin get_pool_status, cancel_job, server lifecycle commands Server operators only

For now, all authenticated users have full access. Future versions will support granular token claims.

Transport-Specific Behavior

Transport Auth Required Notes
stdio No Single-user, local only. Auth not applicable.
streamable-http Yes Recommended for remote agents. Bearer token enforced.
sse (deprecated) Yes Legacy multi-user transport. Bearer token enforced.

Input Validation and Sanitization

MATLAB Code Validation

All user-provided MATLAB code is validated before execution using the SecurityValidator class.

Blocked Functions Detection

The validator checks code against a default blocklist:

security:
  blocked_functions_enabled: true
  blocked_functions:
    - "system"      # Execute OS commands
    - "unix"        # Execute Unix commands
    - "dos"         # Execute DOS/Windows commands
    - "!"           # Shell escape operator
    - "eval"        # Execute arbitrary string as MATLAB code
    - "feval"       # Call function by string name
    - "evalc"       # Evaluate with captured output
    - "evalin"      # Evaluate in different workspace
    - "assignin"    # Assign variable in different workspace
    - "perl"        # Execute Perl scripts
    - "python"      # Execute Python scripts
    - "web"         # Open web browser

Smart String/Comment Stripping

To avoid false positives, the validator removes string literals and comments before checking:

% This is SAFE — "system" is in a comment and string:
disp('The operating system is great')    % Safe
msg = "Using system() in strings";       % Safe

% This is BLOCKED — actual function call:
system('rm -rf /')                       % Blocked!

The _strip_string_literals() helper removes:

  • Single-quoted strings: 'string'
  • Double-quoted strings: "string"
  • Line comments: % comment
  • Block comments: %{ ... %}

Customizing the Blocklist

# Disable blocking entirely (not recommended)
security:
  blocked_functions_enabled: false

# Extend the blocklist
security:
  blocked_functions_enabled: true
  blocked_functions:
    - "system"
    - "unix"
    - "dos"
    - "!"
    - "eval"
    - "feval"
    - "evalc"
    - "evalin"
    - "assignin"
    - "perl"
    - "python"
    - "web"
    - "writefile"      # Add custom blocks as needed
    - "writetable"

Filename Sanitization

File uploads and deletions are validated against path traversal and invalid characters:

# Valid filenames:
"data.mat"           # OK
"my_results_v2.csv"  # OK
"figure_2024-01.png" # OK

# Invalid filenames:
"../../etc/passwd"   # Path traversal — REJECTED
"file\nname.txt"     # Newline — REJECTED
"file$name.mat"      # $ character — REJECTED

Allowed characters: [a-zA-Z0-9._-] (alphanumeric, dot, underscore, hyphen)

Workspace Variable Injection

When executing code, the server injects read-only context variables:

__mcp_job_id__     % Unique job identifier (UUID)
__mcp_session_id__ % Session identifier
__mcp_temp_dir__   % Session temp directory path

These enable helper functions like mcp_progress() to report progress without user input.

Security-Related Configuration Options

Server Config

server:
  host: "127.0.0.1"           # Bind to localhost by default (no Windows firewall UAC)
  port: 8765                   # IANA registered port for MCP
  transport: "streamable-http" # Recommended: "stdio", "streamable-http", or "sse"

Recommendation: Default 127.0.0.1 prevents accidental network exposure. Change to 0.0.0.0 only when deploying behind a reverse proxy with authentication.

Security Config

security:
  blocked_functions_enabled: true
  blocked_functions: [...]          # See "Blocked Functions" section above
  workspace_isolation: true          # Clear workspace between sessions
  upload_max_size_mb: 100            # Max file upload size
  filename_max_length: 255           # Max filename length

Workspace isolation is critical for multi-user deployments. When enabled:

clear all
clear global
clear functions
fclose all
restoredefaultpath

Session Config

session:
  max_sessions: 50                   # Prevent resource exhaustion
  session_timeout_seconds: 3600      # 1 hour idle timeout
  temp_cleanup_on_disconnect: true   # Delete temp files when session ends

Monitoring & Audit

monitoring:
  enabled: true
  store_path: "metrics.db"           # SQLite for audit log
  events:
    - "execution_started"
    - "execution_completed"
    - "execution_failed"
    - "blocked_function_attempt"     # Logged when validator blocks code
    - "upload_attempted"
    - "session_created"
    - "session_destroyed"

Best Practices for Secure Deployment

Personal/Local Use

# Single-user, no network exposure
matlab-mcp --transport stdio

# No authentication needed; socket-based communication with local tool

Team Server (Internal Network)

# config.yaml
server:
  transport: "streamable-http"
  host: "0.0.0.0"
  port: 8765

security:
  blocked_functions_enabled: true
  workspace_isolation: true
  require_proxy_auth: false  # You're using bearer token instead
# Terminal
export MATLAB_MCP_AUTH_TOKEN="your-secure-token"
matlab-mcp --config config.yaml

Network setup:

  • Deploy on a private network (VPN, intranet, corporate LAN)
  • Share the bearer token via secure channel (1Password, Vault, GitOps secret)
  • Agents connect with: http://internal-host:8765/mcp

Production (Internet-Facing)

# config.yaml
server:
  transport: "streamable-http"
  host: "127.0.0.1"          # Bind to localhost ONLY
  port: 8765

security:
  blocked_functions_enabled: true
  workspace_isolation: true

Network setup:

  1. Reverse proxy (nginx, Caddy, Traefik) with:
    • TLS termination (HTTPS)
    • Reverse proxy auth (Basic Auth, OAuth2, API key validation)
    • Rate limiting
  2. Server receives traffic from proxy only, never from internet directly
  3. Agents connect via: https://your-domain.com/mcp

Example nginx config:

server {
    listen 443 ssl;
    server_name your-domain.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    location /mcp {
        # Require Authorization header (agent sets this)
        auth_request /validate_token;
        
        proxy_pass http://127.0.0.1:8765;
        proxy_set_header Authorization $http_authorization;
        proxy_set_header Host $host;
    }
    
    location /validate_token {
        # Custom auth validation (can call external service)
        proxy_pass http://auth-service:9000;
    }
}

Docker Deployment

FROM python:3.12-slim

# Install MATLAB Engine API
COPY matlab_engine*.tar.gz /tmp/
RUN pip install /tmp/matlab_engine*.tar.gz

# Install MCP server
RUN pip install matlab-mcp-python

# Non-root user
RUN useradd -m matlab_mcp
USER matlab_mcp

EXPOSE 8765

# Token from environment variable
CMD ["matlab-mcp", "--transport", "streamable-http", "--host", "0.0.0.0"]

Run with:

docker run \
  -e MATLAB_MCP_AUTH_TOKEN="your-token" \
  -e MATLAB_ROOT="/opt/matlab" \
  -v /opt/matlab:/opt/matlab:ro \
  -p 8765:8765 \
  matlab-mcp:latest

Kubernetes Deployment

apiVersion: v1
kind: Secret
metadata:
  name: matlab-mcp-auth
type: Opaque
stringData:
  token: "your-secure-token"

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: matlab-mcp
spec:
  replicas: 1  # Elastic engine pool doesn't scale horizontally
  selector:
    matchLabels:
      app: matlab-mcp
  template:
    metadata:
      labels:
        app: matlab-mcp
    spec:
      containers:
      - name: mcp
        image: matlab-mcp:latest
        env:
        - name: MATLAB_MCP_AUTH_TOKEN
          valueFrom:
            secretKeyRef:
              name: matlab-mcp-auth
              key: token
        ports:
        - containerPort: 8765
        resources:
          requests:
            memory: "2Gi"
            cpu: "1"
          limits:
            memory: "4Gi"
            cpu: "2"
        livenessProbe:
          httpGet:
            path: /health
            port: 8765
          initialDelaySeconds: 30
          periodSeconds: 10

Reporting Security Vulnerabilities

If you discover a security vulnerability in the MATLAB MCP server:

  1. Do NOT open a public GitHub issue
  2. Email: security@hansur94.dev with:
    • Description of the vulnerability
    • Steps to reproduce
    • Potential impact
    • Suggested fix (if you have one)

We aim to respond within 48 hours and will coordinate a fix and disclosure timeline with you.

Vulnerability Disclosure Policy

  • Private disclosure period: Up to 90 days
  • Credit: Your name/organization in release notes (if desired)
  • CVE request: We will request a CVE for critical vulnerabilities
  • Public disclosure: GitHub Security Advisory after fix is released

Known Limitations

Issue Status Workaround
Regex-based code validation (not a parser) By design Enable auto_check_before_execute: true in config
SSE transport deprecated v2.0+ Use streamable-http instead
No token rotation during runtime Planned v2.1 Restart server to rotate tokens
No per-tool scopes (yet) Planned v2.1 Use admin tokens carefully

See Also

Clone this wiki locally