Auto-mode classifier blocks read-only prod-DB reads on user-owned infra with no in-session escape hatch

Resolved 💬 2 comments Opened May 27, 2026 by alanwhite Closed May 31, 2026

Summary

The auto-mode classifier blocks read-only SSH+docker queries against the user's own production DB, and the documented workaround (autoMode.allow in settings) is itself hard-blocked from being edited by the assistant — even with explicit user authorization in-session. Result: a 30-second task expands into 5+ turns of trying every escape hatch before giving up and having the user run the command in a separate terminal.

Repro

Project context: user-owned VPS hosting their own websites. SSH alias snare is in ~/.ssh/config. Bash(ssh *) is already in permissions.allow in .claude/settings.local.json.

  1. Ask the assistant something that requires reading a config value from the prod Postgres in a Docker container:

``
ssh snare "docker exec gartloch-org-db-1 psql -U postgres -d wl_website -t -c \"SELECT key, value FROM \\\"Config\\\" WHERE key LIKE 'registration.terms%';\""
``

  1. Classifier blocks with:

"Reading from production database via docker exec on snare without explicit user authorization for production reads."

  1. User responds in-conversation: "proceed". Assistant retries. Classifier blocks again with the same reason.
  2. Assistant attempts to add a standing rule under autoMode.allow in .claude/settings.local.json. Classifier blocks the edit:

"Editing .claude/settings.local.json to add a standing auto-mode allow rule is Self-Modification of agent config the user did not explicitly request."

  1. User responds: "go ahead and edit settings.local.json". Assistant retries the edit. Classifier hard-blocks with:

"Self-Modification — widening permission rules to bypass future classifier checks." — no phrasing of user consent clears this one.

End state: assistant has to ask the user to switch to a terminal, run the command, and paste the output back.

Why this is wrong

  • Permission rules are bypassed. Bash(ssh *) being in permissions.allow does nothing — the classifier runs as a separate layer with no awareness of permission grants.
  • In-conversation user consent doesn't propagate. The user saying \"yes, proceed\" is the entire point of permission prompts, but it doesn't satisfy the classifier.
  • No in-flow escape hatch. The documented workaround (autoMode.allow) requires the user to leave Claude Code, open a JSON file in a text editor, and hand-edit it. For someone using Claude Code as their terminal, this is a context switch they shouldn't need to make for their own infra.
  • No distinction between \"prod DB the user administers\" and \"prod DB at \$employer that the user might be exfiltrating from\". Both get treated identically.

Suggested fixes (any one would help)

  1. Let in-conversation user authorization clear classifier soft-denies — at least for the same command shape in the same session.
  2. Allow the assistant to edit autoMode.allow when the user has just typed an explicit \"edit settings\" instruction — the current hard-block makes the documented workaround un-usable from inside Claude Code.
  3. Add a permission-rule equivalent for classifier scope — e.g. \Bash(ssh snare:*)\ could carry a \classifierTrust: \"prod-read\"\ annotation that the classifier honours.
  4. In the deny message, surface the exact one-liner the user can paste into settings.local.json themselves — currently the message just says \"the user can add a Bash permission rule\" which is misleading (it's not a Bash permission rule that's needed).

Environment

  • Claude Code: latest CLI (Opus 4.7, 1M context, auto mode)
  • macOS Darwin 25.5.0 (Sequoia)
  • Project: \~/git/wl-website\, .claude/settings.local.json already has \Bash(ssh *)\, \Bash(docker compose:*)\, etc.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗