Problem
Guardians inspect tool calls but can't see what happens inside scripts:
# Guardian catches this:
rm -rf ~/
# Guardian does NOT catch this:
uv run python script.py
# where script.py does: shutil.rmtree(os.path.expanduser("~"))
The sandbox closes this gap at the OS level, but today it's completely separate from ac-safety — configured independently and bypassable by the model via dangerouslyDisableSandbox: true.
Proposal
ac-safety should own the sandbox. Use the existing safety.yaml config to drive both layers:
allowed_project_roots / allowed_write_prefixes → sandbox write permissions
blocked_prefixes → sandbox read restrictions
- Guardians continue working at tool-call level (unchanged)
- Sandbox enforces the same policy at OS level (new)
One config, two enforcement layers. The user doesn't think about "sandbox" — ac-safety handles it.
dangerouslyDisableSandbox must be unconditionally blocked when ac-safety is active. Not configurable. If the model can disable the sandbox, OS-level enforcement is meaningless.
Problem
Guardians inspect tool calls but can't see what happens inside scripts:
The sandbox closes this gap at the OS level, but today it's completely separate from ac-safety — configured independently and bypassable by the model via
dangerouslyDisableSandbox: true.Proposal
ac-safety should own the sandbox. Use the existing
safety.yamlconfig to drive both layers:allowed_project_roots/allowed_write_prefixes→ sandbox write permissionsblocked_prefixes→ sandbox read restrictionsOne config, two enforcement layers. The user doesn't think about "sandbox" — ac-safety handles it.
dangerouslyDisableSandboxmust be unconditionally blocked when ac-safety is active. Not configurable. If the model can disable the sandbox, OS-level enforcement is meaningless.