# 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 ```mermaid 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 ``` --- ## 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: ```bash # 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: ```bash $ 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: ```http 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 HTTP/1.1 200 OK Content-Type: application/json (MCP response body) ``` **Invalid/missing token:** ```http 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: ```yaml 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: ```matlab % 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`: ```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: ```bash # 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 ```yaml 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:** ```matlab % 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: ```matlab 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. ```yaml execution: workspace_isolation: true # Always keep this enabled in shared deployments ``` --- ## Security-Related Configuration Options ### Authentication and Transport ```yaml 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 ```yaml 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 ```yaml security: max_upload_size_mb: 100 # Prevent disk exhaustion execution: temp_dir: "/tmp/matlab_mcp" # Session-isolated subdirectories ``` ### Session Management ```yaml 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 ```yaml 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: ```yaml 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: ```yaml 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):** ```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: ```yaml 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:** ```bash # 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: ```yaml 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** ```dockerfile 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:** ```bash 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](mailto: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 - **MATLAB Engine Safety:** [Mathworks documentation on workspace isolation](https://www.mathworks.com/help/matlab/matlab_external/use-matlab-engine-for-python.html) - **Web Security:** [OWASP Top 10](https://owasp.org/www-project-top-ten/) - **Token-Based Auth:** [RFC 6750 OAuth 2.0 Bearer Token](https://tools.ietf.org/html/rfc6750) - **TLS Best Practices:** [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/)