Hardening Checklist
Set a Write Token
When binding to a non-loopback address, always set a write token:All mutating requests (POST, PUT, PATCH, DELETE) then require:
Enable gVisor (Optional)
For defense-in-depth container isolation:Requires
runsc installed on the Docker host.Write Guard
All mutating API requests are protected by a write guard middleware:| Scenario | Behavior |
|---|---|
Request from loopback (127.0.0.1, ::1) | Allowed — no token required |
Non-loopback, no RISOLUTO_WRITE_TOKEN set | 403 write_forbidden |
RISOLUTO_WRITE_TOKEN set, valid bearer token | Allowed from any address |
RISOLUTO_WRITE_TOKEN set, missing/invalid token | 401 write_unauthorized |
GET, HEAD, OPTIONS) are exempt from write guard checks and always allowed from any address.
Webhook routes (/webhooks/*) bypass IP/token checks — they use their own HMAC signature verification.
Credential Encryption
Risoluto encrypts all stored credentials using AES-256-GCM with a key derived fromMASTER_KEY via SHA-256:
| Property | Value |
|---|---|
| Algorithm | AES-256-GCM |
| IV length | 12 bytes (random per write) |
| Auth tag | 16 bytes (GCM authentication) |
| Key derivation | SHA-256 of MASTER_KEY |
| Storage | secrets.enc (file-backed) or encrypted_secrets table (SQLite) |
| Audit trail | secrets.audit.log records every set/delete operation |
DbSecretsStore) encrypts each secret individually with its own IV and auth tag, stored as separate rows. Key names are plaintext; values are encrypted.
Network Isolation
Network Isolation
Worker containers run on the
risoluto-internal Docker bridge network by default. The data plane (when using control/data plane split) is not exposed to the host — it only listens on this private network.For additional isolation, use a custom Docker network:Capability Dropping
Capability Dropping
When
codex.sandbox.security.dropCapabilities is true (default), worker containers start with --cap-drop=ALL. Combined with noNewPrivileges: true, this ensures containers cannot escalate privileges.The resulting docker run flags:gVisor Runtime
gVisor Runtime
gVisor (This passes
runsc) provides a user-space kernel that intercepts all syscalls from the container, adding a strong isolation boundary between the agent and the host kernel.--runtime=runsc to Docker. Install gVisor first:Egress Allowlists
Egress Allowlists
The This is enforced via the Codex sandbox policy. An empty list (default) allows all outbound traffic.
egressAllowlist restricts which domains worker containers can reach. When the list is non-empty, only listed domains are reachable:Seccomp Profiles
Seccomp Profiles
For fine-grained syscall filtering, specify a custom seccomp profile:This passes
--security-opt=seccomp=/etc/docker/seccomp-risoluto.json to Docker.Sandbox Policy Summary
| Policy | Default | Effect |
|---|---|---|
noNewPrivileges | true | Prevents privilege escalation via setuid/setgid binaries |
dropCapabilities | true | Drops ALL Linux capabilities (--cap-drop=ALL) |
gvisor | false | User-space kernel for syscall interception |
seccompProfile | "" | Custom seccomp profile (empty = Docker default) |
egressAllowlist | [] | Domain-level egress filtering (empty = allow all) |
threadSandbox | "workspace-write" | Agent can only write to its workspace directory |
turnSandboxPolicy | {type: "workspaceWrite"} | Per-turn sandbox: workspace write + no network access |
Rate Limiting
All/api/* and /metrics endpoints are rate-limited to 300 requests per 60 seconds per client. Webhook endpoints (/webhooks/linear) have a separate limit of 600 requests per 60 seconds. Exceeding the limit returns HTTP 429 Too Many Requests.
Filesystem Paths
Host-Side
| Path | Purpose | Safe to delete? |
|---|---|---|
.risoluto/ (or $DATA_DIR) | SQLite DB, config overlay, encrypted secrets | No — lose all history |
../risoluto-workspaces/ | Per-issue workspace directories | Yes — re-created on dispatch |
~/.codex/ | Codex CLI auth credentials | Partial — need codex login again |
Inside Worker Containers
| Path | Purpose |
|---|---|
/home/agent/.codex-runtime | Ephemeral per-attempt CODEX_HOME |
/home/agent | Container HOME with build caches |
/workspace | Bind-mounted issue workspace |
Environment Variables
| Variable | Default | Description |
|---|---|---|
RISOLUTO_BIND | 127.0.0.1 | HTTP bind address |
RISOLUTO_WRITE_TOKEN | — | Bearer token for remote write access |
MASTER_KEY | — | Encryption key for the secrets store |
What’s Next
Trust Model
Understand Risoluto’s trust boundaries and threat model.
Custom Sandbox
Build a custom sandbox image with your project’s toolchain.