Skip to content

Trust

Security

Arcturn’s safety features are controls with edges, and the edges are written down. A safety feature whose limits you can’t see is worse than no feature, because you’ll trust it.

The choke point

Enforcement happens in one place: the runtime’s tool dispatcher checks the permission engine and returns a denial before a tool’s execute is ever reached. There is no second path into a tool, which is the property that makes the rest of this page meaningful — a control with two entrances is not a control.

Read-only tools pass without a prompt. fetch is deliberately excluded from that list: it reads nothing local but sends data to an arbitrary host, so it is gated like a mutating tool. Anything that reaches the ask step with no permission requester configured resolves to deny — and in non-interactive mode, where there is no user to answer, a check that would have prompted is denied automatically with a note on stderr saying which flag would have allowed it.

The controls

Eight layers, each doing one thing. None of them is a boundary you should treat as airtight on its own; together they are the difference between an agent you supervise and an agent you hope about.

Permission engine

A rule-based allow/deny/ask resolver checked by the tool dispatcher before a tool’s execute is reached. Rules are scoped session over project over user, and a more specific deny beats a broader permissive rule even from a nearer scope.

Checkpoints

Before a write or edit touches a file for the first time in a turn, its prior content — or its absence — is stored as a content-addressed blob. /rewind restores those files and forks the conversation instead of deleting it.

Dry-run overlay

--dry-run reroutes every file mutation into a shadow copy of the workspace. You review one aggregate diff with /diff, then /apply writes back through a temp-file-plus-rename, or /discard deletes the shadow tree.

OS sandbox

Opt-in, and separate from dry run: with "sandbox": "workspace-write", a bash command is wrapped by sandbox-exec on macOS or Bubblewrap on Linux. Writes are denied everywhere except the working directory, the OS temp directory and $HOME/.arcturn.

Taint tracking

Distinctive text from fetch, websearch and MCP output is remembered, and a later mutating call whose arguments repeat it is flagged. Extraction is biased toward silence — a tracker that cries wolf gets turned off.

Canary tokens

High-entropy decoy tokens, or real secret values you register yourself, are watched on the way out. Any egress-capable tool call whose arguments contain one verbatim is treated as exfiltration in progress.

Cost ceiling

Cost accounting is always on and updated after every turn. --max-cost aborts the run the moment cumulative spend reaches the ceiling, including spend from sub-agents — an enforcement mechanism, not a warning.

Audit trail

An append-only log of every completed tool call, every interactive permission decision and every hook verdict, recorded as the run happens rather than reconstructed afterwards. Enable it with "audit": true.

Known limits

Every control above has an edge it does not cover. These are disclosures, not failures — they are here so that you calibrate to what the feature actually does rather than to its name.

  • Permission engine

    Two edges, both structural. alwaysAllowTools is consulted at step 1 of resolution, before any rule: a tool on that list is allowed without the rule set being reached at all, so a host that widens it past the runtime’s own todo and plan puts those tools beyond even a deny. And a rule matches the subject a tool reports — an absolute path from write and edit, the command line from bash, tested per shell segment — so a path rule never sees the path a shell command reaches by another spelling: deny **/*.env stops an edit of that file and does not stop cat .env.

  • Checkpoints and /rewind

    Only write and edit are checkpointed. A shell command that mutates the tree is not, so sed -i and rm are invisible to /rewind and will not come back. The conversation side is genuinely non-destructive; the file side is a real disk mutation.

  • Dry-run overlay

    --dry-run deliberately does not wrap bash, grep or glob — they take commands and patterns rather than a single path — so a shell command still reads and mutates the real tree while dry-run is active.

  • Canary tokens

    Matching is exact substring containment, so any encoding of the secret defeats it completely: base64 the value and nothing fires. It catches a verbatim leak, not a determined exfiltrator.

  • Taint tracking

    Matching is substring containment over whitespace-normalized text, one direction only and case-sensitive. A genuine echo of an injected instruction is verbatim; an instruction the model paraphrases rather than repeats is not detected.

  • OS sandbox

    It narrows write access only — reads, network access and process spawning are left alone — and it needs a backend: sandbox-exec on macOS or bwrap on Linux. Anything else is unsupported.

  • Speculative approval

    Not one of the eight above: speculation is off by default and is introduced on Control. Only write and edit can be speculated, because only file mutations can be undone by throwing a directory away. Everything else is blocked outright while a speculation is open — including a bash call that would only have touched files, because the wrapper cannot know that in advance.

  • Cost ceiling

    The guard checks cumulative cost after every turn, so it aborts at the next turn boundary rather than mid-turn. A limit of 0, or leaving it unset, disables the guard entirely.

  • Audit trail and provenance

    Both are off by default and record only while enabled — a session you did not turn them on for cannot be reconstructed retroactively. The permission log captures the interactive ask path only: a decision resolved automatically by a rule or by the mode has no toolName to attribute and never reaches it, though the tool call itself is still captured.

Adversarial review

The codebase has been through four waves of adversarial review — parallel reviewers whose only job was to break the new seams. The findings are published here rather than quietly patched out, because a security feature that has never been adversarially poked at is a claim, not a control.

The findings were not cosmetic:

  • /apply could write outside the workspace through an in-workspace symlink.
  • Served sessions and sub-agents escaped the audit trail entirely.
  • The WebSocket upgrade had no Origin check, so any web page could drive a loopback server.
  • Two features were present but unreachable: the canary guard was watching a generated token nobody had ever seen, and speculative approval could never shelter a single byte because tools ran sequentially.

Every fix landed with a regression test verified to fail against the previous behaviour first.

Reporting a vulnerability

Open an issue on GitHub. If you would rather not describe the problem in public, open an issue saying so and I will follow up there.

This is a pre-1.0, single-maintainer project; there is no SLA. I would still rather hear about it than not.

Read the limits, then run it.

Every control on this page has an edge, and every edge is written down. Start a session and watch the first one hold.

npm install -g arcturn