← Developers
Level 0: resolver Agent runtime

OpenHands

OpenHands runs an application container that creates a runtime container per conversation through the Docker socket. The runtime is where the agent's shell, browser and file tools execute. This guide assigns the app one policy and the runtimes a second.

Runs as
App container that spawns runtime containers through /var/run/docker.sock
Configuration
config.toml [sandbox], SANDBOX_* environment variables
Runtime image
docker.all-hands.dev/all-hands-ai/runtime
Covered here
The Docker runtime

Configuration and reference code for OpenHands

Why

The runtime container has whatever network the daemon gives it. Assigning it a policy inventories every destination the coding agent reaches, holds the ones it has never used, and logs each decision, without changing the image.

Requirements

Two policies, openhands-app and openhands-runtime, each bound to a site. Root on the Docker host.

1. Assign the app container

run.sh
docker run -it --rm --pull=always \
  --dns <openhands-app primary resolver IP> --dns <openhands-app secondary resolver IP> \
  -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:<version>-nikolaik \
  -e SANDBOX_USER_ID=$(id -u) \
  -e SANDBOX_VOLUMES=/path/to/code:/workspace:rw \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v ~/.openhands:/.openhands \
  -p 127.0.0.1:3000:3000 \
  --add-host host.docker.internal:host-gateway \
  --name openhands-app \
  docker.all-hands.dev/all-hands-ai/openhands:<version>

2. Assign the runtime containers

Runtimes are created by the app through the Docker SDK. Set the daemon default, or pass dns in docker_runtime_kwargs. The daemon default also covers a runtime started with a stale config.

/etc/docker/daemon.json
{
  "dns": ["<openhands-runtime primary resolver IP>", "<openhands-runtime secondary resolver IP>"],
  "dns-search": []
}
config.toml (alternative)
[sandbox]
docker_runtime_kwargs = '{"dns": ["<openhands-runtime primary resolver IP>", "<openhands-runtime secondary resolver IP>"]}'

3. Restrict DNS egress

One rule pair on the host covers the app and every runtime. Add the second site's resolvers if the two policies use different pairs.

egress.sh
iptables -I DOCKER-USER -p udp --dport 53 ! -d <primary resolver IP> -j DROP
iptables -I DOCKER-USER -p tcp --dport 53 ! -d <primary resolver IP> -j DROP

4. Learn, then enforce

Import the model provider template on openhands-app. On openhands-runtime, import the package registry template only if the role installs dependencies. Run Learn Only for seven days, review New Query events, approve, then set Default Action to Deny and Greywall Mode to Enforce.

Verify

Ask the agent to run the commands in a conversation, and run them with docker exec on the app container.

verify.sh
getent hosts first-seen-$(date +%s).example      # expected: <block page address>
dig +time=2 +tries=1 @8.8.8.8 example.com        # expected: connection timed out
getent hosts api.openai.com                      # expected: a public address

Limits

The remote runtime (OpenHands Cloud) is not covered. Connections to a raw IP are governed by the egress firewall.

Vendor documentation this page was verified against

Vendor settings change. Securd behaviour on this page (the block page answer, the per-policy baseline, the DoH base) is a property of the product and does not.

Evaluate Agent DNS with your own agent traffic

Deploy on a single policy in learning mode and review the recorded destinations with your team.