-
Notifications
You must be signed in to change notification settings - Fork 0
Security
The MATLAB MCP Server implements comprehensive security controls to prevent misuse while keeping MATLAB accessible to AI agents across different deployment scenarios.
graph LR
Agent["AI Agent"]
Agent -->|stdio<br/>single session| Server["MCP Server<br/>(Local)"]
Agent -->|SSE over HTTP<br/>multi-session| Proxy["Reverse Proxy<br/>(nginx, Caddy)"]
Proxy -->|localhost:8765<br/>authenticated| Server
Server -->|Per-session<br/>isolation| Sessions["Session Manager<br/>Temp Directory Isolation"]
Stdio Transport (Single User)
- Default for local development and single-user deployments
- No authentication mechanism (process-level isolation provided by OS)
- One implicit "default" session per server instance
SSE Transport (Multi-User)
- Exposes HTTP endpoints for long-lived connections
- MUST be deployed behind a reverse proxy with authentication
- The server does NOT provide built-in authentication (by design)
- Each authenticated request gets its own session ID
- Sessions are isolated via dedicated temp directories
security:
require_proxy_auth: true # Acknowledges reverse proxy is in place
server:
transport: "sse"
host: "127.0.0.1" # Bind to localhost only
port: 8765 # Expose only to proxyWhen SSE is enabled without require_proxy_auth: true, the server logs a SECURITY WARNING at startup:
WARNING: SSE transport enabled without require_proxy_auth=true.
This server should only be exposed to the internet via a reverse proxy
with authentication (OAuth2, JWT, mTLS, etc.).
Example nginx reverse proxy with HTTP Basic Auth:
upstream matlab_mcp {
server localhost:8765;
}
server {
listen 443 ssl http2;
server_name matlab.example.com;
ssl_certificate /etc/ssl/certs/matlab.crt;
ssl_certificate_key /etc/ssl/private/matlab.key;
auth_basic "MATLAB MCP Server";
auth_basic_user_file /etc/nginx/.htpasswd;
location / {
proxy_pass http://matlab_mcp;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}The SecurityValidator enforces a blocklist of dangerous functions before code execution:
# From src/matlab_mcp/security/validator.py
blocked_functions = [
"system", # Execute arbitrary OS commands
"unix", # Execute Unix commands
"dos", # Execute DOS/Windows commands
"!", # Shell escape operator
"eval", # Execute arbitrary string as code
"feval", # Call function by name string
"evalc", # Evaluate and capture output
"evalin", # Evaluate in caller/base workspace
"assignin", # Assign variable in caller/base workspace
"perl", # Execute Perl scripts
"python", # Execute Python scripts
]The validator strips string literals and comments before pattern matching:
% SAFE (will NOT be blocked):
disp('The operating system is great') % "system" in string literal
% system('ls') % "system" in comment
msg = "unix-based systems"; % "unix" in double-quoted string
function systematic_approach() % "system" as part of word (boundary check)
% BLOCKED (actual dangerous calls):
system('rm -rf /') % system() call
!ls -la % Shell escape
eval('disp(''malicious'')') % eval() callImplementation Detail: The regex patterns use \b word boundaries to avoid matching substrings like "systematic", and preprocess code to remove:
- Single-quoted strings:
'...'(with escape handling for'') - Double-quoted strings:
"..." - Line comments:
% ... - Block comments:
%{ ... %}
All file operations (upload, read, delete) sanitize filenames to prevent path traversal:
# REJECTED (path traversal attempts):
"../../../etc/passwd"
"..\\..\\windows\\system32\\drivers\\etc\\hosts"
"/etc/passwd"
"C:\\Windows\\System32\\config\\SAM"
# ACCEPTED (safe filenames):
"data.csv"
"my_results.mat"
"plot_2024-01-15.png"
"signal_processing-v2.m"Validation Rules:
- Characters allowed:
[a-zA-Z0-9._-]plus path separators/(normalized to current dir) - No leading
/or\ - No
..sequences - No special characters that could break filesystem operations
security:
max_upload_size_mb: 100 # Default 100MB
# For each file type
max_mat_file_size_mb: 500
max_csv_size_mb: 50Oversized uploads return a failed status with diagnostic:
{
"status": "failed",
"error": "Upload size 250MB exceeds limit 100MB"
}All security settings are in the security: section of config.yaml:
security:
# Function blocklist enforcement
blocked_functions_enabled: true
blocked_functions:
- "system"
- "unix"
- "dos"
- "!"
- "eval"
- "feval"
- "evalc"
- "evalin"
- "assignin"
- "perl"
- "python"
# Upload protection
max_upload_size_mb: 100
# Workspace isolation between sessions
workspace_isolation: true
# SSE-specific: acknowledge reverse proxy is in place
require_proxy_auth: false # Set to true for SSE deployments
# Session cleanup
session_timeout: 3600 # seconds; idle sessions expire
temp_cleanup_on_disconnect: trueserver:
transport: "stdio"
security:
blocked_functions_enabled: true
workspace_isolation: false # Not needed for single userserver:
transport: "sse"
host: "127.0.0.1"
port: 8765
security:
blocked_functions_enabled: true
require_proxy_auth: true
workspace_isolation: true
session_timeout: 3600
temp_cleanup_on_disconnect: trueserver:
transport: "sse"
host: "127.0.0.1"
port: 8765
security:
blocked_functions_enabled: true
blocked_functions:
- "system"
- "unix"
- "dos"
- "!"
- "eval"
- "feval"
- "evalc"
- "evalin"
- "assignin"
- "perl"
- "python"
- "web" # Add web() if not needed
- "urlread" # Restrict external network access
require_proxy_auth: true
workspace_isolation: true
session_timeout: 1800 # Shorter timeout
temp_cleanup_on_disconnect: true
max_upload_size_mb: 50 # Tighter limitTo customize which functions are blocked:
- Identify your use case: Do you need signal processing, image processing, parallel computing, etc.?
- Review the default blocklist: Are there functions you legitimately need that are blocked?
- Update config.yaml:
security:
blocked_functions_enabled: true
blocked_functions:
- "system"
- "unix"
- "dos"
- "!"
- "eval"
- "feval"
- "evalin"
# Removed 'perl' and 'python' if needed for interop
# Add custom functions you want to block
- "my_dangerous_function"- Disable entirely (not recommended):
security:
blocked_functions_enabled: false # All functions allowedBest Practice: Even if you disable the blocklist, the server provides audit events for all blocked function attempts, visible in monitoring logs for security analysis.
graph TB
Internet["Internet / VPN"]
Internet -->|TLS| ProxyLB["Load Balancer<br/>(optional)"]
ProxyLB -->|mTLS| Proxy["Reverse Proxy<br/>with Auth<br/>(nginx/Caddy)"]
Proxy -->|localhost:8765<br/>no TLS needed| Server["MATLAB MCP Server"]
Server -->|localhost:MATLAB_PORT| MATLAB["MATLAB Engine"]
Server -->|optional| Store["Metrics DB<br/>(SQLite)"]
Key Points:
- Server listens on
127.0.0.1(localhost only) - All authentication/encryption handled by reverse proxy
- mTLS optional for proxy ↔ server connection (same machine)
- MATLAB engine is local, not exposed to network
Each authenticated user gets:
- Unique session ID
- Dedicated temporary directory
- Optional workspace reset (
clear all) between code executions - Automatic cleanup after timeout or disconnect
sessions:
max_sessions: 10
session_timeout: 3600 # 1 hour
temp_cleanup_on_disconnect: true
job_retention_seconds: 86400 # 24 hoursEnable monitoring to track all code execution, blocked attempts, and system health:
monitoring:
enabled: true
db_path: "/data/metrics/matlab-mcp.db"
sample_interval: 30 # secondsVisit the dashboard at http://localhost:8766/dashboard to see:
- Real-time metrics: Pool utilization, job throughput, execution times
- Event log: All code executions, blocked attempts, errors, session creations
- Health status: Engine pool status, memory usage, error rates
Deploy in Docker with volume mounts for isolation:
# docker-compose.yml
services:
matlab-mcp:
image: matlab-mcp:latest
volumes:
- ./config.yaml:/app/config.yaml:ro
- ./custom_tools.yaml:/app/custom_tools.yaml:ro
- matlab-data:/data # Persistent results
- matlab-results:/tmp/matlab-mcp-results
networks:
- internal
environment:
MATLAB_MCP_SECURITY__REQUIRE_PROXY_AUTH: "true"
MATLAB_MCP_SECURITY__WORKSPACE_ISOLATION: "true"
nginx:
image: nginx:latest
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
ports:
- "443:443"
networks:
- internal
- external
networks:
internal:
internal: true # Not accessible from host
external:
driver: bridge- Review audit logs: Check monitoring event log for unexpected blocked attempts
- Rotate credentials: Update reverse proxy auth secrets regularly
- Update MATLAB: Keep MATLAB engine updated for security patches
- Monitor metrics: Watch for unusual utilization patterns or error spikes
-
Dependency scanning: Run
pip-auditto check Python dependencies for CVEs
If you discover a security vulnerability, please do not open a public GitHub issue. Instead:
-
Email: Send details to the project maintainers (check repository README for contact)
-
Information to include:
- Vulnerability description
- Steps to reproduce
- Potential impact
- Suggested fix (if available)
-
Timeline: Expect acknowledgment within 48 hours; fixes typically released within 1-2 weeks
-
Credit: You will be credited in release notes unless you prefer to remain anonymous
We follow responsible disclosure practices:
- Fixes are developed in private
- Security patch released before public disclosure
- CVE assigned if applicable
- Your contribution is acknowledged (with permission)
graph TB
Request["Incoming Request"]
Request -->|Proxy auth| Auth["Authentication<br/>(reverse proxy)"]
Auth -->|Session ID| Session["Session Manager<br/>Workspace Isolation"]
Session -->|Code + Job ID| Validator["SecurityValidator<br/>Blocklist Check"]
Validator -->|Filename sanitize| Upload["File Upload Handler<br/>Size + Path Limits"]
Upload -->|Workspace injected| Execute["JobExecutor<br/>Runs in isolated temp dir"]
Execute -->|Monitor access| Monitor["Monitoring<br/>Audit Log Events"]
Execute -->|Results| Formatter["ResultFormatter<br/>Truncate large outputs"]
Formatter -->|Response| Response["MCP Response"]
style Auth fill:#90EE90
style Session fill:#87CEEB
style Validator fill:#FFB6C1
style Upload fill:#FFD700
style Monitor fill:#DDA0DD
Summary: The MATLAB MCP Server is designed to be secure by default while remaining configurable for different threat models. Use the recommended configurations for your deployment scenario, monitor actively, and report any security issues responsibly.