claude-code - 💡(How to fix) Fix [BUG] Hardcoded Bash safety checks (expansion obfuscation, compound-command guardrails) fire on legitimate research workflows with limited granular bypass [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#48762Fetched 2026-04-16 06:51:40
View on GitHub
Comments
1
Participants
2
Timeline
6
Reactions
0
Timeline (top)
labeled ×5commented ×1

Error Message

Error Messages/Logs

Root Cause

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.

Code Example

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)
RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • 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.

extent analysis

TL;DR

The most likely fix involves modifying the Claude Code to allow trusted patterns to override hardcoded Bash safety checks or exempting trusted root directories from compound-command path-resolution-bypass checks.

Guidance

  • Identify and modify the specific lines in cli.js (e.g., line 1870 for the expansion obfuscation classifier) to add conditional checks for trusted patterns or directories before firing the safety checks.
  • Consider introducing a new configuration option to disable specific hardcoded checks or add a trust marker for directories, allowing users to customize the safety features based on their workflow needs.
  • Review the permissions.allow list implementation to ensure it can effectively override the hardcoded checks for specified patterns, such as python3 *.
  • Investigate the interaction between the hardcoded checks and the PreToolUse hook to ensure that a working hook can short-circuit the Bash permission checks as intended.

Example

// Example of how the expansion obfuscation check might be modified
function C68(command) {
  // Check if the command matches a trusted pattern before applying the regex check
  if (isTrustedPattern(command)) {
    return false; // Do not fire the safety check
  }
  // Original regex check
  if (/\{[^}]*['"]/g.test(command)) {
    // Fire the expansion obfuscation check
  }
}

Notes

The provided solution is speculative and based on the information given in the issue. Actual implementation details may vary depending on the internal workings of Claude Code and its configuration options. It's also important to consider the security implications of modifying or disabling safety checks.

Recommendation

Apply a workaround by modifying the cli.js file to add conditional checks for trusted patterns or directories, as this seems to be the most direct approach to addressing the issue given the current version of Claude Code (2.1.109). This recommendation is based on the assumption that upgrading to a potentially fixed version is not currently an option, and the modifications can be made safely without introducing significant security risks.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix [BUG] Hardcoded Bash safety checks (expansion obfuscation, compound-command guardrails) fire on legitimate research workflows with limited granular bypass [1 comments, 2 participants]