ai · tutorial · agents
Your Agent Passed Every Safety Check. Then It Deleted the Database File
SQL firewalls can't stop rm: SQLite is a file, and files die at the OS layer. The 5-command Linux cage (separate user + staging copy) that makes prod deletion kernel-impossible. Inside.

Your cage has no floor
Picture the standard agent-safety stack in 2026: read-only database handles, a regex firewall blocking DROP and unbounded DELETE, a migration gate demanding human approval. Genuinely good work. Then the agent runs rm db/app.db — or overwrites it with garbage, or "tidies" the directory — and every layer watches helplessly. Nothing was disobeyed. The guards were never consulted. Deleting a file is an operating-system operation, and SQLite is only a file.
This is the exact shape of the PocketOS disaster: obedience treated as a control. An agent that ignores instructions ignores all of them equally — SQL rules included. Anything enforced by telling is bypassable by doing something you weren't told about.
BoringPush is the $199-once Next.js kit where this lesson is load-bearing. The SQL cage (read-only handles, firewall, human-gated migrations, off-site backups) already ships in the template. The filesystem cage below closes the hole SQL guards structurally cannot: the file itself.
Two cages, two enforcers
| Threat | SQL-layer guards | Filesystem cage |
|---|---|---|
DROP TABLE users |
Blocked (firewall + scanner) | N/A |
DELETE FROM orders (no WHERE) |
Blocked | N/A |
rm db/app.db |
Never consulted | Permission denied (kernel) |
| Overwrite db with garbage | Never consulted | Permission denied (kernel) |
| Delete the staging copy | N/A | Allowed — rebuilt hourly, prod untouched |
| Argue with the enforcer | Possible (prompt tricks) | Impossible (kernel checks UID on every syscall) |
The last row is the whole essay. Application guards constrain what the app allows. OS permissions constrain what the machine allows. Only one of them survives a disobedient agent.
Five commands, one standing user
The design fits in a paragraph: the agent runs as its own Linux user (agent, no sudo, key only). Prod's db directory is owned by the app user at mode 750 — the agent cannot list it, let alone delete from it. The agent works on a staging copy in its own directory, refreshed hourly by an atomic sqlite3 .backup cron job the agent never touches. Agent sessions are pointed at the copy, and the kit's read-only database handle for agents respects the same setting, so both layers agree on which file the agent sees.
Worst case, spelled out: the agent deletes the staging copy. The next hourly refresh rebuilds it. Production never flinches. That is the entire SQLite-destruction threat model, closed, on a $5 VPS with stock Linux — no containers, no special tooling, the same UID trick Android uses to sandbox Termux.
If you can think it, BoringPush can make it — and what buyers think after reading disaster postmortems is "make it so the agent physically cannot." The kit ships both cages: a read-only database handle for agents, and a filesystem setup guide in the docs that works on any VPS.
Verify it (don't trust it)
Cages get tested, not believed:
sudo -u agent ls /var/www/myapp/db # → Permission denied ✅
sudo -u agent rm /var/www/myapp/db/app.db # → Permission denied ✅
sudo -u agent touch /srv/agent-staging/db/probe # → works ✅FAQ
Doesn't the read-only SQLite flag already do this?
No — readonly: true governs SQL writes through that handle. It says nothing about rm, overwrite, or directory operations. Different layer, different enforcer.
Why not Docker instead of OS users?
Containers are a fine cage too, but they add image builds, volume mapping, and a daemon to babysit — overhead a solo founder feels weekly. UID + mode bits are free, auditable in five commands, and survive reboots without orchestration.
What about Supabase and MongoDB?
They're servers, not files — no rm equivalent exists. Their twin of this cage is credential separation: service keys absent from the agent's environment, least-privilege roles (app_agent/appAgent) only. Same principle, different layer.
One user per agent or per session?
Per agent (a standing agent user) is enough — sessions are time, users are identity. Go ephemeral per-session only for untrusted third-party agents.
I deleted my staging copy. Now what?
Wait up to an hour, or re-run the .backup command yourself. That's the point: the copy is disposable by design. If losing it scared you, imagine it had been prod.
+ all the boring stuff (analytics, auth, SQLite ↔ Supabase, full marketplace, webhooks)
Command from your phone.
Built so autonomous AI agents build what you want without breaking what's already paying you.
- Built-in analytics — cookie-free mode, $0 forever, no PostHog bill
- SQLite ↔ Supabase: one setting, same field names
- Full digital marketplace & feedback boards included
- 3 payment rails: Stripe, LemonSqueezy & Dodo Payments
- Agent fences: lint gate, read-only data access, auto-rollback
- Ship from your phone via SSH & WireGuard/Tailscale in under a minute
$199
Get BoringPushOne-time payment · Lifetime updates · Unlimited projects.
Keep reading


