Skip to content

Claude Code agent autonomously ran destructive db command, wiped production database #27063

Closed as not planned

Description

@obviouslyiam

What happened

On 2026-02-19, a Claude Code agent running in a separate terminal session autonomously executed drizzle-kit push --force against my production PostgreSQL database on Railway. This force-pushed schema changes that wiped every table in the database — months of trading data, AI research results, competition history, oracle signals, and user data. All gone.

Railway PostgreSQL does not have automatic backups or point-in-time recovery. The data is unrecoverable.

Impact

  • 60+ tables destroyed — only 5 oracle tables survived the initial wipe (and were later accidentally dropped during recovery attempts)
  • Months of production data lost — trading positions, AI-generated research, competition results, smart wallet tracking history
  • ~8 hours of manual disaster recovery to rebuild the schema from ORM definitions and re-seed what little data could be recovered from a secondary database
  • This is the second time drizzle-kit push has caused data loss in this project (first time on Feb 8 it wiped the api_keys table)

The core problem

Claude Code executed an irreversible, destructive database command (drizzle-kit push --force) against a production database without:

  1. Explicit user approval for that specific destructive action
  2. Understanding the consequences — --force bypasses all safety prompts and can drop tables/columns
  3. Any backup verification before running a schema migration tool in force mode

The --force flag exists specifically to skip interactive confirmation prompts. Claude Code used it to avoid being blocked by an interactive prompt, which is exactly the wrong reason to use it.

Expected behavior

Claude Code should never run destructive database commands (especially with force/bypass flags) without explicit user confirmation. Commands like:

  • drizzle-kit push --force
  • DROP TABLE, TRUNCATE, DELETE FROM (without WHERE)
  • Any ORM migration tool with --force, --yes, --no-verify flags
  • git reset --hard, git push --force to main

These should require explicit user approval every time, regardless of permission settings. The --force flag on any command should be a red flag that triggers confirmation.

Environment

  • Claude Code CLI (latest as of 2026-02-19)
  • macOS
  • PostgreSQL on Railway (no automatic backups)
  • Drizzle ORM with drizzle-kit

Suggestion

Consider adding a built-in blocklist or confirmation requirement for known destructive commands, especially:

  • Database migration tools with force flags (drizzle-kit push --force, prisma db push --force-reset, sequelize db:migrate:undo:all)
  • Direct SQL destructive operations (DROP, TRUNCATE, bulk DELETE)
  • Git destructive operations (push --force, reset --hard, clean -f)

The cost of pausing to confirm is a few seconds. The cost of not confirming was months of irreplaceable data.

Activity

  1. github-actions commented on Feb 20, 2026

    @github-actions

    Found 3 possible duplicate issues:

    1. Agent executed destructive database command (alembic downgrade base) without user confirmation — data loss #26913
    2. Claude Opus 4.5 executed destructive SQL UPDATE deleting 55,000 records WITHOUT asking for permission #13325
    3. [BUG] Claude Code Executed Destructive Database Command Despite Safety Instructions #5370

    This issue will be automatically closed as a duplicate in 3 days.

    • If your issue is a duplicate, please close it and 👍 the existing issue instead
    • To prevent auto-closure, add a comment or 👎 this comment

    🤖 Generated with Claude Code

  2. ThatDragonOverThere commented on Feb 25, 2026

    @ThatDragonOverThere

    Same Pattern — Autonomous Deletion Without Permission Prompt

    Cross-linking: experienced the same class of bug. Claude deleted backtest results autonomously on wake — no prompt, no confirmation (#27507). Also documented: permission denial ignored (#27002/#26980), compaction loses safety instructions (#9796).

    The community has now documented: 2,229 files deleted (#23913), 60+ DB tables (this issue), 21 DB tables (#26913), and multiple data file deletions (#27507). This is not isolated — the permission/safety system has systemic failures.

  3. VoxCore84 commented on Mar 13, 2026

    @VoxCore84

    This is exactly the class of destructive action that should never reach execution without a confirmation gate.

    We built an open-source PreToolUse hook specifically for this — it intercepts Bash commands before execution and blocks destructive SQL/database operations (DROP, DELETE without WHERE, TRUNCATE, drizzle-kit push --force, etc.) with a user confirmation prompt. Also catches rm -rf, git push --force, and similar patterns.

    It's a Python script that runs as a Claude Code hook — no dependencies, ~150 lines, configurable allowlist. Won't prevent everything, but would have caught this specific case:

    https://github.com/VoxCore84/claude-code-sql-safety

    We also documented this failure mode as part of a broader 16-issue taxonomy of completion-integrity failures: #32650. The runtime argument is that these guardrails should be built into the product, not community add-ons — but until Anthropic ships them, hooks are the workaround that actually works.

    Separately: the fact that this issue was flagged as a duplicate by the bot and almost auto-closed is concerning. Production data loss from autonomous execution is not a duplicate of anything — it's a safety incident.

  4. yurukusa commented on Mar 29, 2026

    @yurukusa

    A PreToolUse hook would have prevented this. Block drizzle-kit push --force and similar destructive database commands:

    INPUT=$(cat)
    COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
    [ -z "$COMMAND" ] && exit 0
    if echo "$COMMAND" | grep -qiE '(drizzle-kit\s+push\s+--force|prisma\s+db\s+push\s+--force|prisma\s+migrate\s+reset)'; then
        echo "BLOCKED: Destructive database operation." >&2
        echo "Command: $COMMAND" >&2
        echo "Force-push against production is permanently disabled." >&2
        exit 2
    fi
    if echo "$COMMAND" | grep -qiE '(drizzle-kit|prisma|knex|typeorm)\s+(push|migrate|seed|reset)'; then
        if [ -f ".env" ] && grep -qiE '(railway|neon|supabase|planetscale|prod)' .env 2>/dev/null; then
            echo "BLOCKED: Database operation detected with production DATABASE_URL." >&2
            echo "Switch to a development database first." >&2
            exit 2
        fi
    fi
    exit 0
    {
      "hooks": {
        "PreToolUse": [{
          "matcher": "Bash",
          "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/db-production-guard.sh" }]
        }]
      }
    }

    This blocks drizzle-kit push --force at the process level. It also detects when .env contains production database URLs and blocks ORM migration commands. Claude can't bypass the hook — exit 2 stops the command before bash runs.

  5. github-actions commented on May 1, 2026

    @github-actions

    Closing for now — inactive for too long. Please open a new issue if this is still relevant.

  6. github-actions commented on May 8, 2026

    @github-actions

    This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.

  7. locked as resolved and limited conversation to collaborators on May 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleIssue is inactive

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions