- **Default deny**: All operations are blocked unless explicitly allowed by the policy. An empty policy grants no access.
- **Deny rules override allow rules**: When a path appears in both allow and deny lists, the deny rule wins. Deny rules are placed after allow rules in the generated sandbox profile to ensure this.
- **Credential and sensitive file protection**: The sandbox automatically blocks read and write access to credential files regardless of user configuration. Protected files include `.env`, `.env.*`, `.aws`, `.gcloud`, `.kube`, `.ssh`, `.gnupg`, and `.docker/config.json`. These mandatory deny patterns are injected at translation time and cannot be removed by policy configuration or runtime overrides.
- **Git hooks are always blocked**: Write access to `.git/hooks/` in both `$CWD` and `$HOME` is always denied to prevent arbitrary code execution via repository hooks.
- **Git config is blocked by default**: Write access to `.git/config` is denied unless `allow_git_config: true` is set in the policy. This prevents credential helper manipulation.
- **Runtime overrides remove only exact-match deny entries**: When `--sandbox-allow` adds a path to an allow list, only a literal string match in the corresponding deny list is removed. Glob and wildcard deny patterns (e.g., `/etc/**`) are never removed. Mandatory deny patterns (credentials, git hooks) cannot be overridden because they are re-injected at translation time.
- **Profile inheritance is single-level**: A profile can inherit from one built-in profile. Allow and deny lists are merged using union semantics. Boolean fields (`allow_pty`, `allow_git_config`) in the child override the parent.
- **Variable expansion is runtime-only**: Policy paths use `${HOME}`, `${CWD}`, and `${TMPDIR}` which are expanded when the sandbox is set up, not when the policy is defined.
- **Process-level isolation only**: The sandbox restricts the package manager process and its children. It does not enforce CPU, memory, or disk quotas. Network filtering is coarse-grained — host-level filtering is not enforced on either platform.
Use `--sandbox-allow` to make one-off exceptions without creating a custom profile. This is useful when a command needs access that the default profile blocks.
Overrides are non-persistent (apply to current invocation only) and logged in the event log for auditing. An override adds the path to the allow list and removes an exact match entry from the corresponding deny list. Glob deny patterns are never removed. Mandatory security protections (`.env`, `.ssh`, `.aws`, `.git/hooks`, etc.) cannot be bypassed by overrides.
See [sandbox/profiles/README.md](../sandbox/profiles/README.md) for more details.
### Policy Template
Policy template is a configuration primitive for overriding a built-in profile or creating a custom profile. It is used to map a profile name to a path.
See [config/config.template.yml](../config/config.template.yml) for an example.
## Threat Model
- Policy files are trusted
- Policy enforcement is a sandbox implementation concern
- YAML to sandbox specific policy translation must not make the policy weaker than the original policy
- Variable interpolation in policy files must consider only trusted sources
## Enforcement
The sandbox implementation currently only support `block` mode. This means, any policy violation will block the execution of the
package manager command.
## Debug
### MacOS
OSX sandbox implementation is based on [Chromium OSX Sandbox Design](https://www.chromium.org/developers/design-documents/sandbox/osx-sandboxing-design/)
and [Anthropic Sandbox Runtime](https://github.com/anthropic-experimental/sandbox-runtime). Current implementation does not support
identifying sandbox policy violations.
To manually investigate sandbox policy violations, you can use the following command:
**Note**: Unlike macOS, Bubblewrap does not provide real-time violation logging. Policy violations typically manifest as `EACCES` (Permission denied) errors.