Clawker runs every agent in an isolated Docker container with a default-on network firewall. This guide explains the container security controls and how to customize them.Documentation Index
Fetch the complete documentation index at: https://docs.clawker.dev/llms.txt
Use this file to discover all available pages before exploring further.
Network Firewall
The firewall is deny-by-default. When enabled, it blocks all outbound traffic — DNS queries for unlisted domains return NXDOMAIN, and TLS connections to unlisted destinations are reset. Only domains you explicitly allowlist are reachable. This is intentional. The hardcoded allowlist is kept to the bare minimum required for Claude Code itself to function. Everything else — including GitHub, npm, PyPI, or any other service your project needs — must be explicitly configured by you. See the Firewall guide for the full architecture, configuration, CLI commands, and troubleshooting.Hardcoded Allowed Domains
These are the only domains allowed by default — they are required for Claude Code to function (API access, OAuth, telemetry):| Domain | Purpose |
|---|---|
api.anthropic.com | Claude API |
platform.claude.com | OAuth token exchange |
.claude.ai | OAuth authorization, downloads |
mcp-proxy.anthropic.com | MCP tool server proxy |
sentry.io | Error tracking |
statsig.anthropic.com | Feature flags |
statsig.com | Feature flags |
.datadoghq.com | Telemetry (all Datadog subdomains/regions) |
.datadoghq.eu | Telemetry (Datadog EU regions) |
Disabling the Firewall
The global firewall toggle lives insettings.yaml (not the project config):
Agent Awareness Prompt
Every Clawker container image includes an agent prompt file at/etc/claude-code/CLAUDE.md. This file is automatically loaded by Claude Code and gives the agent awareness of its containerized environment:
- What it can and cannot do (filesystem, network, Docker)
- How to diagnose firewall blocks (NXDOMAIN, connection resets, certificate errors)
- What
clawker firewallcommands the user can run on the host to unblock domains - Environment variables available for troubleshooting (
CLAWKER_PROJECT,CLAWKER_AGENT,CLAWKER_FIREWALL_ENABLED, etc.)
clawker firewall add command — without the user needing to know the details.
Container PID 1 and Privilege Drop
The container’s PID 1 isclawkerd, the per-container daemon that supervises Claude Code. clawkerd runs as root inside the container, but it never executes user-controlled code in its own process. The user CMD (Claude Code by default) is forked with kernel-side privilege drop via SysProcAttr.Credential — between fork() and execve() the kernel performs setgroups → setgid → setuid atomically, so there is no user-mode code path between root and the unprivileged claude user (UID 1001).
The clawker control plane talks to clawkerd over a CN-pinned mTLS Session — only a peer holding a cert with CN clawker-controlplane chained to the clawker CA can dispatch commands. See Container Internals → clawkerd for the full PID-1 contract.
Docker Socket
By default, the Docker socket is not mounted into containers:docker_socket: true mounts /var/run/docker.sock read-write into the container. This gives the agent full control over your Docker daemon — it can create, modify, and delete any container, image, or volume on your host. Only enable this if your workflow genuinely requires Docker-in-Docker.
Linux Capabilities
Agent containers require no special privileges for firewall enforcement. eBPF cgroup programs are attached from outside the container by the clawker control plane — raw socket creation is blocked by the eBPFsock_create program rather than by container capabilities.
The supporting infrastructure containers use minimal capabilities. The clawker control plane (clawker-controlplane) runs with CAP_BPF + CAP_SYS_ADMIN to load, attach, and pin eBPF programs and maps. The custom CoreDNS build runs with CAP_BPF + CAP_SYS_ADMIN to open the pinned dns_cache BPF map and update it on DNS responses. Both mount only /sys/fs/bpf — no broader host access. See DNS Cache Population below for why CoreDNS needs these capabilities.
Agent containers default to no extra capabilities (cap_add: []). The cap_add field is available if your workflow needs additional Linux capabilities:
IPv6 Support
Clawker’s firewall is IPv4-first. There are two cases to understand:- Dual-stack sockets (IPv4-mapped IPv6,
::ffff:x.x.x.x). Most modern programs —ssh,curl, Node.js, Python, Go — open dual-stack IPv6 sockets by default and connect to IPv4 targets via IPv4-mapped addresses. The eBPFcgroup/connect6program detects these and applies the same full routing logic as IPv4: DNS redirect to CoreDNS, gateway lockdown, per-domain route lookup via the DNS cache, and Envoy fallback for unknown destinations. From the user’s perspective, dual-stack traffic is enforced identically to pure IPv4. - Native IPv6. Connections to real IPv6 addresses (e.g.,
2606:4700::1or anything forced via-6) are denied. The egress stack (Envoy listeners, CoreDNS forward zones, eBPF DNS cache) is IPv4-only, and there is no safe way to transparently route native IPv6 traffic today. If your workflow requires IPv6 connectivity, prefer hostnames so the container resolves an A record, or open an issue describing the use case.
DNS Cache Population
Per-domain TCP routing in eBPF uses adns_cache BPF map keyed by destination IP. When a container connects to 140.82.121.4, the cgroup hook looks up the IP in the map, recovers the domain hash, and checks the global route_map for a matching {domain_hash, dst_port} rule. This only works if the cache is kept consistent with live DNS responses.
Clawker ships a custom CoreDNS build with an in-tree dnsbpf plugin (internal/dnsbpf/). The plugin intercepts every DNS response for an allowlisted zone, extracts the A records, and writes each (ip → domain_hash, ttl) entry to the pinned dns_cache map in real time. This replaces an earlier startup-time seeding approach that was vulnerable to DNS round-robin rotation: seeded IPs would go stale as CDNs cycled backends, silently blackholing traffic until the firewall was reloaded. The plugin-based approach tracks whatever the upstream resolver returns on every query, so any IP a container actually uses has been observed and hashed at the moment of connection.
The plugin only writes to the BPF map on successful A-record answers. NXDOMAIN and other non-success responses are passed through untouched, so blocked domains never leak into the cache. The custom CoreDNS image is built from a SHA-pinned alpine:3.21 base with the CoreDNS binary copied in — no shell, no package manager, no additional utilities. Its elevated capabilities (CAP_BPF + CAP_SYS_ADMIN) are scoped to the minimum needed for bpf(BPF_OBJ_GET) and bpf(BPF_MAP_UPDATE_ELEM) on the pinned map, and the only host access is a bind mount of /sys/fs/bpf.
TCP/SSH Port-Level Routing
Raw TCP and SSH protocols have no domain-level metadata (no SNI equivalent), so Clawker cannot inspect the intended destination. Instead, eBPF routes all outbound traffic on the configured port to Envoy, which forwards it to the whitelisted domain. For example, aproto: ssh rule for github.com on port 22 means every port 22 connection from the container goes to GitHub, regardless of the destination the agent specified. An attacker cannot reach arbitrary SSH servers — the traffic is locked to the whitelisted target.
This means only one domain can be whitelisted per TCP/SSH port — a tracked limitation, deferred for after the control plane work. See the Firewall guide for details.
Host Proxy
The host proxy is a lightweight daemon that runs on your host machine and forwards credentials into containers. It’s enabled by default:gh auth login). See the Credential Forwarding guide for details.