claude-code - 💡(How to fix) Fix [BUG] Sandbox deny rules with mid-path globs cause E2BIG on Linux — per-file bwrap expansion instead of per-directory overlay [2 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#46461Fetched 2026-04-11 06:19:41
View on GitHub
Comments
2
Participants
2
Timeline
6
Reactions
0
Author
Timeline (top)
labeled ×4commented ×2

On Linux, when permissions.deny contains Read(...) rules with mid-path glob wildcards (e.g., Read(foo/*/data/cache/**)), the sandbox appears to expand the glob against the actual filesystem and generate a separate bubblewrap bind-mount argument for every matching file. In a project with thousands of generated/cached files under the matched path, the resulting bwrap argument list exceeds Linux's ARG_MAX, and posix_spawn fails with E2BIG.

This does not occur on macOS.

Error Message

2026-04-10T23:35:41.677Z [DEBUG] Shell exec error: E2BIG: argument list too long, posix_spawn '/usr/bin/zsh' 2026-04-10T23:35:41.679Z [DEBUG] Bash tool error (131ms): Shell command failed

Root Cause

On Linux, when permissions.deny contains Read(...) rules with mid-path glob wildcards (e.g., Read(foo/*/data/cache/**)), the sandbox appears to expand the glob against the actual filesystem and generate a separate bubblewrap bind-mount argument for every matching file. In a project with thousands of generated/cached files under the matched path, the resulting bwrap argument list exceeds Linux's ARG_MAX, and posix_spawn fails with E2BIG.

This does not occur on macOS.

Fix Action

Workaround

Replace mid-path wildcards with explicit directory names:

"Read(foo/bar/data/cache/**)",
"Read(foo/baz/data/cache/**)"

Code Example

! cat .claude/settings.json
  ⎿  {
       "permissions": {
         "deny": [
             "Read(foo/*/bar/cache/**)"
         ]
     }}

❯ use Bash to echo "hello world"

Bash(echo "hello world")
  ⎿  Interrupted · What should Claude do instead?

The command was interrupted. What would you like me to do instead?

---

2026-04-10T23:35:41.677Z [DEBUG] Shell exec error: E2BIG: argument list too long, posix_spawn '/usr/bin/zsh'
2026-04-10T23:35:41.679Z [DEBUG] Bash tool error (131ms): Shell command failed

---

{ "permissions": { "deny": ["Read(foo/*/data/cache/**)"] } }

---

Shell snapshot created successfully (118918 bytes)
Spawning shell without login (-l flag skipped)
Shell exec error: E2BIG: argument list too long, posix_spawn '/usr/bin/zsh'
Bash tool error (509ms): Shell command failed

---

"Read(foo/*/data/cache/**)"

---

"Read(foo/bar/data/cache/**)",
"Read(foo/baz/data/cache/**)"

---

Documented above
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?

Title: `

High level summary from a human

With sandbox.enabled: true, consider this simple Claude Code session:

! cat .claude/settings.json
  ⎿  {
       "permissions": {
         "deny": [
             "Read(foo/*/bar/cache/**)"
         ]
     }}

❯ use Bash to echo "hello world"

● Bash(echo "hello world")
  ⎿  Interrupted · What should Claude do instead?

● The command was interrupted. What would you like me to do instead?

Bash croaks. If I check the debug log:

2026-04-10T23:35:41.677Z [DEBUG] Shell exec error: E2BIG: argument list too long, posix_spawn '/usr/bin/zsh'
2026-04-10T23:35:41.679Z [DEBUG] Bash tool error (131ms): Shell command failed

But if I delete that single deny rule, Bash works fine!

Summary

On Linux, when permissions.deny contains Read(...) rules with mid-path glob wildcards (e.g., Read(foo/*/data/cache/**)), the sandbox appears to expand the glob against the actual filesystem and generate a separate bubblewrap bind-mount argument for every matching file. In a project with thousands of generated/cached files under the matched path, the resulting bwrap argument list exceeds Linux's ARG_MAX, and posix_spawn fails with E2BIG.

This does not occur on macOS.

Environment

  • Claude Code v2.1.101
  • Linux (RHEL-family), not containerized
  • ARG_MAX: 2,097,152 (2MB)
  • MAX_ARG_STRLEN: 131,072 (128KB) — PAGE_SIZE * 32
  • ulimit -s: 8192
  • Shell snapshot size: ~116KB (from --debug log)
  • Shell environment size: ~3.7KB
  • Sandbox enabled via managed-settings.json (sandbox.enabled: true, sandbox.failIfUnavailable: true)
  • Bubblewrap + socat

Steps to reproduce

  1. On Linux with sandbox enabled, have a project containing a directory tree with thousands of files (e.g., App cache: foo/*/data/cache/ — mine has ~2,700 entries across two subdirectories)
  2. Add a single deny rule to .claude/settings.json:
    { "permissions": { "deny": ["Read(foo/*/data/cache/**)"] } }
  3. Start Claude from the project directory
  4. Run any Bash command (e.g., echo hello)

Result: Every Bash command fails silently. The model sees "Interrupted" and hallucinates explanations. Only claude --debug reveals the real error:

Shell snapshot created successfully (118918 bytes)
Spawning shell without login (-l flag skipped)
Shell exec error: E2BIG: argument list too long, posix_spawn '/usr/bin/zsh'
Bash tool error (509ms): Shell command failed

Diagnosis

I isolated the cause to a single permissions.deny rule:

"Read(foo/*/data/cache/**)"

Key observations:

  • Only Read(...) deny rules trigger it. The following rules with identical or broader wildcards do NOT cause E2BIG, even when present simultaneously:

    • Edit(**/data/cache/**) — no problem
    • Write(**/data/cache/**) — no problem
    • Grep(foo/*/data/cache/**) — no problem

    This suggests only Read (and possibly Edit) deny rules are translated into OS-level sandbox filesystem restrictions. Write, Grep, and Bash deny rules appear to operate only at the tool permission level.

  • Rooted patterns are fine. Read(build/**) works (only 8 files in build/). The issue is specifically mid-path wildcards that fan out across directories with many files.

  • Patterns starting with ** are fine. Edit(**/data/cache/**) doesn't trigger it, suggesting the expansion logic skips patterns with no concrete prefix before the first glob character.

  • Explicit paths fix it. Replacing the wildcard with the actual directory names works. See "Workaround" below.

  • The problem scales with file count. find foo/*/data/cache/ | wc -l returns 2,704. At ~100+ bytes per bwrap argument, that's ~270KB of additional argv — enough to push past OS limits when combined with the ~116KB shell snapshot.

  • Only occurs on Linux. The identical settings work fine on macOS, which uses sandbox-exec profiles instead of bubblewrap bind-mounts.

  • Only occurs in project directories. Running from ~ (no project-level deny rules) works fine. The managed-settings deny rules alone don't trigger it.

  • getLinuxGlobPatternWarnings() — the /sandbox UI displays warnings about glob patterns not working on Linux, so this limitation is partially known. But the glob expansion still proceeds and causes the crash.

Workaround

Replace mid-path wildcards with explicit directory names:

"Read(foo/bar/data/cache/**)",
"Read(foo/baz/data/cache/**)"

Suggested fix

When building bubblewrap arguments from denyRead glob patterns, resolve to the shallowest matching directories and emit one --tmpfs overlay per directory, rather than expanding ** into per-file bind-mounts. For foo/*/data/cache/**, the correct bwrap output should be two directory overlays — not 2,704 individual file entries.

What Should Happen?

Claude's ability to use Bash should not be impaired by this single trivial deny rule.

Error Messages/Logs

Documented above

Steps to Reproduce

Documented above

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

No response

Claude Code Version

2.1.101 (Claude Code)

Platform

Anthropic API

Operating System

Other Linux

Terminal/Shell

iTerm2

Additional Information

No response

extent analysis

TL;DR

The issue can be fixed by modifying the deny rule in .claude/settings.json to use explicit directory names instead of mid-path glob wildcards.

Guidance

  1. Identify problematic deny rules: Look for rules with mid-path glob wildcards (e.g., Read(foo/*/bar/cache/**)) that may be causing the issue.
  2. Replace wildcards with explicit directory names: Update the deny rules to use explicit directory names instead of wildcards (e.g., Read(foo/bar/data/cache/**) and Read(foo/baz/data/cache/**)).
  3. Verify the fix: Run Claude with the updated deny rules and check if Bash commands work as expected.
  4. Monitor for similar issues: Keep an eye on other deny rules that may be using mid-path glob wildcards and update them accordingly.

Example

// Before
{
  "permissions": {
    "deny": [
      "Read(foo/*/data/cache/**)"
    ]
  }
}

// After
{
  "permissions": {
    "deny": [
      "Read(foo/bar/data/cache/**)",
      "Read(foo/baz/data/cache/**)"
    ]
  }
}

Notes

This fix assumes that the issue is caused by the expansion of mid-path glob wildcards in deny rules. If the issue persists after applying this fix, further investigation may be needed to identify the root cause.

Recommendation

Apply the workaround by replacing mid-path wildcards with explicit directory names in the deny rules. This should resolve the issue and allow Bash commands to work as expected.

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