ollama/server/mcp_security_config.go

152 lines
5.2 KiB
Go

package server
import (
"path/filepath"
"strings"
)
// =============================================================================
// MCP Security Configuration
// =============================================================================
//
// SECURITY REVIEW: This file defines the security policies that control which
// commands can be executed as MCP servers and what arguments/environment they
// can receive. Changes to this file should be reviewed by security-aware
// maintainers.
//
// Key security surfaces:
// - BlockedCommands: Prevents execution of dangerous system commands
// - BlockedMetacharacters: Prevents shell injection attacks
// - FilteredEnvironmentVars: Prevents credential leakage to MCP servers
//
// Threat model:
// - Malicious MCP server configs attempting to execute system commands
// - Shell injection through tool arguments
// - Credential theft through environment variable access
//
// =============================================================================
// MCPSecurityConfig defines security policies for MCP servers
type MCPSecurityConfig struct {
// Commands that are never allowed as MCP servers
BlockedCommands []string
// Shell metacharacters that are not allowed in arguments
BlockedMetacharacters []string
// Environment variables that should be filtered
FilteredEnvironmentVars []string
}
// DefaultSecurityConfig returns the default security configuration.
//
// SECURITY REVIEW: This function defines the default blocklists. Adding or
// removing entries has direct security implications. Consider:
// - Why is a command being added/removed?
// - What attack vectors does it enable/prevent?
// - Are there bypass possibilities (symlinks, PATH manipulation)?
func DefaultSecurityConfig() *MCPSecurityConfig {
return &MCPSecurityConfig{
// SECURITY: Blocked commands - these can never be used as MCP server commands.
// Rationale: These commands could be used for privilege escalation,
// arbitrary file manipulation, or establishing network connections.
BlockedCommands: []string{
// Shells - prevent arbitrary command execution
"sh", "bash", "zsh", "fish", "csh", "ksh", "dash", "tcsh",
"cmd", "cmd.exe", "powershell", "powershell.exe", "pwsh", "pwsh.exe",
// System commands - prevent privilege escalation and system damage
"sudo", "su", "doas", "runas", "pkexec",
"rm", "del", "rmdir", "format", "dd", "shred",
"kill", "killall", "pkill", "shutdown", "reboot",
"systemctl", "service", "init",
// Network tools - prevent data exfiltration and network attacks
"curl", "wget", "nc", "netcat", "telnet", "ssh", "scp", "sftp",
"nmap", "ping", "traceroute", "dig", "nslookup",
// Script interpreters - prevent arbitrary code execution
"eval", "exec", "source", ".",
"perl", "ruby", "php", "lua", "tcl",
// File manipulation - prevent permission/ownership changes
"chmod", "chown", "chgrp", "mount", "umount",
"ln", "mkfifo", "mknod",
// Package managers - prevent system modification
"apt", "apt-get", "yum", "dnf", "pacman", "zypper",
"brew", "port", "snap", "flatpak",
},
// SECURITY: Shell metacharacters - block these in arguments to prevent injection.
// These characters could be used to chain commands or redirect I/O.
BlockedMetacharacters: []string{
";", "|", "&", "$(", "`", ">", "<", ">>", "<<",
"||", "&&", "\n", "\r", "$", "!", "*", "?", "=",
},
// SECURITY: Environment variables to filter - prevent credential leakage.
// MCP servers should not have access to credentials in the parent environment.
FilteredEnvironmentVars: []string{
// AWS
"AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN",
// Cloud providers
"GOOGLE_APPLICATION_CREDENTIALS", "AZURE_CLIENT_SECRET",
// API Keys
"GITHUB_TOKEN", "GITLAB_TOKEN", "OPENAI_API_KEY", "ANTHROPIC_API_KEY",
// Database
"DATABASE_URL", "DB_PASSWORD", "MYSQL_ROOT_PASSWORD", "POSTGRES_PASSWORD",
// Authentication
"JWT_SECRET", "SESSION_SECRET", "AUTH_TOKEN", "API_KEY", "API_SECRET",
// SSH
"SSH_AUTH_SOCK", "SSH_AGENT_PID",
},
}
}
// IsCommandAllowed checks if a command is allowed by security policy
func (c *MCPSecurityConfig) IsCommandAllowed(command string) bool {
baseName := filepath.Base(command)
for _, blocked := range c.BlockedCommands {
if baseName == blocked || strings.HasSuffix(command, "/"+blocked) {
return false
}
}
return true
}
// HasShellMetacharacters checks if a string contains shell metacharacters
func (c *MCPSecurityConfig) HasShellMetacharacters(s string) bool {
for _, meta := range c.BlockedMetacharacters {
if strings.Contains(s, meta) {
return true
}
}
return false
}
// ShouldFilterEnvironmentVar checks if an environment variable should be filtered
func (c *MCPSecurityConfig) ShouldFilterEnvironmentVar(key string) bool {
for _, filtered := range c.FilteredEnvironmentVars {
if key == filtered {
return true
}
}
return false
}
// Global security config instance
// NOTE: To add user customization, load from ~/.ollama/mcp-security.json and append to these defaults
var globalSecurityConfig = DefaultSecurityConfig()
// GetSecurityConfig returns the global security configuration
func GetSecurityConfig() *MCPSecurityConfig {
return globalSecurityConfig
}