Customize Sandbox Policies#
Use this page to apply and iterate policy changes on running sandboxes. For a full field-by-field YAML definition, use the Policy Schema Reference.
Policy Structure#
A policy has static sections filesystem_policy, landlock, and process that are locked at sandbox creation, and a dynamic section network_policies that is hot-reloadable on a running sandbox.
version: 1
# Static: locked at sandbox creation. Paths the agent can read vs read/write.
filesystem_policy:
read_only: [/usr, /lib, /etc]
read_write: [/sandbox, /tmp]
# Static: Landlock LSM kernel enforcement. best_effort uses highest ABI the host supports.
landlock:
compatibility: best_effort
# Static: Unprivileged user/group the agent process runs as.
process:
run_as_user: sandbox
run_as_group: sandbox
# Dynamic: hot-reloadable. Named blocks of endpoints + binaries allowed to reach them.
network_policies:
my_api:
name: my-api
endpoints:
- host: api.example.com
port: 443
protocol: rest
tls: terminate
enforcement: enforce
access: full
binaries:
- path: /usr/bin/curl
Static sections are locked at sandbox creation. Changing them requires destroying and recreating the sandbox.
Dynamic sections can be updated on a running sandbox with openshell policy set and take effect without restarting.
Section |
Type |
Description |
|---|---|---|
|
Static |
Controls which directories the agent can access on disk. Paths are split into |
|
Static |
Configures Landlock LSM enforcement behavior. Set |
|
Static |
Sets the OS-level identity for the agent process. |
|
Dynamic |
Controls network access for ordinary outbound traffic from the sandbox. Each block has a name, a list of endpoints (host, port, protocol, and optional rules), and a list of binaries allowed to use those endpoints. |
Apply a Custom Policy#
Pass a policy YAML file when creating the sandbox:
$ openshell sandbox create --policy ./my-policy.yaml -- claude
openshell sandbox create keeps the sandbox running after the initial command exits, which is useful when you plan to iterate on the policy. Add --no-keep if you want the sandbox deleted automatically instead.
To avoid passing --policy every time, set a default policy with an environment variable:
$ export OPENSHELL_SANDBOX_POLICY=./my-policy.yaml
$ openshell sandbox create -- claude
The CLI uses the policy from OPENSHELL_SANDBOX_POLICY whenever --policy is not explicitly provided.
Iterate on a Running Sandbox#
To change what the sandbox can access, pull the current policy, edit the YAML, and push the update. The workflow is iterative: create the sandbox, monitor logs for denied actions, pull the policy, modify it, push, and verify.
flowchart TD
A["1. Create sandbox with initial policy"] --> B["2. Monitor logs for denied actions"]
B --> C["3. Pull current policy"]
C --> D["4. Modify the policy YAML"]
D --> E["5. Push updated policy"]
E --> F["6. Verify the new revision loaded"]
F --> B
style A fill:#76b900,stroke:#000000,color:#000000
style B fill:#76b900,stroke:#000000,color:#000000
style C fill:#76b900,stroke:#000000,color:#000000
style D fill:#ffffff,stroke:#000000,color:#000000
style E fill:#76b900,stroke:#000000,color:#000000
style F fill:#76b900,stroke:#000000,color:#000000
linkStyle default stroke:#76b900,stroke-width:2px
The following steps outline the hot-reload policy update workflow.
Create the sandbox with your initial policy by following Apply a Custom Policy above (or set
OPENSHELL_SANDBOX_POLICY).Monitor denials. Each log entry shows host, port, binary, and reason. Alternatively, use
openshell termfor a live dashboard.$ openshell logs <name> --tail --source sandbox
Pull the current policy. Strip the metadata header (Version, Hash, Status) before reusing the file.
$ openshell policy get <name> --full > current-policy.yaml
Edit the YAML: add or adjust
network_policiesentries, binaries,access, orrules.Push the updated policy. Exit codes: 0 = loaded, 1 = validation failed, 124 = timeout.
$ openshell policy set <name> --policy current-policy.yaml --wait
Verify the new revision. If status is
loaded, repeat from step 2 as needed; iffailed, fix the policy and repeat from step 4.$ openshell policy list <name>
Debug Denied Requests#
Check openshell logs <name> --tail --source sandbox for the denied host, path, and binary.
When triaging denied requests, check:
Destination host and port to confirm which endpoint is missing.
Calling binary path to confirm which
binariesentry needs to be added or adjusted.HTTP method and path (for REST endpoints) to confirm which
rulesentry needs to be added or adjusted.
Then push the updated policy as described above.
Examples#
Add these blocks to the network_policies section of your sandbox policy. Apply with openshell policy set <name> --policy <file> --wait.
Use Simple endpoint for host-level allowlists and Granular rules for method/path control.
Allow pip install and uv pip install to reach PyPI:
pypi:
name: pypi
endpoints:
- host: pypi.org
port: 443
- host: files.pythonhosted.org
port: 443
binaries:
- { path: /usr/bin/pip }
- { path: /usr/local/bin/uv }
Endpoints without protocol or tls use TCP passthrough — the proxy allows the stream without inspecting payloads.
Allow Claude and the GitHub CLI to reach api.github.com with per-path rules: read-only (GET, HEAD, OPTIONS) and GraphQL (POST) for all paths; full write access for alpha-repo; and create/edit issues only for bravo-repo. Replace <org_name> with your GitHub org or username.
Tip
For an end-to-end walkthrough that combines this policy with a GitHub credential provider and sandbox creation, refer to Grant GitHub Push Access to a Sandboxed Agent.
github_repos:
name: github_repos
endpoints:
- host: api.github.com
port: 443
protocol: rest
tls: terminate
enforcement: enforce
rules:
- allow:
method: GET
path: "/**"
- allow:
method: HEAD
path: "/**"
- allow:
method: OPTIONS
path: "/**"
- allow:
method: POST
path: "/graphql"
- allow:
method: "*"
path: "/repos/<org_name>/alpha-repo/**"
- allow:
method: POST
path: "/repos/<org_name>/bravo-repo/issues"
- allow:
method: PATCH
path: "/repos/<org_name>/bravo-repo/issues/*"
binaries:
- { path: /usr/local/bin/claude }
- { path: /usr/bin/gh }
Endpoints with protocol: rest and tls: terminate enable HTTP request inspection — the proxy decrypts TLS and checks each HTTP request against the rules list.
Next Steps#
Explore related topics:
To learn about network access rules and sandbox isolation layers, refer to About Gateways and Sandboxes.
To view the full field-by-field YAML definition, refer to the Policy Schema Reference.
To review the default policy breakdown, refer to Default Policy Reference.