mirror of
https://github.com/leonvanzyl/autocoder.git
synced 2026-01-30 06:12:06 +00:00
feat: add per-project bash command allowlist system
Implement hierarchical command security with project and org-level configs:
WHAT'S NEW:
- Project-level YAML config (.autocoder/allowed_commands.yaml)
- Organization-level config (~/.autocoder/config.yaml)
- Pattern matching (exact, wildcards, local scripts)
- Hardcoded blocklist (sudo, dd, shutdown - never allowed)
- Org blocklist (terraform, kubectl - configurable)
- Helpful error messages with config hints
- Comprehensive documentation and examples
ARCHITECTURE:
- Hierarchical resolution: Hardcoded → Org Block → Org Allow → Global → Project
- YAML validation with 50 command limit per project
- Pattern matching: exact ("swift"), wildcards ("swift*"), scripts ("./build.sh")
- Secure by default: all examples commented out
TESTING:
- 136 unit tests (pattern matching, YAML, hierarchy, validation)
- 9 integration tests (real security hook flows)
- All tests passing, 100% backward compatible
DOCUMENTATION:
- examples/README.md - comprehensive guide with use cases
- examples/project_allowed_commands.yaml - template (all commented)
- examples/org_config.yaml - org config template (all commented)
- PHASE3_SPEC.md - mid-session approval spec (future enhancement)
- Updated CLAUDE.md with security model documentation
USE CASES:
- iOS projects: Add Swift toolchain (xcodebuild, swift*, etc.)
- Rust projects: Add cargo, rustc, clippy
- Enterprise: Block aws, kubectl, terraform org-wide
- Custom scripts: Allow ./scripts/build.sh
PHASES:
✅ Phase 1: Project YAML + blocklist (implemented)
✅ Phase 2: Org config + hierarchy (implemented)
📋 Phase 3: Mid-session approval (spec ready, not implemented)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
10
client.py
10
client.py
@@ -261,6 +261,14 @@ def create_client(
|
||||
if "ANTHROPIC_BASE_URL" in sdk_env:
|
||||
print(f" - GLM Mode: Using {sdk_env['ANTHROPIC_BASE_URL']}")
|
||||
|
||||
# Create a wrapper for bash_security_hook that passes project_dir via context
|
||||
async def bash_hook_with_context(input_data, tool_use_id=None, context=None):
|
||||
"""Wrapper that injects project_dir into context for security hook."""
|
||||
if context is None:
|
||||
context = {}
|
||||
context["project_dir"] = str(project_dir.resolve())
|
||||
return await bash_security_hook(input_data, tool_use_id, context)
|
||||
|
||||
return ClaudeSDKClient(
|
||||
options=ClaudeAgentOptions(
|
||||
model=model,
|
||||
@@ -272,7 +280,7 @@ def create_client(
|
||||
mcp_servers=mcp_servers,
|
||||
hooks={
|
||||
"PreToolUse": [
|
||||
HookMatcher(matcher="Bash", hooks=[bash_security_hook]),
|
||||
HookMatcher(matcher="Bash", hooks=[bash_hook_with_context]),
|
||||
],
|
||||
},
|
||||
max_turns=1000,
|
||||
|
||||
Reference in New Issue
Block a user