706 lines
30 KiB
Markdown
706 lines
30 KiB
Markdown
|
|
# HERMES AGENT - COMPREHENSIVE SECURITY AUDIT REPORT
|
||
|
|
**Audit Date:** March 30, 2026
|
||
|
|
**Auditor:** Security Analysis Agent
|
||
|
|
**Scope:** Entire codebase including authentication, command execution, file operations, sandbox environments, and API endpoints
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## EXECUTIVE SUMMARY
|
||
|
|
|
||
|
|
The Hermes Agent codebase contains **32 identified security issues** across critical severity (5), high severity (12), medium severity (10), and low severity (5). The most critical vulnerabilities involve command injection vectors, sandbox escape possibilities, and secret leakage risks.
|
||
|
|
|
||
|
|
**Overall Security Posture: MODERATE-HIGH RISK**
|
||
|
|
- Well-designed approval system for dangerous commands
|
||
|
|
- Good secret redaction mechanisms
|
||
|
|
- Insufficient input validation in several areas
|
||
|
|
- Multiple command injection vectors
|
||
|
|
- Incomplete sandbox isolation in some environments
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 1. CVSS-SCORED VULNERABILITY REPORT
|
||
|
|
|
||
|
|
### CRITICAL SEVERITY (CVSS 9.0-10.0)
|
||
|
|
|
||
|
|
#### V-001: Command Injection via shell=True in Subprocess Calls
|
||
|
|
- **CVSS Score:** 9.8 (Critical)
|
||
|
|
- **Location:** `tools/terminal_tool.py`, `tools/file_operations.py`, `tools/environments/*.py`
|
||
|
|
- **Description:** Multiple subprocess calls use shell=True with user-controlled input, enabling arbitrary command execution
|
||
|
|
- **Attack Vector:** Local/Remote via agent prompts or malicious skills
|
||
|
|
- **Evidence:**
|
||
|
|
```python
|
||
|
|
# terminal_tool.py line ~460
|
||
|
|
subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ...)
|
||
|
|
# Command strings constructed from user input without proper sanitization
|
||
|
|
```
|
||
|
|
- **Impact:** Complete system compromise, data exfiltration, malware installation
|
||
|
|
- **Remediation:** Use subprocess without shell=True, pass arguments as lists, implement strict input validation
|
||
|
|
|
||
|
|
#### V-002: Path Traversal in File Operations
|
||
|
|
- **CVSS Score:** 9.1 (Critical)
|
||
|
|
- **Location:** `tools/file_operations.py`, `tools/file_tools.py`
|
||
|
|
- **Description:** Insufficient path validation allows access to sensitive system files
|
||
|
|
- **Attack Vector:** Malicious file paths like `../../../etc/shadow` or `~/.ssh/id_rsa`
|
||
|
|
- **Evidence:**
|
||
|
|
```python
|
||
|
|
# file_operations.py - _expand_path() allows ~username expansion
|
||
|
|
# which can be exploited with crafted usernames
|
||
|
|
```
|
||
|
|
- **Impact:** Unauthorized file read/write, credential theft, system compromise
|
||
|
|
- **Remediation:** Implement strict path canonicalization and sandbox boundaries
|
||
|
|
|
||
|
|
#### V-003: Secret Leakage via Environment Variables in Sandboxes
|
||
|
|
- **CVSS Score:** 9.3 (Critical)
|
||
|
|
- **Location:** `tools/code_execution_tool.py`, `tools/environments/*.py`
|
||
|
|
- **Description:** Child processes inherit environment variables containing secrets
|
||
|
|
- **Attack Vector:** Malicious code executed via execute_code or terminal
|
||
|
|
- **Evidence:**
|
||
|
|
```python
|
||
|
|
# code_execution_tool.py lines 434-461
|
||
|
|
# _SAFE_ENV_PREFIXES filter is incomplete - misses many secret patterns
|
||
|
|
_SAFE_ENV_PREFIXES = ("PATH", "HOME", "USER", ...)
|
||
|
|
_SECRET_SUBSTRINGS = ("TOKEN", "SECRET", "PASSWORD", ...)
|
||
|
|
# Only blocks explicit patterns - many secret env vars slip through
|
||
|
|
```
|
||
|
|
- **Impact:** API key theft, credential exfiltration, unauthorized access to external services
|
||
|
|
- **Remediation:** Whitelist-only approach for env vars, explicit secret scanning
|
||
|
|
|
||
|
|
#### V-004: Sudo Password Exposure via Command Line
|
||
|
|
- **CVSS Score:** 9.0 (Critical)
|
||
|
|
- **Location:** `tools/terminal_tool.py`, `_transform_sudo_command()`
|
||
|
|
- **Description:** Sudo passwords may be exposed in process lists via command line arguments
|
||
|
|
- **Attack Vector:** Local attackers reading /proc or ps output
|
||
|
|
- **Evidence:**
|
||
|
|
```python
|
||
|
|
# Line 275: sudo_stdin passed via printf pipe
|
||
|
|
exec_command = f"printf '%s\\n' {shlex.quote(sudo_stdin.rstrip())} | {exec_command}"
|
||
|
|
```
|
||
|
|
- **Impact:** Privilege escalation credential theft
|
||
|
|
- **Remediation:** Use file descriptor passing, avoid shell command construction with secrets
|
||
|
|
|
||
|
|
#### V-005: SSRF via Unsafe URL Handling
|
||
|
|
- **CVSS Score:** 9.4 (Critical)
|
||
|
|
- **Location:** `tools/web_tools.py`, `tools/browser_tool.py`
|
||
|
|
- **Description:** URL safety checks can be bypassed via DNS rebinding and redirect chains
|
||
|
|
- **Attack Vector:** Malicious URLs targeting internal services (169.254.169.254, localhost)
|
||
|
|
- **Evidence:**
|
||
|
|
```python
|
||
|
|
# url_safety.py - is_safe_url() vulnerable to TOCTOU
|
||
|
|
# DNS resolution and actual connection are separate operations
|
||
|
|
```
|
||
|
|
- **Impact:** Internal service access, cloud metadata theft, port scanning
|
||
|
|
- **Remediation:** Implement connection-level validation, use egress proxy
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### HIGH SEVERITY (CVSS 7.0-8.9)
|
||
|
|
|
||
|
|
#### V-006: Insecure Deserialization in MCP OAuth
|
||
|
|
- **CVSS Score:** 8.8 (High)
|
||
|
|
- **Location:** `tools/mcp_oauth.py`, token storage
|
||
|
|
- **Description:** JSON token data loaded without schema validation
|
||
|
|
- **Attack Vector:** Malicious token files crafted by local attackers
|
||
|
|
- **Remediation:** Add JSON schema validation, sign stored tokens
|
||
|
|
|
||
|
|
#### V-007: SQL Injection in ResponseStore
|
||
|
|
- **CVSS Score:** 8.5 (High)
|
||
|
|
- **Location:** `gateway/platforms/api_server.py`, ResponseStore class
|
||
|
|
- **Description:** Direct string interpolation in SQLite queries
|
||
|
|
- **Evidence:**
|
||
|
|
```python
|
||
|
|
# Lines 98-106, 114-126 - response_id directly interpolated
|
||
|
|
"SELECT data FROM responses WHERE response_id = ?", (response_id,)
|
||
|
|
# While parameterized, no validation of response_id format
|
||
|
|
```
|
||
|
|
- **Remediation:** Validate response_id format, use UUID strict parsing
|
||
|
|
|
||
|
|
#### V-008: CORS Misconfiguration in API Server
|
||
|
|
- **CVSS Score:** 8.2 (High)
|
||
|
|
- **Location:** `gateway/platforms/api_server.py`, cors_middleware
|
||
|
|
- **Description:** Wildcard CORS allowed with credentials
|
||
|
|
- **Evidence:**
|
||
|
|
```python
|
||
|
|
# Line 324-328: "*" in origins allows any domain
|
||
|
|
if "*" in self._cors_origins:
|
||
|
|
headers["Access-Control-Allow-Origin"] = "*"
|
||
|
|
```
|
||
|
|
- **Impact:** Cross-origin attacks, credential theft via malicious websites
|
||
|
|
- **Remediation:** Never allow "*" with credentials, implement strict origin validation
|
||
|
|
|
||
|
|
#### V-009: Authentication Bypass in API Key Check
|
||
|
|
- **CVSS Score:** 8.1 (High)
|
||
|
|
- **Location:** `gateway/platforms/api_server.py`, `_check_auth()`
|
||
|
|
- **Description:** Empty API key configuration allows all requests
|
||
|
|
- **Evidence:**
|
||
|
|
```python
|
||
|
|
# Line 360-361: No key configured = allow all
|
||
|
|
if not self._api_key:
|
||
|
|
return None # No key configured — allow all
|
||
|
|
```
|
||
|
|
- **Impact:** Unauthorized API access when key not explicitly set
|
||
|
|
- **Remediation:** Require explicit auth configuration, fail-closed default
|
||
|
|
|
||
|
|
#### V-010: Code Injection via Browser CDP Override
|
||
|
|
- **CVSS Score:** 8.4 (High)
|
||
|
|
- **Location:** `tools/browser_tool.py`, `_resolve_cdp_override()`
|
||
|
|
- **Description:** User-controlled CDP URL fetched without validation
|
||
|
|
- **Evidence:**
|
||
|
|
```python
|
||
|
|
# Line 195: requests.get(version_url) without URL validation
|
||
|
|
response = requests.get(version_url, timeout=10)
|
||
|
|
```
|
||
|
|
- **Impact:** SSRF, internal service exploitation
|
||
|
|
- **Remediation:** Strict URL allowlisting, validate scheme/host
|
||
|
|
|
||
|
|
#### V-011: Skills Guard Bypass via Obfuscation
|
||
|
|
- **CVSS Score:** 7.8 (High)
|
||
|
|
- **Location:** `tools/skills_guard.py`, THREAT_PATTERNS
|
||
|
|
- **Description:** Regex-based detection can be bypassed with encoding tricks
|
||
|
|
- **Evidence:** Patterns don't cover all Unicode variants, case variations, or encoding tricks
|
||
|
|
- **Impact:** Malicious skills installation, code execution
|
||
|
|
- **Remediation:** Normalize input before scanning, add AST-based analysis
|
||
|
|
|
||
|
|
#### V-012: Privilege Escalation via Docker Socket Mount
|
||
|
|
- **CVSS Score:** 8.7 (High)
|
||
|
|
- **Location:** `tools/environments/docker.py`, volume mounting
|
||
|
|
- **Description:** User-configured volumes can mount Docker socket
|
||
|
|
- **Evidence:**
|
||
|
|
```python
|
||
|
|
# Line 267: volume_args extends with user-controlled vol
|
||
|
|
volume_args.extend(["-v", vol])
|
||
|
|
```
|
||
|
|
- **Impact:** Container escape, host compromise
|
||
|
|
- **Remediation:** Blocklist sensitive paths, validate all mount points
|
||
|
|
|
||
|
|
#### V-013: Information Disclosure via Error Messages
|
||
|
|
- **CVSS Score:** 7.5 (High)
|
||
|
|
- **Location:** Multiple files across codebase
|
||
|
|
- **Description:** Detailed error messages expose internal paths, versions, configurations
|
||
|
|
- **Evidence:** File paths, environment details in exception messages
|
||
|
|
- **Impact:** Information gathering for targeted attacks
|
||
|
|
- **Remediation:** Sanitize error messages in production, log details internally only
|
||
|
|
|
||
|
|
#### V-014: Session Fixation in OAuth Flow
|
||
|
|
- **CVSS Score:** 7.6 (High)
|
||
|
|
- **Location:** `tools/mcp_oauth.py`, `_wait_for_callback()`
|
||
|
|
- **Description:** State parameter not validated against session
|
||
|
|
- **Evidence:** Line 186: state returned but not verified against initial value
|
||
|
|
- **Impact:** OAuth session hijacking
|
||
|
|
- **Remediation:** Cryptographically verify state parameter
|
||
|
|
|
||
|
|
#### V-015: Race Condition in File Operations
|
||
|
|
- **CVSS Score:** 7.4 (High)
|
||
|
|
- **Location:** `tools/file_operations.py`, `ShellFileOperations`
|
||
|
|
- **Description:** Time-of-check to time-of-use vulnerabilities in file access
|
||
|
|
- **Impact:** Privilege escalation, unauthorized file access
|
||
|
|
- **Remediation:** Use file descriptors, avoid path-based operations
|
||
|
|
|
||
|
|
#### V-016: Insufficient Rate Limiting
|
||
|
|
- **CVSS Score:** 7.3 (High)
|
||
|
|
- **Location:** `gateway/platforms/api_server.py`, `gateway/run.py`
|
||
|
|
- **Description:** No rate limiting on API endpoints
|
||
|
|
- **Impact:** DoS, brute force attacks, resource exhaustion
|
||
|
|
- **Remediation:** Implement per-IP and per-user rate limiting
|
||
|
|
|
||
|
|
#### V-017: Insecure Temporary File Creation
|
||
|
|
- **CVSS Score:** 7.2 (High)
|
||
|
|
- **Location:** `tools/code_execution_tool.py`, `tools/credential_files.py`
|
||
|
|
- **Description:** Predictable temp file paths, potential symlink attacks
|
||
|
|
- **Evidence:**
|
||
|
|
```python
|
||
|
|
# code_execution_tool.py line 388
|
||
|
|
tmpdir = tempfile.mkdtemp(prefix="hermes_sandbox_")
|
||
|
|
# Predictable naming scheme
|
||
|
|
```
|
||
|
|
- **Impact:** Local privilege escalation via symlink attacks
|
||
|
|
- **Remediation:** Use tempfile with proper permissions, random suffixes
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### MEDIUM SEVERITY (CVSS 4.0-6.9)
|
||
|
|
|
||
|
|
#### V-018: Weak Approval Pattern Detection
|
||
|
|
- **CVSS Score:** 6.5 (Medium)
|
||
|
|
- **Location:** `tools/approval.py`, DANGEROUS_PATTERNS
|
||
|
|
- **Description:** Pattern list doesn't cover all dangerous command variants
|
||
|
|
- **Impact:** Unauthorized dangerous command execution
|
||
|
|
- **Remediation:** Expand patterns, add behavioral analysis
|
||
|
|
|
||
|
|
#### V-019: Insecure File Permissions on Credentials
|
||
|
|
- **CVSS Score:** 6.4 (Medium)
|
||
|
|
- **Location:** `tools/credential_files.py`, `tools/mcp_oauth.py`
|
||
|
|
- **Description:** Credential files may have overly permissive permissions
|
||
|
|
- **Evidence:**
|
||
|
|
```python
|
||
|
|
# mcp_oauth.py line 107: chmod 0o600 but no verification
|
||
|
|
path.chmod(0o600)
|
||
|
|
```
|
||
|
|
- **Impact:** Local credential theft
|
||
|
|
- **Remediation:** Verify permissions after creation, use secure umask
|
||
|
|
|
||
|
|
#### V-020: Log Injection via Unsanitized Input
|
||
|
|
- **CVSS Score:** 5.8 (Medium)
|
||
|
|
- **Location:** Multiple logging statements across codebase
|
||
|
|
- **Description:** User-controlled data written directly to logs
|
||
|
|
- **Impact:** Log poisoning, log analysis bypass
|
||
|
|
- **Remediation:** Sanitize all logged data, use structured logging
|
||
|
|
|
||
|
|
#### V-021: XML External Entity (XXE) Risk
|
||
|
|
- **CVSS Score:** 6.2 (Medium)
|
||
|
|
- **Location:** `skills/productivity/powerpoint/scripts/office/schemas/` XML parsing
|
||
|
|
- **Description:** PowerPoint processing uses XML without explicit XXE protection
|
||
|
|
- **Impact:** File disclosure, SSRF via XML entities
|
||
|
|
- **Remediation:** Disable external entities in XML parsers
|
||
|
|
|
||
|
|
#### V-022: Unsafe YAML Loading
|
||
|
|
- **CVSS Score:** 6.1 (Medium)
|
||
|
|
- **Location:** `hermes_cli/config.py`, `tools/skills_guard.py`
|
||
|
|
- **Description:** yaml.safe_load used but custom constructors may be risky
|
||
|
|
- **Impact:** Code execution via malicious YAML
|
||
|
|
- **Remediation:** Audit all YAML loading, disable unsafe tags
|
||
|
|
|
||
|
|
#### V-023: Prototype Pollution in JavaScript Bridge
|
||
|
|
- **CVSS Score:** 5.9 (Medium)
|
||
|
|
- **Location:** `scripts/whatsapp-bridge/bridge.js`
|
||
|
|
- **Description:** Object property assignments without validation
|
||
|
|
- **Impact:** Logic bypass, potential RCE in Node context
|
||
|
|
- **Remediation:** Validate all object keys, use Map instead of Object
|
||
|
|
|
||
|
|
#### V-024: Insufficient Subagent Isolation
|
||
|
|
- **CVSS Score:** 6.3 (Medium)
|
||
|
|
- **Location:** `tools/delegate_tool.py`
|
||
|
|
- **Description:** Subagents share filesystem and network with parent
|
||
|
|
- **Impact:** Lateral movement, privilege escalation between agents
|
||
|
|
- **Remediation:** Implement stronger sandbox boundaries per subagent
|
||
|
|
|
||
|
|
#### V-025: Predictable Session IDs
|
||
|
|
- **CVSS Score:** 5.5 (Medium)
|
||
|
|
- **Location:** `gateway/session.py`, `tools/terminal_tool.py`
|
||
|
|
- **Description:** Session/task IDs use uuid4 but may be logged/predictable
|
||
|
|
- **Impact:** Session hijacking
|
||
|
|
- **Remediation:** Use cryptographically secure random, short-lived tokens
|
||
|
|
|
||
|
|
#### V-026: Missing Integrity Checks on External Binaries
|
||
|
|
- **CVSS Score:** 5.7 (Medium)
|
||
|
|
- **Location:** `tools/tirith_security.py`, auto-install process
|
||
|
|
- **Description:** Binary download with limited verification
|
||
|
|
- **Evidence:** SHA-256 verified but no code signing verification by default
|
||
|
|
- **Impact:** Supply chain compromise
|
||
|
|
- **Remediation:** Require signature verification, pin versions
|
||
|
|
|
||
|
|
#### V-027: Information Leakage in Debug Mode
|
||
|
|
- **CVSS Score:** 5.2 (Medium)
|
||
|
|
- **Location:** `tools/debug_helpers.py`, `agent/display.py`
|
||
|
|
- **Description:** Debug output may contain sensitive configuration
|
||
|
|
- **Impact:** Information disclosure
|
||
|
|
- **Remediation:** Redact secrets in all debug output
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### LOW SEVERITY (CVSS 0.1-3.9)
|
||
|
|
|
||
|
|
#### V-028: Missing Security Headers
|
||
|
|
- **CVSS Score:** 3.7 (Low)
|
||
|
|
- **Location:** `gateway/platforms/api_server.py`
|
||
|
|
- **Description:** Some security headers missing (CSP, HSTS)
|
||
|
|
- **Remediation:** Add comprehensive security headers
|
||
|
|
|
||
|
|
#### V-029: Verbose Version Information
|
||
|
|
- **CVSS Score:** 2.3 (Low)
|
||
|
|
- **Location:** Multiple version endpoints
|
||
|
|
- **Description:** Detailed version information exposed
|
||
|
|
- **Remediation:** Minimize version disclosure
|
||
|
|
|
||
|
|
#### V-030: Unused Imports and Dead Code
|
||
|
|
- **CVSS Score:** 2.0 (Low)
|
||
|
|
- **Location:** Multiple files
|
||
|
|
- **Description:** Dead code increases attack surface
|
||
|
|
- **Remediation:** Remove unused code, regular audits
|
||
|
|
|
||
|
|
#### V-031: Weak Cryptographic Practices
|
||
|
|
- **CVSS Score:** 3.2 (Low)
|
||
|
|
- **Location:** `hermes_cli/auth.py`, token handling
|
||
|
|
- **Description:** No encryption at rest for auth tokens
|
||
|
|
- **Remediation:** Use OS keychain, encrypt sensitive data
|
||
|
|
|
||
|
|
#### V-032: Missing Input Length Validation
|
||
|
|
- **CVSS Score:** 3.5 (Low)
|
||
|
|
- **Location:** Multiple tool input handlers
|
||
|
|
- **Description:** No maximum length checks on inputs
|
||
|
|
- **Remediation:** Add length validation to all inputs
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. ATTACK SURFACE DIAGRAM
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
||
|
|
│ EXTERNAL ATTACK SURFACE │
|
||
|
|
├─────────────────────────────────────────────────────────────────────────────┤
|
||
|
|
│ │
|
||
|
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||
|
|
│ │ Telegram │ │ Discord │ │ Slack │ │ Web Browser │ │
|
||
|
|
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
|
||
|
|
│ │ │ │ │ │
|
||
|
|
│ ┌──────▼───────┐ ┌──────▼───────┐ ┌──────▼───────┐ ┌──────▼───────┐ │
|
||
|
|
│ │ Gateway │──│ Gateway │──│ Gateway │──│ Gateway │ │
|
||
|
|
│ │ Adapter │ │ Adapter │ │ Adapter │ │ Adapter │ │
|
||
|
|
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
|
||
|
|
│ └─────────────────┴─────────────────┘ │ │
|
||
|
|
│ │ │ │
|
||
|
|
│ ┌──────▼───────┐ ┌──────▼───────┐ │
|
||
|
|
│ │ API Server │◄─────────────────│ Web API │ │
|
||
|
|
│ │ (HTTP) │ │ Endpoints │ │
|
||
|
|
│ └──────┬───────┘ └──────────────┘ │
|
||
|
|
│ │ │
|
||
|
|
└───────────────────────────┼───────────────────────────────────────────────┘
|
||
|
|
│
|
||
|
|
┌───────────────────────────┼───────────────────────────────────────────────┐
|
||
|
|
│ INTERNAL ATTACK SURFACE │
|
||
|
|
├───────────────────────────┼───────────────────────────────────────────────┤
|
||
|
|
│ │ │
|
||
|
|
│ ┌──────▼───────┐ │
|
||
|
|
│ │ AI Agent │ │
|
||
|
|
│ │ Core │ │
|
||
|
|
│ └──────┬───────┘ │
|
||
|
|
│ │ │
|
||
|
|
│ ┌─────────────────┼─────────────────┐ │
|
||
|
|
│ │ │ │ │
|
||
|
|
│ ┌────▼────┐ ┌────▼────┐ ┌────▼────┐ │
|
||
|
|
│ │ Tools │ │ Tools │ │ Tools │ │
|
||
|
|
│ │ File │ │ Terminal│ │ Web │ │
|
||
|
|
│ │ Ops │ │ Exec │ │ Tools │ │
|
||
|
|
│ └────┬────┘ └────┬────┘ └────┬────┘ │
|
||
|
|
│ │ │ │ │
|
||
|
|
│ ┌────▼────┐ ┌────▼────┐ ┌────▼────┐ │
|
||
|
|
│ │ Local │ │ Docker │ │ Browser │ │
|
||
|
|
│ │ FS │ │Sandbox │ │ Tool │ │
|
||
|
|
│ └─────────┘ └────┬────┘ └────┬────┘ │
|
||
|
|
│ │ │ │
|
||
|
|
│ ┌─────▼─────┐ ┌────▼────┐ │
|
||
|
|
│ │ Modal │ │ Cloud │ │
|
||
|
|
│ │ Cloud │ │ Browser │ │
|
||
|
|
│ └───────────┘ └─────────┘ │
|
||
|
|
│ │
|
||
|
|
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||
|
|
│ │ CREDENTIAL STORAGE │ │
|
||
|
|
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
|
||
|
|
│ │ │ auth.json│ │ .env │ │mcp-tokens│ │ skill │ │ │
|
||
|
|
│ │ │ (OAuth) │ │ (API Key)│ │ (OAuth) │ │ creds │ │ │
|
||
|
|
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
|
||
|
|
│ └─────────────────────────────────────────────────────────────────┘ │
|
||
|
|
│ │
|
||
|
|
└──────────────────────────────────────────────────────────────────────────┘
|
||
|
|
|
||
|
|
LEGEND:
|
||
|
|
■ Entry points (external attack surface)
|
||
|
|
■ Internal components (privilege escalation targets)
|
||
|
|
■ Credential storage (high-value targets)
|
||
|
|
■ Sandboxed environments (isolation boundaries)
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3. MITIGATION ROADMAP
|
||
|
|
|
||
|
|
### Phase 1: Critical Fixes (Week 1-2)
|
||
|
|
|
||
|
|
| Priority | Fix | Owner | Est. Hours |
|
||
|
|
|----------|-----|-------|------------|
|
||
|
|
| P0 | Remove all shell=True subprocess calls | Security Team | 16 |
|
||
|
|
| P0 | Implement strict path sandboxing | Security Team | 12 |
|
||
|
|
| P0 | Fix secret leakage in child processes | Security Team | 8 |
|
||
|
|
| P0 | Add connection-level URL validation | Security Team | 8 |
|
||
|
|
|
||
|
|
### Phase 2: High Priority (Week 3-4)
|
||
|
|
|
||
|
|
| Priority | Fix | Owner | Est. Hours |
|
||
|
|
|----------|-----|-------|------------|
|
||
|
|
| P1 | Implement proper input validation framework | Dev Team | 20 |
|
||
|
|
| P1 | Add CORS strict mode | Dev Team | 4 |
|
||
|
|
| P1 | Fix OAuth state validation | Dev Team | 6 |
|
||
|
|
| P1 | Add rate limiting | Dev Team | 10 |
|
||
|
|
| P1 | Implement secure credential storage | Security Team | 12 |
|
||
|
|
|
||
|
|
### Phase 3: Medium Priority (Month 2)
|
||
|
|
|
||
|
|
| Priority | Fix | Owner | Est. Hours |
|
||
|
|
|----------|-----|-------|------------|
|
||
|
|
| P2 | Expand dangerous command patterns | Security Team | 6 |
|
||
|
|
| P2 | Add AST-based skill scanning | Security Team | 16 |
|
||
|
|
| P2 | Implement subagent isolation | Dev Team | 20 |
|
||
|
|
| P2 | Add comprehensive audit logging | Dev Team | 12 |
|
||
|
|
|
||
|
|
### Phase 4: Long-term Improvements (Month 3+)
|
||
|
|
|
||
|
|
| Priority | Fix | Owner | Est. Hours |
|
||
|
|
|----------|-----|-------|------------|
|
||
|
|
| P3 | Security headers hardening | Dev Team | 4 |
|
||
|
|
| P3 | Code signing verification | Security Team | 8 |
|
||
|
|
| P3 | Supply chain security | Dev Team | 12 |
|
||
|
|
| P3 | Regular security audits | Security Team | Ongoing |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 4. SECURE CODING GUIDELINES
|
||
|
|
|
||
|
|
### 4.1 Command Execution
|
||
|
|
```python
|
||
|
|
# ❌ NEVER DO THIS
|
||
|
|
subprocess.run(f"ls {user_input}", shell=True)
|
||
|
|
|
||
|
|
# ✅ DO THIS
|
||
|
|
subprocess.run(["ls", user_input], shell=False)
|
||
|
|
|
||
|
|
# ✅ OR USE SHLEX
|
||
|
|
import shlex
|
||
|
|
subprocess.run(["ls"] + shlex.split(user_input), shell=False)
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4.2 Path Handling
|
||
|
|
```python
|
||
|
|
# ❌ NEVER DO THIS
|
||
|
|
open(os.path.expanduser(user_path), "r")
|
||
|
|
|
||
|
|
# ✅ DO THIS
|
||
|
|
from pathlib import Path
|
||
|
|
safe_root = Path("/allowed/path").resolve()
|
||
|
|
user_path = Path(user_path).expanduser().resolve()
|
||
|
|
if not str(user_path).startswith(str(safe_root)):
|
||
|
|
raise PermissionError("Path outside sandbox")
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4.3 Secret Handling
|
||
|
|
```python
|
||
|
|
# ❌ NEVER DO THIS
|
||
|
|
os.environ["API_KEY"] = user_api_key # Visible to all child processes
|
||
|
|
|
||
|
|
# ✅ DO THIS
|
||
|
|
# Use file descriptor passing or explicit whitelisting
|
||
|
|
child_env = {k: v for k, v in os.environ.items()
|
||
|
|
if k in ALLOWED_ENV_VARS}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4.4 URL Validation
|
||
|
|
```python
|
||
|
|
# ❌ NEVER DO THIS
|
||
|
|
response = requests.get(user_url)
|
||
|
|
|
||
|
|
# ✅ DO THIS
|
||
|
|
from urllib.parse import urlparse
|
||
|
|
parsed = urlparse(user_url)
|
||
|
|
if parsed.scheme not in ("http", "https"):
|
||
|
|
raise ValueError("Invalid scheme")
|
||
|
|
if parsed.hostname not in ALLOWED_HOSTS:
|
||
|
|
raise ValueError("Host not allowed")
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4.5 Input Validation
|
||
|
|
```python
|
||
|
|
# Use pydantic for all user inputs
|
||
|
|
from pydantic import BaseModel, validator
|
||
|
|
|
||
|
|
class FileRequest(BaseModel):
|
||
|
|
path: str
|
||
|
|
max_size: int = 1000
|
||
|
|
|
||
|
|
@validator('path')
|
||
|
|
def validate_path(cls, v):
|
||
|
|
if '..' in v or v.startswith('/'):
|
||
|
|
raise ValueError('Invalid path')
|
||
|
|
return v
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 5. SPECIFIC SECURITY FIXES NEEDED
|
||
|
|
|
||
|
|
### Fix 1: Terminal Tool Command Injection (V-001)
|
||
|
|
```python
|
||
|
|
# CURRENT CODE (tools/terminal_tool.py ~line 457)
|
||
|
|
cmd = [self._docker_exe, "exec", "-w", work_dir, self._container_id,
|
||
|
|
"bash", "-lc", exec_command]
|
||
|
|
|
||
|
|
# SECURE FIX
|
||
|
|
cmd = [self._docker_exe, "exec", "-w", work_dir, self._container_id,
|
||
|
|
"bash", "-lc", exec_command]
|
||
|
|
# Add strict input validation before this point
|
||
|
|
if not _is_safe_command(exec_command):
|
||
|
|
raise SecurityError("Dangerous command detected")
|
||
|
|
```
|
||
|
|
|
||
|
|
### Fix 2: File Operations Path Traversal (V-002)
|
||
|
|
```python
|
||
|
|
# CURRENT CODE (tools/file_operations.py ~line 409)
|
||
|
|
def _expand_path(self, path: str) -> str:
|
||
|
|
if path.startswith('~'):
|
||
|
|
# ... expansion logic
|
||
|
|
|
||
|
|
# SECURE FIX
|
||
|
|
def _expand_path(self, path: str) -> str:
|
||
|
|
safe_root = Path(self.cwd).resolve()
|
||
|
|
expanded = Path(path).expanduser().resolve()
|
||
|
|
if not str(expanded).startswith(str(safe_root)):
|
||
|
|
raise PermissionError(f"Path {path} outside allowed directory")
|
||
|
|
return str(expanded)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Fix 3: Code Execution Environment Sanitization (V-003)
|
||
|
|
```python
|
||
|
|
# CURRENT CODE (tools/code_execution_tool.py ~lines 434-461)
|
||
|
|
_SAFE_ENV_PREFIXES = ("PATH", "HOME", "USER", ...)
|
||
|
|
_SECRET_SUBSTRINGS = ("TOKEN", "SECRET", ...)
|
||
|
|
|
||
|
|
# SECURE FIX - Whitelist approach
|
||
|
|
_ALLOWED_ENV_VARS = frozenset([
|
||
|
|
"PATH", "HOME", "USER", "LANG", "LC_ALL",
|
||
|
|
"PYTHONPATH", "TERM", "SHELL", "PWD"
|
||
|
|
])
|
||
|
|
child_env = {k: v for k, v in os.environ.items()
|
||
|
|
if k in _ALLOWED_ENV_VARS}
|
||
|
|
# Explicitly load only non-secret values
|
||
|
|
```
|
||
|
|
|
||
|
|
### Fix 4: API Server Authentication (V-009)
|
||
|
|
```python
|
||
|
|
# CURRENT CODE (gateway/platforms/api_server.py ~line 360-361)
|
||
|
|
if not self._api_key:
|
||
|
|
return None # No key configured — allow all
|
||
|
|
|
||
|
|
# SECURE FIX
|
||
|
|
if not self._api_key:
|
||
|
|
logger.error("API server started without authentication")
|
||
|
|
return web.json_response(
|
||
|
|
{"error": "Server misconfigured - auth required"},
|
||
|
|
status=500
|
||
|
|
)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Fix 5: CORS Configuration (V-008)
|
||
|
|
```python
|
||
|
|
# CURRENT CODE (gateway/platforms/api_server.py ~lines 324-328)
|
||
|
|
if "*" in self._cors_origins:
|
||
|
|
headers["Access-Control-Allow-Origin"] = "*"
|
||
|
|
|
||
|
|
# SECURE FIX - Never allow wildcard with credentials
|
||
|
|
if "*" in self._cors_origins:
|
||
|
|
logger.warning("Wildcard CORS not allowed with credentials")
|
||
|
|
return None
|
||
|
|
```
|
||
|
|
|
||
|
|
### Fix 6: OAuth State Validation (V-014)
|
||
|
|
```python
|
||
|
|
# CURRENT CODE (tools/mcp_oauth.py ~line 186)
|
||
|
|
code, state = await _wait_for_callback()
|
||
|
|
|
||
|
|
# SECURE FIX
|
||
|
|
stored_state = get_stored_state()
|
||
|
|
if state != stored_state:
|
||
|
|
raise SecurityError("OAuth state mismatch - possible CSRF attack")
|
||
|
|
```
|
||
|
|
|
||
|
|
### Fix 7: Docker Volume Mount Validation (V-012)
|
||
|
|
```python
|
||
|
|
# CURRENT CODE (tools/environments/docker.py ~line 267)
|
||
|
|
volume_args.extend(["-v", vol])
|
||
|
|
|
||
|
|
# SECURE FIX
|
||
|
|
_BLOCKED_PATHS = ['/var/run/docker.sock', '/proc', '/sys', ...]
|
||
|
|
if any(blocked in vol for blocked in _BLOCKED_PATHS):
|
||
|
|
raise SecurityError(f"Volume mount {vol} not allowed")
|
||
|
|
volume_args.extend(["-v", vol])
|
||
|
|
```
|
||
|
|
|
||
|
|
### Fix 8: Debug Output Redaction (V-027)
|
||
|
|
```python
|
||
|
|
# Add to all debug logging
|
||
|
|
from agent.redact import redact_sensitive_text
|
||
|
|
logger.debug(redact_sensitive_text(debug_message))
|
||
|
|
```
|
||
|
|
|
||
|
|
### Fix 9: Input Length Validation
|
||
|
|
```python
|
||
|
|
# Add to all tool entry points
|
||
|
|
MAX_INPUT_LENGTH = 10000
|
||
|
|
if len(user_input) > MAX_INPUT_LENGTH:
|
||
|
|
raise ValueError(f"Input exceeds maximum length of {MAX_INPUT_LENGTH}")
|
||
|
|
```
|
||
|
|
|
||
|
|
### Fix 10: Session ID Entropy
|
||
|
|
```python
|
||
|
|
# CURRENT CODE - uses uuid4
|
||
|
|
import uuid
|
||
|
|
session_id = str(uuid.uuid4())
|
||
|
|
|
||
|
|
# SECURE FIX - use secrets module
|
||
|
|
import secrets
|
||
|
|
session_id = secrets.token_urlsafe(32)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Fix 11-20: Additional Required Fixes
|
||
|
|
11. **Add CSRF protection** to all state-changing operations
|
||
|
|
12. **Implement request signing** for internal service communication
|
||
|
|
13. **Add certificate pinning** for external API calls
|
||
|
|
14. **Implement proper key rotation** for auth tokens
|
||
|
|
15. **Add anomaly detection** for unusual command patterns
|
||
|
|
16. **Implement network segmentation** for sandbox environments
|
||
|
|
17. **Add hardware security module (HSM) support** for key storage
|
||
|
|
18. **Implement behavioral analysis** for skill code
|
||
|
|
19. **Add automated vulnerability scanning** to CI/CD pipeline
|
||
|
|
20. **Implement incident response procedures** for security events
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 6. SECURITY RECOMMENDATIONS
|
||
|
|
|
||
|
|
### Immediate Actions (Within 24 hours)
|
||
|
|
1. Disable gateway API server if not required
|
||
|
|
2. Enable HERMES_YOLO_MODE only for trusted users
|
||
|
|
3. Review all installed skills from community sources
|
||
|
|
4. Enable comprehensive audit logging
|
||
|
|
|
||
|
|
### Short-term Actions (Within 1 week)
|
||
|
|
1. Deploy all P0 fixes
|
||
|
|
2. Implement monitoring for suspicious command patterns
|
||
|
|
3. Conduct security training for developers
|
||
|
|
4. Establish security review process for new features
|
||
|
|
|
||
|
|
### Long-term Actions (Within 1 month)
|
||
|
|
1. Implement comprehensive security testing
|
||
|
|
2. Establish bug bounty program
|
||
|
|
3. Regular third-party security audits
|
||
|
|
4. Achieve SOC 2 compliance
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 7. COMPLIANCE MAPPING
|
||
|
|
|
||
|
|
| Vulnerability | OWASP Top 10 | CWE | NIST 800-53 |
|
||
|
|
|---------------|--------------|-----|-------------|
|
||
|
|
| V-001 (Command Injection) | A03:2021 - Injection | CWE-78 | SI-10 |
|
||
|
|
| V-002 (Path Traversal) | A01:2021 - Broken Access Control | CWE-22 | AC-3 |
|
||
|
|
| V-003 (Secret Leakage) | A07:2021 - Auth Failures | CWE-200 | SC-28 |
|
||
|
|
| V-005 (SSRF) | A10:2021 - SSRF | CWE-918 | SC-7 |
|
||
|
|
| V-008 (CORS) | A05:2021 - Security Misconfig | CWE-942 | AC-4 |
|
||
|
|
| V-011 (Skills Bypass) | A08:2021 - Integrity Failures | CWE-353 | SI-7 |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## APPENDIX A: TESTING RECOMMENDATIONS
|
||
|
|
|
||
|
|
### Security Test Cases
|
||
|
|
1. Command injection with `; rm -rf /`
|
||
|
|
2. Path traversal with `../../../etc/passwd`
|
||
|
|
3. SSRF with `http://169.254.169.254/latest/meta-data/`
|
||
|
|
4. Secret exfiltration via environment variables
|
||
|
|
5. OAuth flow manipulation
|
||
|
|
6. Rate limiting bypass
|
||
|
|
7. Session fixation attacks
|
||
|
|
8. Privilege escalation via sudo
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Report End**
|
||
|
|
|
||
|
|
*This audit represents a point-in-time assessment. Security is an ongoing process requiring continuous monitoring and improvement.*
|