HomeBlog › The bash allowlist: safe-by-default shell execution for agents
Blog

The bash allowlist: safe-by-default shell execution for agents

Jul 19, 20265 min readBy the Rysh team

Approve everything and you'll rubber-stamp. Approve nothing and the agent is useless. Rysh's answer: an allowlist where unknown means ask.

Give an agent a shell and you've made a choice, whether you admit it or not.

Option one: it asks permission for every command. By day two you're hammering "approve" on ls without reading it — and the day it slips rm -rf into the queue, your reflexes approve that too. Blanket prompting doesn't produce safety; it produces rubber-stamp fatigue.

Option two: it asks for nothing. Fast, fun, and you've handed root-adjacent power to a stochastic process. Everyone has read at least one postmortem that starts this way.

Rysh picks a third option, and it's the boring, correct one from decades of security engineering: an allowlist, with safe-by-default fallthrough.

The policy in one paragraph

When a rysh agent calls the bash tool, the command is classified before it runs. Read-only and idempotent commands execute freely — no prompt, no friction. Everything else asks you first. And "everything else" explicitly includes the command the classifier doesn't recognize: unknown means ask, never "probably fine."

What runs free

The allowlist covers the commands an engineer runs a hundred times a day to look at the world without changing it:

Notice what these have in common: run them once or run them fifty times, the world is the same afterwards. That's the property the allowlist encodes — not "commands we like," but idempotence and read-only-ness. It's why an agent in rysh can investigate a bug at full speed: grep the codebase, walk the git history, run the tests, list the processes — zero prompts, because zero risk.

(Yes, go test can technically mutate things if your tests are badly behaved. The allowlist encodes the contract that tests are hermetic; if yours aren't, that's worth fixing for reasons well beyond rysh.)

What gets stopped at the gate

The RequiresApproval check on rysh's bash tool flags the shapes that change the world or smuggle in something that could:

When one of these comes up, you get a pre-approval prompt: the command, what the agent says it's for, and a decision that's rare enough to actually think about. That's the payoff of the allowlist — by letting the safe 90% flow, the 10% that reaches you deserves and gets your attention.

One more deliberate wrinkle: git commit isn't even in the bash game. It's a dedicated, always-gated tool (git_commit), because writing to your repo history is a decision with your name on it. Reads are bash; commits are ceremony.

Why shape-based classification beats vibes

A tempting alternative is to let the model itself judge "is this command safe?" Don't. The model is the thing being governed; it can't also be the governor. Rysh's classification is structural — it looks at what the command is (read vs mutate, redirect vs not, substitution vs not), not at how confidently anyone describes it.

Structural rules are auditable. You can read the policy and predict, for any command, whether it will prompt. No surprises in either direction — and no prompt-injection path where a cleverly-worded task convinces anyone that curl | sh is "just reading."

This layers with the rest of rysh's governance rather than standing alone: file edits are preview-first (you see the diff before disk changes), every tool call is visible in the pane as it happens, and secrets are redacted client-side before output leaves your machine. The allowlist is one gate in a fence, not the fence.

The trust curve this buys you

Here's what actually happens on teams that adopt agents: trust isn't granted, it's accumulated. Day one, you read every prompt. Week two, you've watched the agent's mutating commands be sensible fifty times, and each approval takes two seconds. The gate never disappears — but it stops being friction and becomes a heartbeat: proof that you're still the one holding the pen for anything irreversible.

That's the honest pitch. Not "our agent never makes mistakes" — it runs on Claude (your API key, your machine — rysh is self-hostable), and no model is infallible. The pitch is: the mistakes an agent can make without you are read-only. Everything else has your fingerprint on it.

Safe by default. Fast where it's free. Loud where it counts.


This is the governance layer teams keep telling us they were missing. Help us shape it — become a design partner: rysh.ai/design-partner.

More in this series: Preview-first editing: coloured diffs before anything touches disk · Is it safe to let an agent loose on your systems? An honest checklist

Try Rysh

Every pane is a shell and an AI agent — install takes one command.

Get started free →