D-201 Use
Policy file
A short file says what the agent may touch. Boundlane compiles it into the sandbox's own policy format and checks the result before anything starts.
Where the policy comes from
| Plan | Policy used |
|---|---|
| Free | The built-in developer-default, plus boundlane.yaml in the project root if there is one. |
| Team | The policy your security lead published, delivered as a signed file. A project file is not used. See Publish and revisions. |
You do not need to learn the sandbox's policy language. You also cannot write something in this file that the sandbox cannot enforce. Fields that would need that are left out.
The default policy
This is developer-default. The project folder is writable. Three package registries and the GitHub API are readable. Everything else is closed. The full picture, including what each agent adds, is on Default access.
version: 1
name: developer-default
agents: [claude, codex, grok, opencode]
workspace: read-write
hosts:
- host: api.github.com
access: read-only
- host: registry.npmjs.org
access: read-only
- host: pypi.org
access: read-only
- host: files.pythonhosted.org
access: read-only
approvals: personThe model API is not listed. Each agent's key comes with the endpoints it is allowed to reach, so the key and its destination stay together. See Keys and tokens.
Adding hosts for a project
Run boundlane init to create a boundlane.yaml in the project root, then add what this project needs.
version: 1
hosts:
- host: api.stripe.com
access: read-only
- host: api.github.com
access: read-write
allow:
- GET /repos/acme/web/**
- POST /repos/acme/web/pulls
paths:
read_only: [/opt/fixtures]Hosts merge with the default. A host listed in both uses the access level from the project file. Commit the file so everyone on the project runs with the same rules.
Changing paths or workspace takes effect the next time a sandbox is created. Changing hosts can apply to a running sandbox.
Fields
| Field | Values | Notes |
|---|---|---|
version | 1 | Required. |
name | Text | Shown in the log and on Team. |
agents | Agent names | Which agents may run under this policy. See Agents. |
workspace | read-write, read-only | Access to the project copy. Default read-write. |
paths.read_only | Absolute paths | Extra paths inside the sandbox the agent may read. Paths under a home directory are rejected. |
paths.read_write | Absolute paths | Extra writable paths. / is rejected. |
hosts[].host | Exact host name | Wildcards are not accepted. |
hosts[].port | Number | Default 443. |
hosts[].access | read-only, read-write | See Host access. |
hosts[].allow | METHOD /path | Required with read-write. Each line is one allowed request shape. |
approvals | person | The only value. There is no setting for automatic approval. |
Host access
read-only allows GET, HEAD, and OPTIONS, and blocks everything else. It is a rule about HTTP methods. It does not promise that a server's GET has no side effects.
read-write allows only the requests you list under allow. In a path, * matches within one segment and ** matches across segments. So /repos/acme/web/** covers everything under the repository, but not /repos/acme/web itself.
There is no level that allows every method on a host. If you need it, list the requests.
Every rule is enforced. The sandbox's own default for request rules is to log violations and let them through. Boundlane always sets it to block.
Package registries
- npm. Scoped packages such as
@types/nodeare requested with an encoded slash in the path. Theread-onlylevel already allows it.npm auditsends aPOST, whichread-onlyblocks, so agent images turn audit off. Runnpm auditoutside the sandbox. - pip. Packages download from
files.pythonhosted.org, not onlypypi.org. The default lists both.
What it compiles to
See the compiled policy without starting anything:
boundlane policy compileversion: 1
filesystem_policy:
include_workdir: false
read_only: [/bin, /usr, /lib, /etc, /app, /var/log, /proc, /dev/urandom]
read_write: [/sandbox, /tmp, /dev/null] # /sandbox is the working folder
landlock:
compatibility: hard_requirement
process:
run_as_user: sandbox
run_as_group: sandbox
network_policies:
pypi_org:
name: pypi.org
endpoints:
- host: pypi.org
port: 443
protocol: rest
enforcement: enforce
access: read-only
binaries:
- path: <agent binary> # real path, from the agent catalogA few choices are worth knowing:
hard_requirementmeans the sandbox does not start if the kernel cannot enforce the filesystem rules. The upstream default would start it anyway and log a warning.- The working folder is listed by path instead of with
include_workdir, so the check below can reason about it. - Each host gets its own rule, and the rule names the real path of the agent. Programs the agent starts, such as
pipornpm, use the agent's rules. - The user setting applies on Docker and Podman. Under the MicroVM driver, the sandbox runs as the user the driver configures.
The check before start
Before a sandbox starts, Boundlane runs OpenShell's policy prover. It compares the compiled policy, including access that agent keys add, against a boundary. If any action is possible that the boundary does not allow, the prover names it and nothing starts.
boundlane policy check! Policy check exceeds_boundary
Checked developer-default (built in) + boundlane.yaml for Claude Code.
Example claude can POST to api.github.com:443 /repos/acme/infra/hooksTo fix it, narrow the allow lines for that host, or ask whoever owns the boundary to include it. The command exits with code 2 until the result is within_boundary.
| Result | Meaning | Starts? |
|---|---|---|
within_boundary | Nothing the policy allows is outside the boundary. | Yes |
exceeds_boundary | The prover found an action outside it, and shows one. | No |
unsupported | The policy has a rule type the prover does not model. | No |
inconclusive | The prover could not decide. | No |
error | A file could not be read or parsed. | No |
On Free, the boundary is compiled from the same file. The check then catches access that keys and their profiles add on top of what you wrote. On Team, the security lead publishes the boundary, and project files cannot go past it.
After the sandbox is created, Boundlane runs the check a second time on the policy the sandbox actually holds. If that fails, the sandbox is deleted before the agent starts.
Outside this file
The prover returns unsupported for GraphQL, MCP, WebSocket, and JSON-RPC rules. Raw TCP and TLS passthrough cannot be checked at the request level. The policy file has no fields for them.
An agent cannot use GitHub's GraphQL API, an MCP server over the network, or a database connection inside the sandbox through this file. Outbound MCP on the sandbox's network path is still inspected. A rule for the MCP payload is not.
Pinning a host to an address range is not in the file. A listed host name that resolves to a private address can reach that address, so list internal hosts with care.