[BUG] Hardcoded Bash safety checks (expansion obfuscation, compound-command guardrails) fire on legitimate research workflows with limited granular bypass

Resolved 💬 3 comments Opened Apr 15, 2026 by Todd-ChromedomeConsulting Closed Apr 19, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Claude Code contains several hardcoded Bash safety checks that fire on common research-workflow patterns. The checks cannot be scoped to trusted directories or disabled on a per-pattern basis. The only available bypass paths are bypassPermissions mode (which disables the entire deny list as a side effect, making it unsafe for routine use) or a PreToolUse hook returning an allow decision in the correct wrapped format (which I spent months not knowing about due to a separate parser bug — see related issue).

Verified hardcoded checks present in the installed cli.js binary:

Expansion obfuscation classifier at cli.js line 1870, function C68. The regex /\{[^}]*['"]/ fires on any Bash command containing a brace followed by a quote character. This matches Python f-strings (python3 -c "print(f'{var}')"), heredocs with variable interpolation, jq queries with quoted strings inside braces, and many other legitimate patterns. There is no allowlist, no file-path exemption, and no config switch to disable the classifier while leaving the rest of the Bash parser intact.

Compound-command guardrails — three separate variants verified present in cli.js by text search:

"Compound command contains cd with write operation - manual approval required to prevent path resolution bypass"
"Compound command contains cd with output redirection - manual approval required to prevent path resolution bypass"
"Compound command contains cd with path operation — manual approval required to prevent path resolution bypass"
All three fire on the pattern cd <path> && <command>, even when the target directory is a trusted root and every component command is explicitly in the permissions.allow list.

Research-heavy workflows routinely generate commands of the form cd /tmp/research && python3 sweep.py > results.json 2>&1 && wc -l results.json. Every command of this shape triggers a mandatory approval prompt regardless of how permissions are configured. In a multi-hour unattended research session this converts productive wall-clock time into approval-click time on patterns that allow-list rules should cover.

What Should Happen?

At minimum one of the following:

The permissions.allow list should be able to carve out specific patterns (e.g., python3 ) as trusted overrides to the hardcoded checks. Currently, a permissions.allow entry for python3 does not prevent the approval prompt from firing on cd /tmp && python3 script.py because the compound-command check fires before the allow list is consulted.

Trusted root directories should be exempt from the compound-command path-resolution-bypass check. If /tmp or a user-specified research directory is in a trusted roots list, cd /tmp/x && python3 y.py should not require approval.

A per-directory trust marker or a config option to disable the expansion obfuscation classifier while leaving the rest of the Bash parser intact. The current dichotomy (full bypassPermissions, which disables the deny list entirely, or no bypass at all) gives users no safe middle ground for routine research work.

Note that Claude Code has recently added permissions.defaultMode: "dontAsk" and a permissions.ask list, which are real improvements to the bypass mechanisms. Neither addresses the specific issue of hardcoded Bash checks firing ahead of the permission allow list. Both would benefit from a companion feature that lets trusted patterns override the hardcoded checks.

Error Messages/Logs

The approval prompts themselves are the observable output:

Compound command contains cd with output redirection - manual approval required to prevent path resolution bypass
(Two other compound-command variants exist in cli.js — see "What's Wrong?" above.)

The expansion obfuscation check displays:

Contains brace with quote character (expansion obfuscation)

Steps to Reproduce

Reproduction 1 — expansion obfuscation:

Add "Bash(python3 *)" to permissions.allow in settings.json.
Run any Bash command containing a Python f-string: python3 -c "print(f'{1+1}')"
Observe: the approval prompt fires with the expansion obfuscation message, despite the allow rule.
Reproduction 2 — compound command with cd:

Add "Bash(python3 *)" to permissions.allow in settings.json.
Run a compound command: cd /tmp && python3 -c "print(42)" > out.txt
Observe: the approval prompt fires with the "path resolution bypass" message, despite the allow rule covering the python3 call.
Both reproductions show that the hardcoded safety checks fire ahead of the permissions allow list, making the allow rules functionally incomplete for any workflow that generates these common Bash patterns.

Claude Model

None

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.109

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

Architecture: arm64 (Apple Silicon) Node.js: v25.6.1 Install path: /opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/cli.js Shell: zsh

Context:

This bug compounds with a separate bug I am filing in parallel regarding PreToolUse hook output format being silently discarded by the cli.js parser at line 8045. The two bugs interact: a working PreToolUse gatekeeper hook would short-circuit the Bash permission check (including the hardcoded classifiers described here) before they fire, making this bug a frustration rather than a blocker. Because the gatekeeper hook was silently disabled for months due to the format parser bug, I experienced the maximum possible friction from the hardcoded checks — approval prompts on every research operation that included an f-string or a cd-plus-command pattern, with no way to eliminate them short of disabling the entire permission system.

The practical impact in a research-heavy workflow: sessions that should run in 30 minutes stretch to several hours of wall-clock time because the approval prompts halt unattended work every few minutes. Agents generating the commands routinely use cd <path> && <command> because that is the more natural shell idiom, and the approval friction persists even when the user has written permission policies specifically allowing the individual components.

View original on GitHub ↗

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