> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/NVIDIA/OpenShell/llms.txt
> Use this file to discover all available pages before exploring further.

# Policies

> Apply, iterate, and hot-reload sandbox network policies on running OpenShell sandboxes without restarting.

Use this page to apply and iterate policy changes on running sandboxes. For a full field-by-field YAML definition, refer to the [Policy schema reference](/reference/policy-schema).

## 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 can be hot-reloaded on a running sandbox.

```yaml theme={null}
version: 1

# Static: locked at sandbox creation.
filesystem_policy:
  read_only: [/usr, /lib, /etc]
  read_write: [/sandbox, /tmp]

# Static: Landlock LSM kernel enforcement.
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 without restarting the sandbox.
network_policies:
  my_api:
    name: my-api
    endpoints:
      - host: api.example.com
        port: 443
        protocol: rest
        enforcement: enforce
        access: full
    binaries:
      - path: /usr/bin/curl
```

| Section             | Type    | Description                                                                                                                                                                                                                                                                                                                                               |
| ------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `filesystem_policy` | Static  | Controls which directories the agent can access on disk. Paths are split into `read_only` and `read_write` lists. Any path not listed in either list is inaccessible. [Landlock LSM](https://docs.kernel.org/security/landlock.html) enforces these restrictions at the kernel level.                                                                     |
| `landlock`          | Static  | Configures Landlock LSM enforcement behavior. Set `compatibility` to `best_effort` (use the highest ABI the host kernel supports) or `hard_requirement` (fail if the required ABI is unavailable).                                                                                                                                                        |
| `process`           | Static  | Sets the OS-level identity for the agent process. `run_as_user` and `run_as_group` default to `sandbox`. Root (`root` or `0`) is rejected. The agent also runs with seccomp filters that block dangerous system calls.                                                                                                                                    |
| `network_policies`  | Dynamic | Controls outbound network access. Each block pairs allowed endpoints (host, port, protocol) with allowed binaries. Every outbound connection — except `https://inference.local` — goes through the proxy, which checks the destination and calling binary against policy. A connection is allowed only when both match an entry in the same policy block. |

<Note>
  Static sections (`filesystem_policy`, `landlock`, `process`) are locked at sandbox creation. Changing them requires destroying and recreating the sandbox. The `network_policies` section can be updated on a running sandbox with `openshell policy set`.
</Note>

## Apply a custom policy

Pass a policy YAML file when creating the sandbox:

```bash theme={null}
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:

```bash theme={null}
export OPENSHELL_SANDBOX_POLICY=./my-policy.yaml
openshell sandbox create -- claude
```

## Iterate on a running sandbox

The policy iteration workflow is: create the sandbox, monitor logs for denied actions, pull the current policy, modify it, push it, verify. Repeat until the agent can reach everything it needs.

<Steps>
  <Step title="Create the sandbox with your initial policy">
    Follow [Apply a custom policy](#apply-a-custom-policy) above, or set `OPENSHELL_SANDBOX_POLICY`.
  </Step>

  <Step title="Monitor denials">
    Each log entry shows host, port, binary, and reason. Use `openshell term` for a live dashboard.

    ```bash theme={null}
    openshell logs <name> --tail --source sandbox
    ```
  </Step>

  <Step title="Pull the current policy">
    Strip the metadata header (Version, Hash, Status) before reusing the file.

    ```bash theme={null}
    openshell policy get <name> --full > current-policy.yaml
    ```
  </Step>

  <Step title="Edit the policy YAML">
    Add or adjust `network_policies` entries, binaries, `access`, or `rules`.
  </Step>

  <Step title="Push the updated policy">
    Exit codes: `0` = loaded, `1` = validation failed, `124` = timeout.

    ```bash theme={null}
    openshell policy set <name> --policy current-policy.yaml --wait
    ```
  </Step>

  <Step title="Verify the new revision">
    If status is `loaded`, repeat from step 2 as needed. If `failed`, fix the policy and repeat from step 4.

    ```bash theme={null}
    openshell policy list <name>
    ```
  </Step>
</Steps>

## Hot-reload behavior

Changes to `network_policies` take effect immediately — no sandbox restart required. The proxy picks up the new revision within seconds of `openshell policy set` completing.

Changes to static sections (`filesystem_policy`, `landlock`, `process`) cannot be hot-reloaded. You must destroy and recreate the sandbox with the updated policy.

## Global policy override

Use a global policy to apply one policy payload to every sandbox:

```bash theme={null}
openshell policy set --global --policy ./global-policy.yaml
```

When a global policy is configured:

* The global payload is applied in full for all sandboxes.
* Sandbox-level policy updates are rejected until the global policy is removed.

To restore sandbox-level policy control:

```bash theme={null}
openshell policy delete --global
```

To inspect a sandbox's effective settings and policy source:

```bash theme={null}
openshell settings get <name>
```

## Policy examples

Add these blocks to the `network_policies` section of your sandbox policy. Apply with `openshell policy set <name> --policy <file> --wait`.

<Tabs>
  <Tab title="Simple endpoint">
    Allow `pip install` and `uv pip install` to reach PyPI:

    ```yaml theme={null}
    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` use TCP passthrough — the proxy allows the stream without inspecting payloads.
  </Tab>

  <Tab title="Granular rules (REST)">
    Allow Claude and the GitHub CLI to reach `api.github.com` with per-path rules: read-only access for all paths, GraphQL via POST, full write access for `alpha-repo`, and create/edit issues only for `bravo-repo`. Replace `<org_name>` with your GitHub org or username.

    ```yaml theme={null}
    github_repos:
      name: github_repos
      endpoints:
        - host: api.github.com
          port: 443
          protocol: rest
          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` enable HTTP request inspection. The proxy auto-detects TLS on HTTPS endpoints, terminates it, and checks each HTTP request against the `rules` list.
  </Tab>
</Tabs>

## Debug denied requests

Check `openshell logs <name> --tail --source sandbox` for the denied host, path, and binary.

When triaging a denied request, check:

* **Destination host and port** — confirm which endpoint entry is missing.
* **Calling binary path** — confirm which `binaries` entry needs to be added or adjusted.
* **HTTP method and path** (for REST endpoints) — confirm which `rules` entry needs to be added or adjusted.

Then push the updated policy as described in [Iterate on a running sandbox](#iterate-on-a-running-sandbox).

## Next steps

<CardGroup cols={2}>
  <Card title="Policy schema reference" icon="file-text" href="/reference/policy-schema">
    Full field-by-field YAML definition for all policy sections.
  </Card>

  <Card title="Default policy reference" icon="shield" href="/reference/default-policy">
    Breakdown of the built-in default policy and agent compatibility.
  </Card>

  <Card title="Architecture" icon="diagram-project" href="/concepts/architecture">
    Sandbox isolation layers and network access rules explained.
  </Card>

  <Card title="GitHub sandbox tutorial" icon="book" href="/tutorials/github-sandbox">
    End-to-end walkthrough combining a GitHub provider with a scoped policy.
  </Card>
</CardGroup>
