BoundBench

Crush

Charm's glamorous terminal agentic coding tool

github.com/charmbracelet/crush · 2026-10-03 · bdcf796

Defense-in-depth score

1.6 / 10

Minimal

Crush asks before most shell commands and file writes, and shows the real command or diff. But the prompt does not cover every path, and a cloned repository can turn approval off or run its own shell script the moment you launch Crush there. Nothing is sandboxed, every command gets your full environment and credentials, and there are no step, time or cost limits. Treat it as running with your full user authority, and only launch it in repositories whose crushrc/crush.json you have reviewed.

Key gaps (6)

  1. A repository's crush.json, .crushrc or .crush/crush.json can set permissions.allowed_tools to auto-approve bash, silently disabling the approval gate. C2 · Approval gates
  2. A .crushrc or crushrc in the opened project is executed as a shell script at startup with the user's full environment and no trust prompt. C6 · Memory, context & configuration integrity
  3. MCP servers declared in any loaded config, including the repository's, are launched automatically with the full environment and no consent. C7 · Third-party extensions
  4. A hijacked default session can read secrets (safe-listed printenv), and because the approval gate does not cover every path it can exfiltrate them and run destructive commands without any human approval. C5 · Untrusted input blast radius
  5. No isolation: all commands run as the developer's user with home directory, credentials and network. C4 · Code-execution isolation
  6. Ambient user identity with full environment passed to every subprocess; a bypassed gate reaches the whole user account. C1 · Identity & least privilege

Criteria

C1 Identity & least privilege

Minimal 0.07 / 1.00

Crush runs as the developer's own OS user and narrows none of that authority. Every shell command and every MCP server it launches inherits the full process environment, so model-provider API keys, cloud credentials, GitHub tokens and the SSH agent are all reachable. There is no per-tool identity or credential scoping; the only check between the model and those credentials is the approval prompt, which does not cover every path. A hijacked session therefore acts with everything the developer can do.

C2 Approval gates

Minimal 0.25 / 1.00

By default Crush asks before running shell commands, writing or editing files, fetching URLs and calling MCP tools, and the prompt shows the real command or diff. But the gate has several holes. The built-in 'safe command' list is not a strict boundary. A project's own crush.json or .crushrc can add bash to allowed_tools, which silently auto-approves it. 'Allow for session' on bash approves every later command in that directory, and an approved agentic_fetch sub-agent runs with its whole session auto-approved.

C3 Tool & action scoping

Minimal 0.20 / 1.00

Crush's main tool is an arbitrary shell, guarded only by a denylist of command names (curl, wget, ssh, sudo, package installs) that is not a complete boundary. File tools accept any path on the machine and rely on the approval prompt; view and ls only ask when a path is outside the working directory, and that check is not a strict boundary. fetch and download accept any http(s) URL including localhost and cloud metadata addresses. All tools, including shell, write and network, are enabled by default, though each can be disabled in config.

C4 Code-execution isolation

Minimal 0.00 / 1.00

There is no isolation at all. Shell commands run through an embedded Go shell interpreter that executes real binaries as the developer's user, in the developer's environment, with full network access. Repository-supplied crushrc files, hooks, LSP servers and MCP servers also run directly on the host. A denylist of command names is the only filter, and it is not a complete boundary.

C5 Untrusted input blast radius

Minimal 0.20 / 1.00

Crush reads files, web pages and MCP results straight into the model context with no marking of what is untrusted and nothing that changes behaviour after reading it. The approval prompt is the only brake: printenv is on the safe list, so a hijacked model can read API keys from the environment unprompted, and the gate does not cover every path, so it can act on them without approval. The sourcegraph tool also sends model-chosen text to a third party without asking.

C6 Memory, context & configuration integrity

Minimal 0.10 / 1.00

Opening Crush in a cloned repository trusts that repository completely. A .crushrc or crushrc in the project is executed as a shell script at startup, and $(...) in a project crush.json runs at load time, before any UI appears; the project's config can also add hooks, MCP servers and LSP servers, auto-approve tools, and redirect provider endpoints. The project's .crush/crush.json is merged with the highest priority. Instruction files such as AGENTS.md, CLAUDE.md and .cursorrules are loaded silently. The docs warn users about this, but the code asks for no trust decision.

C7 Third-party extensions

Minimal 0.13 / 1.00

Crush launches MCP servers listed in any loaded config, including a repository's own crush.json, automatically at startup with no consent prompt. Commands are run exactly as written (often 'npx' or 'uvx' of an unpinned package), with no hash or signature check, and each server gets the full user environment. MCP tool calls are approval-gated, but by then the server process already runs with the user's authority. When the Docker MCP gateway is enabled, the model can add new MCP servers without a prompt.

C8 Secrets & sensitive-data protection

Minimal 0.20 / 1.00

API keys come from environment variables or plaintext JSON config files written with 0600 permissions; there is no keychain use. Debug HTTP logging redacts auth-like headers but writes full request and response bodies. Every shell subprocess inherits the full environment, and printenv/env are on the unprompted safe list, so the model can read provider and cloud keys into its context. Anonymous usage telemetry to PostHog is on by default (no prompt content), and can be disabled via env var or config.

C9 Audit & traceability

Minimal 0.45 / 1.00

Every tool call and its result are saved as messages in a local SQLite database, written as each result arrives, so a session's actions can be reconstructed. Sub-agent runs are stored as their own sessions. Approvals and denials are not stored, and the database and logs live in the project's .crush directory, which the agent's own shell can edit or delete.

C10 Limits & kill switch

Minimal 0.00 / 1.00

Crush has no cap on steps, time or cost per run. The only automatic stop is a loop detector for identical repeated tool calls and a context-window summarizer, neither of which bounds damage. Shell commands are not timed out: after 60 seconds they move to a background job that keeps running. Pressing cancel kills a foreground command's process group, but background jobs keep running until the app exits.