ac-security-sandbox
SKILL.md
AC Security Sandbox
Defense-in-depth security for autonomous code execution.
Overview
Provides three layers of security:
- OS-Level Sandbox: Isolated execution environment
- Filesystem Permissions: Restricted path access
- Command Allowlist: Pre-approved commands only
Quick Start
Validate Command
from scripts.security_sandbox import SecuritySandbox
sandbox = SecuritySandbox(project_dir)
# Check if command is allowed
is_safe, reason = sandbox.validate_command("npm install")
if is_safe:
# Execute command
pass
else:
print(f"Blocked: {reason}")
Configure Allowlist
sandbox.configure_allowlist([
"ls", "cat", "head", "tail",
"npm", "node", "python",
"git", "grep"
])
Security Layers
Layer 1: OS-Level Sandbox
# Enable sandbox mode
sandbox_config = {
"enabled": True,
"isolation": "strict",
"network": "restricted"
}
Layer 2: Filesystem Permissions
permissions = {
"allow": [
"Read(./**)", # Read project files
"Write(./**)", # Write project files
"Edit(./**)", # Edit project files
],
"deny": [
"Read(/etc/**)", # No system files
"Write(/usr/**)", # No system writes
"Bash(rm -rf /)", # No destructive commands
]
}
Layer 3: Command Allowlist
ALLOWED_COMMANDS = {
# File inspection
"ls", "cat", "head", "tail", "wc", "grep", "find",
# File operations
"cp", "mv", "mkdir", "chmod", "touch",
# Node.js
"npm", "node", "npx", "yarn", "pnpm",
# Python
"python", "python3", "pip", "pip3",
# Version control
"git",
# Process management
"ps", "lsof", "sleep", "pkill",
# Build tools
"make", "cmake", "cargo", "go",
# Testing
"jest", "pytest", "vitest", "playwright"
}
Command Validation
Pre-Tool-Use Hook
async def bash_security_hook(input_data, tool_use_id, context):
command = input_data.get("tool_input", {}).get("command", "")
# Extract all commands (handles pipes, &&, etc.)
commands = extract_commands(command)
for cmd in commands:
if cmd not in ALLOWED_COMMANDS:
return {
"decision": "block",
"reason": f"Command '{cmd}' not in allowlist"
}
return {} # Allow execution
Command Extraction
def extract_commands(command: str) -> list[str]:
"""
Extract base commands from complex command strings.
Examples:
"npm install && npm test" → ["npm", "npm"]
"cat file.txt | grep error" → ["cat", "grep"]
"git add . && git commit -m 'msg'" → ["git", "git"]
"""
# Parse command string
# Handle: pipes (|), chains (&&, ||), semicolons (;)
# Return list of base command names
Blocked Command Patterns
Always Blocked
DANGEROUS_PATTERNS = [
r"rm\s+-rf\s+/", # Recursive delete root
r"dd\s+if=", # Direct disk writes
r"mkfs", # Format filesystems
r":(){ :|:& };:", # Fork bombs
r"chmod\s+777", # Overly permissive
r"curl.*\|\s*bash", # Pipe to shell
r"wget.*\|\s*sh", # Pipe to shell
]
Context-Dependent
# Allowed in project directory only
RESTRICTED_COMMANDS = {
"rm": lambda path: path.startswith("./"),
"mv": lambda src, dst: src.startswith("./") and dst.startswith("./"),
"cp": lambda src, dst: dst.startswith("./"),
}
Configuration
.claude/security-config.json
{
"sandbox": {
"enabled": true,
"isolation": "strict"
},
"permissions": {
"filesystem": {
"read": ["./**", "~/.config/claude/**"],
"write": ["./**"],
"deny": ["/etc/**", "/usr/**", "~/.ssh/**"]
},
"network": {
"allow": ["localhost", "api.anthropic.com"],
"deny": ["*"]
}
},
"allowlist": {
"commands": ["npm", "node", "git", "python"],
"custom": []
}
}
Operations
1. Initialize Sandbox
sandbox = SecuritySandbox(project_dir)
await sandbox.initialize()
# Loads config, sets up hooks
2. Validate Command
is_safe, reason = sandbox.validate_command(command)
# Returns (True, None) or (False, "reason")
3. Validate Path
is_allowed = sandbox.validate_path(path, operation="write")
# Checks against filesystem permissions
4. Register Hook
hook = sandbox.create_pre_tool_hook()
# Returns hook function for Claude SDK
5. Add Custom Command
sandbox.add_allowed_command("my-custom-tool")
# Adds to allowlist (persists to config)
6. Audit Log
# Get recent security events
events = sandbox.get_audit_log(limit=100)
for event in events:
print(f"{event.timestamp}: {event.action} - {event.command}")
Audit Logging
All security decisions are logged:
// .claude/security-audit.jsonl
{"timestamp": "2025-01-15T10:00:00Z", "action": "ALLOW", "command": "npm install", "reason": null}
{"timestamp": "2025-01-15T10:01:00Z", "action": "BLOCK", "command": "rm -rf /", "reason": "Dangerous pattern"}
{"timestamp": "2025-01-15T10:02:00Z", "action": "ALLOW", "command": "git commit", "reason": null}
Best Practices
DO
- Start with minimal allowlist
- Add commands as needed
- Review audit logs regularly
- Use project-relative paths
DON'T
- Allow
sudocommands - Allow system path writes
- Disable sandbox in production
- Ignore blocked command logs
Integration Points
- ac-session-manager: Provides security hooks
- ac-build-runner: Validates build commands
- ac-coder-agent: Restricts agent commands
- ac-config-manager: Loads security config
References
references/ALLOWLIST.md- Complete command listreferences/PATTERNS.md- Blocked patternsreferences/AUDIT.md- Audit log format
Scripts
scripts/security_sandbox.py- Core SecuritySandboxscripts/command_validator.py- Command validationscripts/path_validator.py- Path validationscripts/audit_logger.py- Security audit logging