Security model
What is isolated from what, and where a decision needs a person.
Rokkhe executes untrusted work against systems you own. The model below is what keeps that from becoming a liability: separation you can inspect, defaults that fail closed, and consequential actions that stop at a person.
#Network separation
The stack runs on three networks so a compromise of one tier does not reach the next. This is enforced by the deployment, not by convention.
| Network | Carries | Reaches the database |
|---|---|---|
| edge | caddy, web, api, auth | Through the API only. |
| data | database, redis, api, auth, worker, migrate | Yes — and nothing here is routable from the internet. |
| sandbox | worker, and each scan’s container | No route at all. |
A scan’s container joins the sandbox network and nothing else. A target that compromises the scanner reaches neither your findings nor your accounts.
#Container hardening
- no-new-privileges is set, so a process cannot gain capabilities it did not start with.
- The edge drops ALL capabilities and runs on a read-only root filesystem.
- Memory and PID limits are set per service, so one runaway process cannot starve the host.
- The sandbox image is pinned by the deployment rather than resolved at scan time.
#Egress
A sandbox has no direct route out. Where the optional egress gateway is deployed, it is the single deliberate exit, and it takes an allowlist: which hosts, which ports, how many requests, and at what rate. Scope it to the engagement target to bound a deployment tightly.
#Configuration fails closed
The production overlay has no defaults for the database password, the connection string, the public origin, or the auth secret. The stack refuses to render without them rather than starting with a placeholder.
docker-compose.yml on its own ships development credentials so a local stack needs no setup. Running it alone on a reachable host publishes a deployment whose secrets are in the repository. Always pass the production overlay as well.
#Credentials
Integration credentials are encrypted with a keyring you supply, identified by an active key id. Rotation and revocation are separate operations with different consequences, and a deployment missing the key fails where the credential is used rather than where it is stored — plan key changes as a deployment step, not a settings change.
#Workspace boundary
Every record carries the workspace that produced it, and the boundary is enforced where data is read rather than in the interface. A collector’s events, a run’s findings, and a case’s evidence all inherit it.
#The approval boundary
Investigation proposes; it does not act. A response intent carries the plan, the evidence, and the reasoning, and waits for a named person to approve it. The actor is recorded at that step, which is what makes the record defensible afterwards.
A proposal that has not reproduced is presented as a proposal. Escalation happens after an exploit reproduces in a sandbox, not on the strength of a pattern match.
#Health probes are internal
The edge answers 404 for /health/* because the detailed payload names versions, environment, and dependency state. /api/health is the public compatibility endpoint and reports only status and readiness.