Runner-fleet security model
A runner executes real agent work with real credentials, so its security model is deliberate. This page explains the guarantees behind Set up a runner securely so you can reason about what a runner can and cannot reach.
Pull / outbound-only transport
Section titled “Pull / outbound-only transport”A runner only ever connects out to the hub over HTTPS; the hub never connects in. There is no inbound port to expose, no broker to operate, and the trust boundary is one direction. A runner asks for work only when it has free capacity, which is also a natural backpressure mechanism.
Token model
Section titled “Token model”Each runner authenticates with its own bearer token (scrn_…): 256 bits of
CSPRNG entropy, stored only as a SHA-256 hash server-side. Rotation
(POST /api/runners/{id}/rotate-token) mints a fresh token and invalidates the
old one immediately — rotation is revocation. Tokens are returned exactly once,
at registration or rotation, and never retrievable again.
Required TLS
Section titled “Required TLS”The runner refuses a plaintext http:// hub URL at boot. A token and the
per-run secret bundle must never cross a cleartext link. The only way to allow
http:// is to set SUPACLOUD_RUNNER_ALLOW_INSECURE_TRANSPORT=true explicitly —
acceptable solely on a trusted private network you fully control.
Secrets ride the payload, and only that
Section titled “Secrets ride the payload, and only that”The runner holds no copy of the hub database and no long-lived platform secret. When it claims a task, the launch payload carries exactly the secrets that one task needs (provider keys, git keys, the scope-bound task session token) and nothing else:
- The payload is encrypted at rest on the assignment with a scope-bound AAD; only a redacted preview is stored in clear, the ciphertext is revealed on claim and dropped when the task reaches a terminal state.
- A denylist strips any hub-master secret (the credential-encryption key, vault credentials, the JWT/OIDC/MCP-confirmation secrets, the database URL, chat-bot and billing tokens) from the dispatch payload — defence-in-depth so such a secret can never reach a (possibly third-party) runner even by accident.
Relay redaction
Section titled “Relay redaction”A remote run streams its events back to the hub, which ingests them into the same event pipeline a local run uses. Each relayed event is run through a redactor seeded from that assignment’s resolved secrets before it is persisted or emitted — so a secret echoed into an event by an agent is scrubbed on a remote run exactly as on a local one.
Authoritative server-side gating
Section titled “Authoritative server-side gating”Crucially, a runner having no database does not weaken authorization. The agent’s MCP tool surface and blast-radius limits are enforced server-side, against the task’s session token, on every call — identical for a remote-runner agent and a local one. The runner cannot grant its agent more than the hub allows.
Liveness & at-least-once
Section titled “Liveness & at-least-once”The hub marks a runner offline when its heartbeat goes stale past a bounded
window (default 90 s, floor 45 s, SUPACLOUD_RUNNER_STALE_SECS), stops selecting
it, and re-surfaces its outstanding work — both never-claimed and in-flight
(claimed/running) — failing it, dropping its at-rest per-run secret, and freeing
the task to re-dispatch. The claim itself is race-free (FOR UPDATE SKIP LOCKED)
and a stale runner’s late terminal report is rejected rather than clobbering
re-dispatched work.
Third-party onboarding: enrollment & the scoped runner JWT
Section titled “Third-party onboarding: enrollment & the scoped runner JWT”The scrn_… bearer above is the right credential for a runner you operate.
To onboard a runner on a host you trust less, a second credential class adds
defence-in-depth so the operator never holds a long-lived hub credential and the
runner can only ever serve the workspaces you scoped it to. The operator-facing
steps are in Set up a runner
securely;
the trust model is:
- Single-use, response-wrapped enrollment token. An admin mints a short-TTL enrollment token that carries a scope (trust class, tier, isolation, allowed workspaces + labels). The plaintext is returned exactly once and stored only as a hash. The runner exchanges it on boot, and that exchange burns the token atomically — it cannot be replayed, and a bad or expired token never leaves an orphan runner.
- Scoped runner JWT — never a session. The exchange returns a short-lived
(≤ 1 hour)
scrnj_…JWT whose claims mirror the runner’s grant. It is signed with a domain-separated key derived from the session secret, so a runner JWT never verifies as a user session and a session never verifies as a runner JWT — cross-acceptance fails at the signature check. A requiredtyp = runnerclaim is a belt-and-braces second discriminator. The runner refreshes the JWT before it expires, and each refresh re-checks the grant in the database, so revoking a workspace takes effect within one token lifetime rather than waiting for a redeploy. - Two trust classes. A trusted runner minted with no explicit workspaces holds the wildcard (any workspace) — reserve it for hosts you fully control. An edge runner is untrusted by default and fail-closed: it enrols with an empty workspace set and is dispatched nothing until an owner explicitly grants it a workspace, even while it is online and idle.
- Grant enforced at dispatch. The runner’s grant is a
runner_grantsrow — the authoritative, DB-mutable scope, never something the runner asserts. It is applied as a candidate filter before ranking: a runner can never be sent work outside its grant and can never widen its own scope. A non-empty label set on the grant further requires every task label to be granted (required ⊆ allowed). The pre-enrollment fleet is unaffected — ascrn_…runner with no grant row keeps the implicit trusted wildcard, so dispatch stays byte-identical.
By default only a system admin may mint enrollment tokens; the
runner_onboarding_by_owner instance switch additionally lets organization /
workspace owners onboard edge runners scoped to workspaces they own, never
beyond their own scope.