Security Model
The CLI is an execution edge, not an authority. Every property below is enforced by the server or by a check the CLI cannot skip, and each maps to a command you can run to see it.
Credential absence
The CLI holds no signing secret. A lease is an HMAC-signed token the server issues on claim and verifies again on POST /cli/claim/<leaseId>/verify before anything runs; the CLI only decodes the payload to read the act axes after that round trip succeeds. There is no configuration that lets vagaris dev spawn without a verified lease, and no local path that mints one.
Deny by default
A lease without a tool policy means no tools, and a none policy refuses the spawn. Claude Code is launched with --allowedTools derived from the lease and never with claude --dangerously-skip-permissions; Codex is launched with codex --tool. Unknown adapters are refused rather than run unbounded. See Permissions.
Privileged acts never happen locally
Pushing to a main branch, deploying, writing to a production database, mutating infrastructure, reading a secret or changing billing are brokered: the CLI sends a request, the server executes, approves, parks or denies, and the CLI reports the verdict. No local credential exists for these classes.
Machine identity
vagaris node enroll generates an Ed25519 key pair; the private key is written to ~/.vagris/node-identity.json (mode 0600) and never sent anywhere. vagaris node doctor proves possession by signing a server nonce. A lease bound to a node is refused from any other node; vagaris node revoke invalidates the node's leases and cancels its runs server-side. See Node Enrolment.
Containment of the executor
- Worktree isolation. Each run executes in its own git worktree, removed afterwards.
- Environment sanitising. Before the spawn, the child environment is stripped of product variables,
LD_*/DYLD_*,GIT_CONFIG_*,NODE_OPTIONSand other interpreter and shell startup hooks, infrastructure write tokens and seat-forbidden inherited secrets. The keys removed are listed in thedevreport asstrippedEnvKeys. - Kill-switch integrity.
runctl cancelreportscancelledonly when the server has confirmed the process is dead. A run whose process survived the kill attempt is shown as still running — never a false stop.
Evidence
Every governed run records session boundaries, policy decisions (with the gate that made them), baseline probes, the executed command and its output, scope requests and errors into an evidence envelope the server can audit. dev prints the counts and the closure-gate verdict.
Credentials on your machine
- Board login tokens are stored in the OS credential store (macOS Keychain via
security, Linux Secret Service viasecret-tool);~/.vagris/auth.jsonholds only metadata. Without a credential store, a login is used for the current command and not persisted, and the CLI says so. vagaris auth logoutrevokes server-side before deleting locally.vagaris uninstalldoes the same before removing files.- Agent API keys are printed once by
vagaris agent local-cli. Prefercontext set --api-key-env-var-nameover writing a key into the context file. - The
.envnext to the instance config (which holdsPAPERCLIP_AGENT_JWT_SECRET) is written with mode 0600.
Writing into other tools' directories
The CLI never writes into ~/.claude or ~/.codex unless you pass --install-skills to vagaris agent local-cli and consent (interactively, or with --yes). What it wrote is recorded, and vagaris uninstall lists those links and leaves them in place rather than deleting inside another tool's home.
Support bundles and telemetry
vagaris support-bundle passes every field through a redactor: vendor API keys, tokens, connection strings, PII and raw customer content are replaced with stable [REDACTED:kind:hash] placeholders; environment variables are included by name only; source code and database rows are never collected. See Support.
Telemetry is anonymous usage data, disabled by VAGARIS_TELEMETRY_DISABLED=1 (legacy PAPERCLIP_TELEMETRY_DISABLED=1), by DO_NOT_TRACK=1, automatically in CI, or by telemetry.enabled: false in the instance config.
Known limits
- Revoking a node changes server state; a process already running on that node stops the next time it contacts the server, not at the moment of revocation.
- Leases have a bounded lifetime, but an expired lease is refused on verification rather than swept proactively.
- The MCP server ships with a stdio transport; there is no HTTP MCP endpoint to expose.
The full threat model with per-control status lives in the repository at doc/security/threat-model-cli.md.
Reporting a vulnerability
Use the repository's GitHub Security Advisory form — never a public issue. Details on Support.