{"slug": "i-let-claude-code-run-dangerously-skip-permissions-on-my-production-db-here-s-i", "title": "I let Claude Code run --dangerously-skip-permissions on my production DB. Here's what I changed.", "summary": "A developer at Riversea Lab accidentally ran Claude Code with --dangerously-skip-permissions on a production database after misconfiguring an environment file. The multi-agent loop hit 12K KV writes per minute due to a counter bug, but no data loss occurred. The developer implemented a three-layer defense: a permissions allowlist in settings.json, a separate git worktree for staging credentials, and a CLAUDE.md instructing Claude to ask before touching production.", "body_md": "Last Tuesday at 3am, a multi-agent loop hit 12K KV writes/minute and froze. The loop was a one-line counter bug. That part was fixable. What I found while tracing it was worse.\n\nI had `--dangerously-skip-permissions`\n\nenabled on a Claude Code session that was running D1 migrations. I thought it was pointing at staging. It wasn't — I'd misconfigured my env file reference, loading `.env.production`\n\ninstead of `.dev.vars`\n\n. Claude didn't ask. The flag told it not to. The migration was `ADD COLUMN`\n\n, not `DROP COLUMN`\n\n, so no data loss. Survivable. But only barely.\n\nThe thing I got wrong: I treated `--dangerously-skip-permissions`\n\nas \"skip the annoying confirmation popups.\" It's actually \"remove the only moment a human sees what command is about to run.\" Those are very different things. Turning the flag back off helps, but it doesn't constrain *what Claude attempts* — it just adds a prompt you'll click through anyway at 3am.\n\nWhat actually worked was adding a deny rule in `.claude/settings.json`\n\n:\n\n```\n{\n  \"permissions\": {\n    \"allow\": [\"Bash(wrangler d1 execute * --local*)\"],\n    \"deny\": [\"Bash(wrangler d1 execute *)\"]  \n  }\n}\n```\n\nThe allow rule is more specific than the deny, so `--local`\n\ncalls go through and everything else is blocked before execution. Over 2 weeks post-fix, Claude attempted zero production DB commands. Three deny events were logged — all from ambiguous prompts I wrote during fast context-switches, not from Claude going rogue.\n\nI ended up running three layers: the `settings.json`\n\nallowlist, a separate git worktree for migration work that physically contains only staging credentials, and a `CLAUDE.md`\n\nthat instructs Claude to ask before anything touching production. The CLAUDE.md approach has a real caveat though — in long sessions the instructions lose weight as context grows. Anything critical needs to be restated in the prompt itself.\n\nI wrote up the full breakdown — including the worktree setup, the exact `CLAUDE.md`\n\nwording, and why MCP tool permissions behave inconsistently with the deny rules — over on riversealab.com.", "url": "https://wpnews.pro/news/i-let-claude-code-run-dangerously-skip-permissions-on-my-production-db-here-s-i", "canonical_source": "https://dev.to/riversea/i-let-claude-code-run-dangerously-skip-permissions-on-my-production-db-heres-what-i-changed-4p8", "published_at": "2026-06-19 06:22:36+00:00", "updated_at": "2026-06-19 07:00:35.189067+00:00", "lang": "en", "topics": ["ai-agents", "ai-safety", "developer-tools", "large-language-models"], "entities": ["Claude Code", "Riversea Lab", "D1"], "alternates": {"html": "https://wpnews.pro/news/i-let-claude-code-run-dangerously-skip-permissions-on-my-production-db-here-s-i", "markdown": "https://wpnews.pro/news/i-let-claude-code-run-dangerously-skip-permissions-on-my-production-db-here-s-i.md", "text": "https://wpnews.pro/news/i-let-claude-code-run-dangerously-skip-permissions-on-my-production-db-here-s-i.txt", "jsonld": "https://wpnews.pro/news/i-let-claude-code-run-dangerously-skip-permissions-on-my-production-db-here-s-i.jsonld"}}