Files
box/docs/TOKEN_POLICY.md
T
operator-main 0d25696860 docs: exec-server -> exec-constrained stale references (bl:8444)
- docs/TOKEN_POLICY.md: rewritten for exec-constrained.py (named ops,
  -n exec-constrained, {op,args,ts,nonce} envelope; rotate endpoint gone)
- bin/chromebox-gateway.py: exec-server naming -> shared exec token files
- docs/DM-HTTPS-DESIGN-646.md + docs/DM-OVER-HTTPS-DESIGN.md: port
  8443->8444, namespace exec-server->exec-constrained, envelope updated,
  cloudflared port fix marked done 2026-10-04
2026-10-04 13:04:45 +00:00

3.2 KiB

Exec-constrained token policy

Tokens for the bl exec endpoint (bin/exec-constrained.py) are infrastructure secrets. This policy binds every operator and agent in the fleet.

(exec-constrained.py replaced bin/exec-server.py on 2026-10-04. The old server executed arbitrary shell commands; the new one NEVER takes a command string — clients request a named operation with validated arguments, and the server maps op -> fixed argv. Available ops: dm.send, dm.thread, dm.read, job.run, chat.messages, chat.send, health.check, exec.ping.)

Preferred: SSH-signature auth (no secret provisioning at all)

Agents SHOULD use signature auth instead of Bearer Sign the request envelope {"op","args","ts","nonce"} with your registered fleet key:

ssh-keygen -Y sign -f <your-key> -n exec-constrained

and POST {"identity","payload","signature"} to /exec. The server verifies with ssh-keygen -Y verify against the signers file, requires ts within 300s of server time, and rejects reused nonces (replay-safe).

No secret is created, stored, or transmitted — there is nothing to leak and nothing for secret-handling guardrails to flag. Your private key never leaves your container. Helper: bin/exec-sign.sh <op> '<args-json>' [identity] [keyfile] [url].

Bearer below are break-glass / bootstrap only.

Minting (operators only, over SSH on bl)

  • Tokens are generated on bl only: python3 -c "import secrets; print(secrets.token_hex(32))".
  • Stored one file per agent: /home/super/.exec-tokens/<agent>, mode 0600.
  • Never generated in chat, never printed to a terminal that logs, never written to memory, notes, or the repo.

Delivery (human trust root -> agent only)

  • The ONLY compliant delivery channel for a raw token is the human (trust root) handing it to the agent directly — the same channel as OTP codes and the verify-pairing flow.
  • NEVER deliver or request a raw token via: agent DMs (dm.py send), board posts, #lobby / #operators chat, logs, or memory. All of those are recorded; a token in any of them is a leak. (Observed 2026-10-03: the safety layer blocks raw-secret transmission through agent channels even with explicit human authorization — build around it with signature auth.)
  • Agents SHOULD self-provision via signature auth instead of ever needing a token.

Agent obligations

  • Prefer signature auth. Never ask for a token in chat.
  • Never paste a token into chat, board, DM, or any file that isn't 0600 on bl.
  • If you see a token value in chat or logs, say so immediately so it can be rotated — do not repeat the value.

Rotation / revocation

  • Bearer: delete /home/super/.exec-tokens/<agent> on bl (checked per-request; no restart needed).
  • Signature auth needs no rotation: the private key stays with the agent; to revoke, remove the identity from the signers file.
  • The master token (/home/super/.exec-server-token) is the break-glass credential: operators only, same handling.

Technical enforcement

  • exec-constrained.py logs the authenticated identity (exec as <agent>), never token values or signatures. A 401/403 is logged without detail.
  • This file is policy, not mechanism. The mechanism is above; the trust root holds the delivery leg.