Changes: - Support path patterns without ./ prefix (e.g., 'scripts/test.sh') - Reject non-string or empty command names in org config - Add 8 new test cases (5 for path patterns, 3 for validation) Details: - matches_pattern() now treats any pattern with '/' as a path pattern - load_org_config() validates that cmd['name'] is a non-empty string - All 148 unit tests + 9 integration tests passing Security hardening: Prevents invalid command names from reaching pattern matching logic, reducing attack surface.
14 KiB
AutoCoder Security Configuration Examples
This directory contains example configuration files for controlling which bash commands the autonomous coding agent can execute.
Table of Contents
- Quick Start
- Project-Level Configuration
- Organization-Level Configuration
- Command Hierarchy
- Pattern Matching
- Common Use Cases
- Security Best Practices
Quick Start
For a Single Project (Most Common)
When you create a new project with AutoCoder, it automatically creates:
my-project/
.autocoder/
allowed_commands.yaml ← Automatically created from template
Edit this file to add project-specific commands (Swift tools, Rust compiler, etc.).
For All Projects (Organization-Wide)
If you want commands available across all projects, manually create:
# Copy the example to your home directory
cp examples/org_config.yaml ~/.autocoder/config.yaml
# Edit it to add org-wide commands
nano ~/.autocoder/config.yaml
Project-Level Configuration
File: {project_dir}/.autocoder/allowed_commands.yaml
Purpose: Define commands needed for THIS specific project.
Example (iOS project):
version: 1
commands:
- name: swift
description: Swift compiler
- name: xcodebuild
description: Xcode build system
- name: swift*
description: All Swift tools (swiftc, swiftlint, swiftformat)
- name: ./scripts/build.sh
description: Project build script
When to use:
- ✅ Project uses a specific language toolchain (Swift, Rust, Go)
- ✅ Project has custom build scripts
- ✅ Temporary tools needed during development
Limits:
- Maximum 100 commands per project
- Cannot override org-level blocked commands
- Cannot allow hardcoded blocklist commands (sudo, dd, etc.)
See: examples/project_allowed_commands.yaml for full example with Rust, Python, iOS, etc.
Organization-Level Configuration
File: ~/.autocoder/config.yaml
Purpose: Define commands and policies for ALL projects.
Example (startup team):
version: 1
# Available to all projects
allowed_commands:
- name: jq
description: JSON processor
- name: python3
description: Python interpreter
# Blocked across all projects (cannot be overridden)
blocked_commands:
- aws
- kubectl
- terraform
When to use:
- ✅ Multiple projects need the same tools (jq, python3, etc.)
- ✅ Enforce organization-wide security policies
- ✅ Block dangerous commands across all projects
See: examples/org_config.yaml for full example with enterprise/startup configurations.
Command Hierarchy
When the agent tries to run a command, the system checks in this order:
┌─────────────────────────────────────────────────────┐
│ 1. HARDCODED BLOCKLIST (highest priority) │
│ sudo, dd, shutdown, reboot, chown, etc. │
│ ❌ NEVER allowed, even with user approval │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ 2. ORG BLOCKLIST (~/.autocoder/config.yaml) │
│ Commands you block organization-wide │
│ ❌ Projects CANNOT override these │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ 3. ORG ALLOWLIST (~/.autocoder/config.yaml) │
│ Commands available to all projects │
│ ✅ Automatically available │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ 4. GLOBAL ALLOWLIST (security.py) │
│ Default commands: npm, git, curl, ls, cat, etc. │
│ ✅ Always available │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ 5. PROJECT ALLOWLIST (.autocoder/allowed_commands) │
│ Project-specific commands │
│ ✅ Available only to this project │
└─────────────────────────────────────────────────────┘
Key Rules:
- If a command is BLOCKED at any level above, it cannot be allowed below
- If a command is ALLOWED at any level, it's available (unless blocked above)
- Blocklist always wins over allowlist
Pattern Matching
You can use patterns to match multiple commands:
Exact Match
- name: swift
description: Swift compiler only
Matches: swift
Does NOT match: swiftc, swiftlint
Prefix Wildcard
- name: swift*
description: All Swift tools
Matches: swift, swiftc, swiftlint, swiftformat
Does NOT match: npm, rustc
Local Scripts
- name: ./scripts/build.sh
description: Build script
Matches:
./scripts/build.shscripts/build.sh/full/path/to/scripts/build.sh- Running
build.shfrom any directory (matched by filename)
Common Use Cases
iOS Development
Project config (.autocoder/allowed_commands.yaml):
version: 1
commands:
- name: swift*
description: All Swift tools
- name: xcodebuild
description: Xcode build system
- name: xcrun
description: Xcode tools runner
- name: simctl
description: iOS Simulator control
Rust CLI Project
Project config:
version: 1
commands:
- name: cargo
description: Rust package manager
- name: rustc
description: Rust compiler
- name: rustfmt
description: Rust formatter
- name: clippy
description: Rust linter
- name: ./target/debug/my-cli
description: Debug build
- name: ./target/release/my-cli
description: Release build
API Testing Project
Project config:
version: 1
commands:
- name: jq
description: JSON processor
- name: httpie
description: HTTP client
- name: ./scripts/test-api.sh
description: API test runner
Enterprise Organization (Restrictive)
Org config (~/.autocoder/config.yaml):
version: 1
allowed_commands:
- name: jq
description: JSON processor
blocked_commands:
- aws # No cloud access
- gcloud
- az
- kubectl # No k8s access
- terraform # No infrastructure changes
- psql # No production DB access
- mysql
Startup Team (Permissive)
Org config (~/.autocoder/config.yaml):
version: 1
allowed_commands:
- name: python3
description: Python interpreter
- name: jq
description: JSON processor
- name: pytest
description: Python tests
blocked_commands: [] # Rely on hardcoded blocklist only
Security Best Practices
✅ DO
-
Start restrictive, add as needed
- Begin with default commands only
- Add project-specific tools when required
- Review the agent's blocked command errors to understand what's needed
-
Use org-level config for shared tools
- If 3+ projects need
jq, add it to org config - Reduces duplication across project configs
- If 3+ projects need
-
Block dangerous commands at org level
- Prevent accidental production deployments (
kubectl,terraform) - Block cloud CLIs if appropriate (
aws,gcloud,az)
- Prevent accidental production deployments (
-
Use descriptive command names
- Good:
description: "Swift compiler for iOS builds" - Bad:
description: "Compiler"
- Good:
-
Prefer patterns for tool families
swift*instead of listingswift,swiftc,swiftlintseparately- Automatically includes future tools (e.g., new Swift utilities)
❌ DON'T
-
Don't add commands "just in case"
- Only add when the agent actually needs them
- Empty config is fine - defaults are usually enough
-
Don't try to allow blocklisted commands
- Commands like
sudo,dd,shutdowncan NEVER be allowed - The system will reject these in validation
- Commands like
-
Don't use org config for project-specific tools
- Bad: Adding
xcodebuildto org config when only one project uses it - Good: Add
xcodebuildto that project's config
- Bad: Adding
-
Don't exceed the 100 command limit per project
- If you need more, you're probably listing subcommands unnecessarily
- Use wildcards instead:
flutter*covers all flutter commands, not just the base
-
Don't ignore validation errors
- If your YAML is rejected, fix the structure
- Common issues: missing
version, malformed lists, over 100 commands
Default Allowed Commands
These commands are always available to all projects:
File Operations:
ls,cat,head,tail,wc,grep,cp,mkdir,mv,rm,touch
Shell:
pwd,echo,sh,bash,sleep
Version Control:
git
Process Management:
ps,lsof,kill,pkill(dev processes only: node, npm, vite)
Network:
curl
Node.js:
npm,npx,pnpm,node
Docker:
docker
Special:
chmod(only+xmode for making scripts executable)
Hardcoded Blocklist
These commands are NEVER allowed, even with user approval:
Disk Operations:
dd,mkfs,fdisk,parted
System Control:
shutdown,reboot,poweroff,halt,init
Privilege Escalation:
sudo,su,doas
System Services:
systemctl,service,launchctl
Network Security:
iptables,ufw
Ownership Changes:
chown,chgrp
Dangerous Commands (Phase 3 will add approval):
aws,gcloud,az,kubectl,docker-compose
Troubleshooting
Error: "Command 'X' is not allowed"
Solution: Add the command to your project config:
# In .autocoder/allowed_commands.yaml
commands:
- name: X
description: What this command does
Error: "Command 'X' is blocked at organization level"
Cause: The command is in the org blocklist or hardcoded blocklist.
Solution:
- If in org blocklist: Edit
~/.autocoder/config.yamlto remove it - If in hardcoded blocklist: Cannot be allowed (by design)
Error: "Could not parse YAML config"
Cause: YAML syntax error.
Solution: Check for:
- Missing colons after keys
- Incorrect indentation (use 2 spaces, not tabs)
- Missing quotes around special characters
Config not taking effect
Solution:
- Restart the agent (changes are loaded on startup)
- Verify file location:
- Project:
{project}/.autocoder/allowed_commands.yaml - Org:
~/.autocoder/config.yaml(must be manually created)
- Project:
- Check YAML is valid (run through a YAML validator)
Testing
Running the Tests
AutoCoder has comprehensive tests for the security system:
Unit Tests (136 tests - fast):
source venv/bin/activate
python test_security.py
Tests:
- Pattern matching (exact, wildcards, scripts)
- YAML loading and validation
- Blocklist enforcement
- Project and org config hierarchy
- All existing security validations
Integration Tests (9 tests - uses real security hooks):
source venv/bin/activate
python test_security_integration.py
Tests:
- Blocked commands are rejected (sudo, shutdown, etc.)
- Default commands work (ls, git, npm, etc.)
- Non-allowed commands are blocked (wget, python, etc.)
- Project config allows commands (swift, xcodebuild, etc.)
- Pattern matching works (swift* matches swiftlint)
- Org blocklist cannot be overridden
- Org allowlist is inherited by projects
- Invalid YAML is safely ignored
- 50 command limit is enforced
Manual Testing
To manually test the security system:
1. Create a test project:
python start.py
# Choose "Create new project"
# Name it "security-test"
2. Edit the project config:
# Navigate to the project directory
cd path/to/security-test
# Edit the config
nano .autocoder/allowed_commands.yaml
3. Add a test command (e.g., Swift):
version: 1
commands:
- name: swift
description: Swift compiler
4. Run the agent and observe:
- Try a blocked command:
"Run sudo apt install nginx"→ Should be blocked - Try an allowed command:
"Run ls -la"→ Should work - Try your config command:
"Run swift --version"→ Should work - Try a non-allowed command:
"Run wget https://example.com"→ Should be blocked
5. Check the agent output:
The agent will show security hook messages like:
Command 'sudo' is blocked at organization level and cannot be approved.
Or:
Command 'wget' is not allowed.
To allow this command:
1. Add to .autocoder/allowed_commands.yaml for this project, OR
2. Request mid-session approval (the agent can ask)
Files Reference
examples/project_allowed_commands.yaml- Full project config templateexamples/org_config.yaml- Full org config templatesecurity.py- Implementation and hardcoded blocklisttest_security.py- Unit tests (136 tests)test_security_integration.py- Integration tests (9 tests)CLAUDE.md- Full system documentation
Questions?
See the main documentation in CLAUDE.md for architecture details and implementation specifics.