Skip to main content

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.

This tutorial shows how OpenShell’s network policy system works in under five minutes. You create a sandbox, watch a request get blocked by the default-deny policy, apply a fine-grained L7 rule, and verify that reads are allowed while writes are blocked — all without restarting anything. After completing this tutorial, you will understand:
  • How default-deny networking blocks all outbound traffic from a sandbox.
  • How to apply a network policy that grants read-only access to a specific API.
  • How L7 enforcement distinguishes between HTTP methods such as GET and POST on the same endpoint.
  • How to inspect deny logs for a complete audit trail.

Prerequisites

  • A working OpenShell installation. Complete the Quickstart before proceeding.
  • Docker Desktop running on your machine.
To run every step of this tutorial non-interactively, use the automated demo script in the examples/sandbox-policy-quickstart directory. It runs the full walkthrough in under a minute.
bash examples/sandbox-policy-quickstart/demo.sh

Tutorial

1

Create a sandbox

Create a sandbox with no network policies. This gives you a clean environment to observe default-deny behavior.
$ openshell sandbox create --name demo --keep --no-auto-providers
--keep keeps the sandbox running after you exit so you can reconnect later. --no-auto-providers skips the provider setup prompt since this tutorial uses curl instead of an AI agent.You land in an interactive shell inside the sandbox:
sandbox@demo:~$
2

Try to reach the GitHub API

With no network policy in place, every outbound connection is blocked. Test this by making a simple API call from inside the sandbox:
$ curl -s https://api.github.com/zen
https://api.github.com/zen is a lightweight, unauthenticated GitHub REST endpoint that returns a random aphorism. It requires no tokens or parameters, which makes it a convenient smoke-test target for verifying outbound HTTPS connectivity.The request fails. The sandbox proxy intercepted the HTTPS CONNECT request to api.github.com:443 and rejected it because no network policy authorizes curl to reach that host.
curl: (56) Received HTTP code 403 from proxy after CONNECT
Exit the sandbox. The --keep flag keeps it running:
$ exit
3

Check the deny log

Every denied connection produces a structured log entry. Query the sandbox logs from your host to confirm the denial and inspect the reason.
$ openshell logs demo --since 5m
You see a line like:
action=deny dst_host=api.github.com dst_port=443 binary=/usr/bin/curl deny_reason="no matching network policy"
Every denied connection is logged with the destination, the binary that attempted it, and the reason. Nothing gets out silently.
4

Create the policy file

To allow the sandbox to reach the GitHub API, define a network policy that grants read-only access. Create a file called github-readonly.yaml with the following content:
github-readonly.yaml
version: 1

filesystem_policy:
  include_workdir: true
  read_only: [/usr, /lib, /proc, /dev/urandom, /app, /etc, /var/log]
  read_write: [/sandbox, /tmp, /dev/null]
landlock:
  compatibility: best_effort
process:
  run_as_user: sandbox
  run_as_group: sandbox

network_policies:
  github_api:
    name: github-api-readonly
    endpoints:
      - host: api.github.com
        port: 443
        protocol: rest
        enforcement: enforce
        access: read-only
    binaries:
      - { path: /usr/bin/curl }
The filesystem_policy, landlock, and process sections preserve the default sandbox settings. This is required because policy set replaces the entire policy.The network_policies section is the key part: curl may make GET, HEAD, and OPTIONS requests to api.github.com over HTTPS. Everything else is denied. The proxy auto-detects TLS on HTTPS endpoints and terminates it to inspect each HTTP request and enforce the read-only access preset at the method level.
This tutorial uses curl and read-only access to keep things simple. When building policies for real workloads:
  • To scope the policy to an agent, replace the binaries section with your agent’s binary, such as /usr/local/bin/claude, instead of curl.
  • To grant write access, change access: read-only to read-write or add explicit rules for specific paths. Refer to the Policy Schema Reference.
  • To allow additional endpoints, stack multiple policies in the same file for PyPI, npm, or your internal APIs. Refer to Policies for examples.
5

Apply the policy

Apply the policy to the running sandbox:
$ openshell policy set demo --policy github-readonly.yaml --wait
--wait blocks until the sandbox confirms the new policy is loaded. No restart required. Policies are hot-reloaded.
6

Verify GET requests are allowed

Reconnect to the sandbox and retry the same request to confirm that read access works.
$ openshell sandbox connect demo
Retry the request:
$ curl -s https://api.github.com/zen
Anything added dilutes everything else.
The read-only preset allows GET requests through.
7

Try a write operation

The read-only preset allows GET but blocks mutating methods like POST, PUT, and DELETE. Test this by sending a POST request while still inside the sandbox:
$ curl -s -X POST https://api.github.com/repos/octocat/hello-world/issues \
    -H "Content-Type: application/json" \
    -d '{"title":"oops"}'
{"error":"policy_denied","policy":"github-api-readonly","detail":"POST /repos/octocat/hello-world/issues not permitted by policy"}
The CONNECT request succeeded because api.github.com is allowed, but the L7 proxy inspected the HTTP method and returned 403. POST is not in the read-only preset. An agent with this policy can read code from GitHub but cannot create issues, push commits, or modify anything.Exit the sandbox:
$ exit
8

Check the L7 deny log

L7 denials are logged separately from connection-level denials. The log entry includes the exact HTTP method and path that the proxy rejected.
$ openshell logs demo --level warn --since 5m
l7_decision=deny dst_host=api.github.com l7_action=POST l7_target=/repos/octocat/hello-world/issues l7_deny_reason="POST /repos/octocat/hello-world/issues not permitted by policy"
The log captures the exact HTTP method, path, and deny reason. In production, pipe these logs to your SIEM for a complete audit trail of every request your agent makes.
To log violations without blocking requests, set enforcement: audit instead of enforcement: enforce in the policy. This is useful for building a policy iteratively: deploy in audit mode, review the logs, and switch to enforce when the rules are correct.
9

Clean up

Delete the sandbox to free resources. This stops all processes and purges any injected credentials.
$ openshell sandbox delete demo

What just happened

StateWhat happens
Default denyAll outbound traffic is blocked — nothing gets out without an explicit policy
L7 read-onlyGET to api.github.com is allowed; POST is blocked at the HTTP method level
Audit trailEvery request is logged with the method, path, binary, and decision
The policy hot-reloads in seconds and gives you verifiable, fine-grained control over what your agent can access — without --dangerously-skip-permissions.

What’s next

GitHub push access

Walk through a full policy iteration with Claude Code, including diagnosing denials and applying fixes from outside the sandbox.

Policy schema reference

Learn about all available policy fields, access presets, and rule syntax.

Sandbox policies

See full policy examples for PyPI, npm, and internal APIs.

Policy audit mode

Use enforcement: audit to log violations without blocking, then promote to enforce.

Build docs developers (and LLMs) love