The Commands I Never Let an AI Agent Run (and How I Sandboxed OpenClaw)
Someone on X asked a simple question the other day:
"What's one command you never let an AI agent run without asking you first?"
My answer took about five seconds:
Anything that deletes files or force pushes. And anything that touches the production database 😅
Short answer. The setup behind it is my AI agent security checklist.
I run a one-person company. Day to day, agents help me handle code, build features, set up deployments to Cloudflare, and run security checks. That only works because the dangerous stuff never runs without me.
I used to run OpenClaw. I don't anymore. The commands below stayed. The OpenClaw section is the setup I used, and the config I'd start with if I were locking it down again.
Below: the commands I never let an agent run alone, why each one is on the list, and how I enforced them.
Link to this sectionWhy a Deny-List Matters More Than a Smart Model
Agents don't have taste. They follow instructions.
I wrote about this in The Hidden Reality of Running a Business with AI Agents. Instructions miss edge cases. Small deviations compound. Most of the time that means a blog post that feels a little off.
But when the agent has a shell, "a little off" can mean a deleted folder. Or a rewritten Git history. Or a production table that's gone.
The model being smart doesn't change that. A good model with a bad instruction, or a prompt injection hidden in a web page it just read, will still run the command.
So I don't rely on the model to be careful.
I rely on the setup to make careless impossible.
My rule: if a mistake can't be undone in five minutes, the agent doesn't get to make it alone.
Link to this sectionThe Commands I Never Let an Agent Run Alone
Link to this section1. Anything That Deletes Files
rm -rf, find ... -delete, cleaning up "old" folders, wiping a build directory that turns out to hold something important.
Deleting is the fastest way for a helpful agent to do damage. It's also the hardest to notice. Nothing errors. Things are just... gone.
Link to this section2. Force Pushes and History Rewrites
git push --force, git reset --hard on shared branches, rebasing something that's already pushed.
A force push doesn't just change your code. It changes everyone's version of the truth. If an agent "fixes" a messy branch by rewriting history, the work it overwrote may not exist anywhere else.
Agents reach for --force because it makes errors go away. That's exactly the problem.
Link to this section3. Anything That Touches the Production Database
Migrations. DROP. DELETE without a WHERE. "Quick fixes" to a row. Even reads, if the data is sensitive.
The production database is where my users' data lives. An agent doesn't know which table is safe to experiment on. It doesn't know a migration will lock a busy table. It doesn't know that "test user" is actually a paying customer.
Prod is the one place where I want zero creativity.
Link to this section4. Anything That Reads or Moves Secrets
.env files, API keys, SSH keys, the ~/.openclaw directory itself.
In my OpenClaw security guide I wrote that I treat ~/.openclaw like my SSH keys. Same idea here. An agent that can read secrets can leak them, through a log, a commit, or a request to some URL it was tricked into calling.
Link to this section5. Anything That Sends or Publishes
Emails to users. Posts. Deploys. Anything a real person will see.
This one comes straight from how I place human checkpoints: high risk gets reviewed before execution, low risk gets reviewed after. Sending and publishing are high risk because you can't un-send an email.
Link to this sectionWhen I Ran OpenClaw
A list in a prompt is a suggestion. The agent can forget it, misread it, or get talked out of it.
When I ran OpenClaw, I wanted those rules outside the model. I did not keep the exact sandbox mode, workspace access, or allowlist. If you run OpenClaw, start here. These are the values I'd set. They are not a paste of my old file.
Link to this sectionLayer 1: Run Agents in a Sandbox
OpenClaw can run agent sessions inside containers instead of on your machine. Three settings control it: mode, scope, and backend.
Sandboxing does nothing until you turn it on. mode defaults to "off".
mode: "off": no sandboxingmode: "non-main": sandbox every session except the agent's main sessionmode: "all": sandbox everything
The Docker backend's defaults are already tight: no network (network: "none"), a read-only root filesystem, all Linux capabilities dropped (capDrop: ["ALL"]), and no-new-privileges. The default image is openclaw-sandbox:trixie-slim.
OpenClaw's config file is openclaw.json. This is the shape I'd start with:
{
agents: {
defaults: {
sandbox: {
mode: "non-main", // or "all" if no session should touch the host
backend: "docker",
scope: "session", // each session gets its own container
workspaceAccess: "ro", // agent workspace read-only at /agent
docker: {
network: "none", // no egress
readOnlyRoot: true,
capDrop: ["ALL"],
tmpfs: ["/tmp", "/var/tmp", "/run"],
},
},
},
},
}Why this matters: with mode set to non-main or all, an agent tricked into rm -rf is deleting files inside a throwaway container. Not on the host.
One thing in the docs I did not expect: denying the file tools does not make an agent read-only. exec is still a shell.
"ro"mounts the agent workspace read-only at/agentand turns offwrite,edit, andapply_patch."none"does not mount the agent workspace at all. The default."rw"mounts it read-write at/workspace.
"ro" is not a frozen container. The tmpfs paths (/tmp, /var/tmp, /run) stay writable, so a shell can still write there. If the agent should not write anything, deny exec too.
Link to this sectionLayer 2: Allowlist Commands, Ask on Everything Else
This is the part that turns the "never alone" list into something the process enforces.
OpenClaw has exec approvals, controlled by tools.exec.mode:
| Mode | What It Does |
|---|---|
deny | Block host exec entirely |
allowlist | Run only allowlisted commands, no prompts |
ask | Run allowlisted commands, ask me for anything else |
auto | Run allowlist matches, send misses to a reviewer that can allow once, deny, or ask a human |
full | Run everything, no ordinary prompts |
Here's the trick: my deny-list is really an allowlist.
I don't try to list every dangerous command. That's a losing game, because there are a hundred ways to delete a file. Instead I allow the boring, safe commands and let everything else hit an approval prompt.
{
tools: {
exec: {
mode: "ask", // allowlist hits run, misses ask me
strictInlineEval: true, // python -c, node -e etc. always need approval
},
},
}If no approval UI is reachable, askFallback defaults to deny. A missed prompt does not run the command.
There's also a built-in preset that sets most of this in one go: openclaw exec-policy preset cautious (allowlist, ask on miss, deny as fallback).
Watch out for this one: allowlisting git allows all of git, including git push --force. OpenClaw lets you add an argPattern (a JavaScript regex on the arguments) to an allowlist entry, so you can allow git status and git diff while git push --force still hits the prompt:
{
"version": 1,
"agents": {
"main": {
"allowlist": [
{ "pattern": "rg" },
{ "pattern": "git", "argPattern": "^(status|diff|log|show)( .*)?$" }
]
}
}
}argPattern is checked against the arguments, not against the git token. Do not also add a path-only { "pattern": "git" }. A miss falls back to that entry, and git push --force would run.
This lives in the exec approvals policy. Set it with openclaw approvals, not by editing the file by hand. openclaw approvals get shows the effective policy. The git pattern above is an example of the shape. It is not an allowlist I kept.
Skip YOLO mode on anything that can reach real data. openclaw exec-policy preset yolo sets host exec to security full and ask off, and sets askFallback to full. That is the same end state as tools.exec.mode "full" plus host askFallback "full". Fine for a throwaway experiment. The opposite of this post.
Link to this sectionLayer 3: Least-Privilege Credentials
The sandbox protects the machine. Credentials decide what the agent can reach outside it.
Separate keys per agent or per project. Least privilege. No production keys on a machine an agent can read.
That is the rule I'd start with. It is not a claim about a specific key I issued.
Secrets live in files with tight permissions, as in the security guide: chmod 700 ~/.openclaw, and chmod 600 on openclaw.json and secret files.
Link to this sectionLayer 4: Production Lives Somewhere Else
The simplest way to stop an agent touching the production database is to make sure it can't see it.
- Agents work against a local or staging database, never prod.
- If it needs production data, give it a read-only user on a replica or a snapshot, not the primary.
- A migration that touches production waits for approval. The agent can draft it. A person runs it.
Link to this sectionLayer 5: Git Protections That Don't Trust Anyone
Even if an agent somehow runs git push --force, the remote should say no.
- Protect
mainwith branch protection or rulesets: block force pushes, block deletion, require a pull request. - Agents work on their own branches and open PRs. They don't push to
main. - CI runs on every PR, so broken changes get caught before I even look.
This is the layer that protects you from yourself too.
Link to this sectionLayer 6: Watch What They Do
Approvals and sandboxes stop the obvious stuff. Monitoring catches the weird stuff.
Monitor in production. Staging will not show you the weird cases. Agent behavior changes with real data. Track task success rates, cost drift, and quality over time.
For OpenClaw specifically:
openclaw logs --limit 100for a quick look at what ran.--followstreams the log.- Look for unexpected command executions, sessions from unknown sources, and API usage spikes
This is also a big part of why I built AgentCenter: when you have a team of agents running, you need one place to see what each one is doing, what it delivered, and where it got stuck.
Link to this sectionWhat I use now
I moved off OpenClaw. The agents that help me now are Claude Code, Claude cloud agents, and Grok Bot.
The rules came with me. They work on a branch and open a pull request. Nothing pushes to main. A deploy, including one to Cloudflare, waits for me. So does anything that touches production or a secret.
Claude Code can write that down in .claude/settings.json. This example is from the Claude Code settings docs. It is not my file. permissions.allow lets a command run without a prompt. permissions.deny blocks one. Deny is checked first, so an allow rule cannot override it. The file is strict JSON. A comment or a trailing comma is a syntax error.
{
"permissions": {
"allow": ["Bash(npm run *)", "Bash(git diff *)"],
"deny": ["Read(./.env)", "Read(./.env.*)"]
}
}A Read(./.env) deny blocks Claude Code's file tools on that path. It does not catch every shell command that reads a file without naming it. The docs say that. The rule helps. It is not a lock on the disk.
Grok Bot asks for approval before risky actions.
Claude's cloud agents get the same rule as the local ones. A branch, a pull request, and my approval before a deploy or anything on production.
Link to this sectionThe AI agent security checklist
Here's the whole thing in one place. The OpenClaw lines are where I'd start if I were setting it up again. The rest is what I still require: a branch, a pull request, and my approval before a deploy or anything that touches production or secrets.
Never without approval
- File deletion (
rm,find -delete, "cleanup" tasks) -
git push --force,git reset --hard, history rewrites - Anything that connects to the production database
- Reading, printing or moving secrets (
.env, keys,~/.openclaw) - Sending emails, publishing, deploying
Sandbox
-
agents.defaults.sandbox.modeset tonon-mainorall(the default isoff) - Docker backend left on its defaults:
network: "none",readOnlyRoot: true,capDrop: ["ALL"] -
workspaceAccess: "ro"or"none"when the agent should not write the workspace ("rw"is the writable value) -
execdenied when the agent should not write at all ("ro"still leaves tmpfs writable)
Exec approvals
-
tools.exec.mode: "ask"(oropenclaw exec-policy preset cautious) - Allowlist only safe, boring commands
-
argPatternongitso pushes and resets still prompt -
strictInlineEval: true -
askFallbackleft asdeny - No YOLO mode on anything that can reach real data
Credentials and prod
- No production keys on a machine an agent can read
- Separate keys per agent or project, least privilege
-
~/.openclawat700,openclaw.jsonand secret files at600 - Agents use local or staging data; prod reads only through a read-only user
- Migrations reviewed and run by a human
Git
- Force pushes and branch deletion blocked on
main - Agents work on branches and open PRs
- CI on every PR
Monitoring
- Logs checked regularly (
openclaw logs --limit 100) - Cost and success rate tracked over time
Link to this sectionFinal thought
Agents are great at doing work. They're terrible at knowing which work is irreversible.
That's my job.
The setup above isn't about distrusting AI. It's the same thing I'd do for a new hire: give them a safe place to work, the access they need and nothing more, and a second pair of eyes on anything that can't be undone.
Delegate and supervise. Not set and forget.
If you're running OpenClaw on a server, start with the security guide and then come back to this checklist. And if you're curious how this fits into running a whole business with agents, read Building a One-Person Company with AI Agents.
What's on your "never without me" list? Tell me on X. I'm always collecting new ones.
I write about building real products with AI agents: setups, costs, and what breaks. One email when there's a new post, no fluff.