Skip to content

CLAUDE_CODE_SUBPROCESS_ENV_SCRUB should not override permission mode #51258

Closed as not planned

Description

@renatodinizc

Summary

When CLAUDE_CODE_SUBPROCESS_ENV_SCRUB is set, Claude Code forces the permission mode back to default, even when --dangerously-skip-permissions is explicitly passed. This couples two orthogonal concerns.

Observed behavior

$ claude --dangerously-skip-permissions
⚠ Permission mode forced to default — CLAUDE_CODE_SUBPROCESS_ENV_SCRUB is set (allowed_non_write_users hardening). Declare allowedTools explicitly, or set CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=0 to opt out.

Expected behavior

CLAUDE_CODE_SUBPROCESS_ENV_SCRUB should only control whether sensitive environment variables are scrubbed before being passed to subprocesses. It should not override the user's explicit permission mode selection.

These protect against different threat vectors:

  • Env scrubbing: prevents secrets (API keys, tokens) from leaking to subprocesses
  • Permission mode: controls whether tools require user approval before execution

Coupling them means users who want env scrubbing (reasonable security hygiene) are forced to also lose control over their permission model, with no way to opt into one without the other.

Suggested fix

Decouple the two behaviors:

  • CLAUDE_CODE_SUBPROCESS_ENV_SCRUB controls env var sanitization only
  • --dangerously-skip-permissions (or allowedTools) controls the permission model independently

Activity

  1. github-actions commented on May 27, 2026

    @github-actions

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

  2. gitayam commented on Jun 7, 2026

    @gitayam

    🔄 Requesting reopen. This closed for inactivity 2026-05-27, but the bug
    reproduces on the current release (2.1.153) and has expanded scope: the same
    override now affects --permission-mode bypassPermissions as well as
    --dangerously-skip-permissions. Sharing controlled data so the next triage
    pass has something concrete to act on.

    Setup

    • claude-code 2.1.153 / macOS 26.4.1 arm64 / node 26.0.0
    • ~/.claude/settings.json env block contains only CLAUDE_CODE_SUBPROCESS_ENV_SCRUB: "true" (no other env confounds)
    • Reproducer runs from a plain shell, no outer claude parent
    • Both built-in tools (Write, Bash, Edit) tested
    • N=10 per (config × tool) cell = 30 invocations per config; trivial binary-scorable tasks

    Scrub ON — 4 flag configs × 3 tools × N=10 = 120 invocations

    Config Flags on child claude -p SUCCESS Scrub warning
    A --dangerously-skip-permissions 0/30 30/30
    B --dangerously-skip-permissions + --allowedTools Write Bash Edit 30/30 30/30
    C --permission-mode bypassPermissions 0/30 30/30
    D --permission-mode bypassPermissions + --allowedTools Write Bash Edit 30/30 30/30

    The original issue covered config A. Config C is new evidence: bypassPermissions is force-overridden the same way --dangerously-skip-permissions is. Config D's success is attributable entirely to --allowedTools (matches B exactly).

    Scrub OFF — control (after removing the env var from settings.json)

    Config Flags SUCCESS Scrub warning
    E --permission-mode bypassPermissions 30/30 0/30

    So bypassPermissions itself is healthy — it's the scrub interaction that's the bug.

    Confirming the bug is in the env var, not in any specific setting-source

    Tested via inline --settings '{"env":{"CLAUDE_CODE_SUBPROCESS_ENV_SCRUB":"true"}}' (no settings.json edit): --permission-mode bypassPermissions alone, N=5, 0/5 SUCCESS, 5/5 scrub warnings. The override fires the same whether the env var is in settings.json or passed inline.

    Silent-failure mode worth noting

    In failing configs the child claude doesn't return an error. It emits the scrub warning to stderr and prints DONE without invoking the tool at all. The orchestrator sees exit 0, no error — but the work didn't happen. This is what makes the bug expensive in automation contexts: it looks like everything worked.

    Related: #60985 confirmation on 2.1.153 — partial, with nuance

    The companion issue #60985 (closed 2026-05-24 as dup of this one) reported two specific failures on 2.1.145. Retested on 2.1.153, N=10 each, distinguishing two outcome dimensions the original conflated:

    Config Tool succeeded Warning fired
    G0: baseline — auto mode, scrub unset (via env -u) 10/10 0/10
    G1: auto + scrub ON, no allowedTools 0/10 10/10
    G2: auto + scrub ON + --allowed-tools "Bash Edit Read Write Grep Glob" (#60985's exact failing form) 10/10 10/10
    G3: auto + scrub ON + --allowedTools Write --allowedTools Bash --allowedTools Edit (camel, repeated) 10/10 10/10
    G4: shell-env CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=0 + inline --settings scrub-on 0/10 10/10
    G5: inline --settings '{"env":{"CLAUDE_CODE_SUBPROCESS_ENV_SCRUB":"0"}}' 10/10 0/10

    Two interpretations:

    The G4 result confirms #60985's secondary claim about shell-env precedence is still a real problem — meaningful because the warning text reads "set CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=0 to opt out," which most readers will try first.

    (Worth noting: G0 requires env -u CLAUDE_CODE_SUBPROCESS_ENV_SCRUB even after removing the var from settings.json — any claude session started while it was set will propagate the inherited env to children, so the var has to be unset in shell as well. Found this while wiring the control.)

    The unresolved core complaint remains:

    CLAUDE_CODE_SUBPROCESS_ENV_SCRUB should only control whether sensitive environment variables are scrubbed before being passed to subprocesses. It should not override the user's explicit permission mode selection.

    Still true on 2.1.153. Both --dangerously-skip-permissions and --permission-mode bypassPermissions are silently overridden when this env var is set, with no opt-out documented in the warning text other than enumerating --allowedTools.

    Repro

    Two paired scripts; each checks its precondition and refuses to run if wrong:

    • repro-60776.sh — requires SUBPROCESS_ENV_SCRUB set → demonstrates configs A-D
    • repro-60776-control.sh — requires SUBPROCESS_ENV_SCRUB unset → demonstrates config E

    Both run from plain bash, use only built-in tools (no MCP), capture environment manifests, and override N via env (N=20 bash repro-60776.sh). Happy to share via gist if useful — they're ~150 lines each.

    Suggested triage outcomes (in order of how disruptive each is to existing users):

    1. Document --allowedTools enumeration as the supported workaround in the warning text and in the env-scrub docs. Low effort, immediately useful.
    2. Update the warning text to remove the misleading "set CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=0 to opt out" suggestion (shell env doesn't override settings.json — also documented at Misleading warning: '--allowed-tools' CLI flag and shell env do not satisfy CLAUDE_CODE_SUBPROCESS_ENV_SCRUB auto-mode gate #60985).
    3. Decouple env-scrubbing from permission-mode hardening — the original ask of this issue. Right now operators who want subprocess env scrubbing for credential hygiene are forced to also lose --dangerously-skip-permissions and --permission-mode bypassPermissions, with no opt-in to one without the other.
  3. stephenfeather commented on Jun 30, 2026

    @stephenfeather

    Still exists as of version 2.1.196

  4. github-actions commented on Sep 1, 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.

  5. locked as resolved and limited conversation to collaborators on Sep 1, 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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions