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:
17
prompts.py
17
prompts.py
@@ -180,6 +180,10 @@ def scaffold_project_prompts(project_dir: Path) -> Path:
|
||||
project_prompts = get_project_prompts_dir(project_dir)
|
||||
project_prompts.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Create .autocoder directory for configuration files
|
||||
autocoder_dir = project_dir / ".autocoder"
|
||||
autocoder_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Define template mappings: (source_template, destination_name)
|
||||
templates = [
|
||||
("app_spec.template.txt", "app_spec.txt"),
|
||||
@@ -201,8 +205,19 @@ def scaffold_project_prompts(project_dir: Path) -> Path:
|
||||
except (OSError, PermissionError) as e:
|
||||
print(f" Warning: Could not copy {dest_name}: {e}")
|
||||
|
||||
# Copy allowed_commands.yaml template to .autocoder/
|
||||
examples_dir = Path(__file__).parent / "examples"
|
||||
allowed_commands_template = examples_dir / "project_allowed_commands.yaml"
|
||||
allowed_commands_dest = autocoder_dir / "allowed_commands.yaml"
|
||||
if allowed_commands_template.exists() and not allowed_commands_dest.exists():
|
||||
try:
|
||||
shutil.copy(allowed_commands_template, allowed_commands_dest)
|
||||
copied_files.append(".autocoder/allowed_commands.yaml")
|
||||
except (OSError, PermissionError) as e:
|
||||
print(f" Warning: Could not copy allowed_commands.yaml: {e}")
|
||||
|
||||
if copied_files:
|
||||
print(f" Created prompt files: {', '.join(copied_files)}")
|
||||
print(f" Created project files: {', '.join(copied_files)}")
|
||||
|
||||
return project_prompts
|
||||
|
||||
|
||||
Reference in New Issue
Block a user