[BUG] Sandbox `denyWithinAllow` list omits `.git/` prefix from git-internal file paths

Status Closed — not planned
Reported on v2.1.42
Maintainer reply None cached
Activity 12 comments · opened Feb 15, 2026 · closed May 25, 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?

What's Wrong?

The sandbox's denyWithinAllow list constructs incorrect paths for git-internal files. Files that live inside .git/ (such as HEAD, objects, refs, hooks, config) are listed without the .git/ path component, pointing to nonexistent paths at the project root instead.

Actual Behavior

The deny list contains:

/path/to/project/HEAD
/path/to/project/objects
/path/to/project/refs
/path/to/project/hooks
/path/to/project/config

The .git/ segment is missing from every path.

Impact

  1. .git/ internals are unprotected. The deny rules target nonexistent paths at the project root, so the sandbox does not actually block writes to .git/HEAD, .git/objects, etc.
  2. False positives. If a project happened to have files named HEAD, config, objects, refs, or hooks at the root level, they would be incorrectly blocked.

What Should Happen?

Expected Behavior

The deny list should contain:

/path/to/project/.git/HEAD
/path/to/project/.git/objects
/path/to/project/.git/refs
/path/to/project/.git/hooks
/path/to/project/.git/config

Error Messages/Logs

Steps to Reproduce

Steps to Reproduce

  1. Create a standard (non-bare) git repo
  2. Enable sandbox in settings:
{
  "sandbox": {
    "enabled": true,
    "autoAllowBashIfSandboxed": true,
    "excludedCommands": ["git"]
  }
}
  1. Start a Claude Code session in the repo
  2. Ask Claude to show the full denyWithinAllow list
  3. Observe that git-internal files are listed without the .git/ prefix

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.42 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

VS Code integrated terminal

Additional Information

_No response_

View original on GitHub ↗

11 Comments

bpirvu · 6 months ago

Note: fixing the paths alone may not be sufficient

During investigation, I manually added correct Edit(.git/**) deny rules to my permissions config. This resulted in the sandbox blocking legitimate git add and git commit operations with errors like:

fatal: Unable to create '/path/to/project/.git/index.lock': Operation not permitted
error: unable to create temporary file: Operation not permitted
error: dot_claude/commands/commit-all.md: failed to insert into database

The root cause: when Claude wraps git commands inside bash -c "git add ... && git commit ..." (which it frequently does), bash is the top-level command, not git. The excludedCommands: ["git"] rule only applies when git is the top-level command, so the chained commands run inside the sandbox and hit the .git deny rules.

This means that if this bug is fixed by simply correcting the paths to include .git/, the corrected deny rules would break git operations for anyone whose Claude instance chains commands via bash -c — which appears to be the common behavior.

Possible approaches:

  • A: Fix the paths and make excludedCommands apply to child processes, not just the top-level command.
  • B: Fix the paths but exempt denyWithinAllow entries from applying to child processes of excluded commands.
  • C: Remove the git-internal entries from denyWithinAllow entirely and rely on the broader .git directory blocking rule that the sandbox already applies separately.
nf-matt · 6 months ago

I thought I was going crazy today. Glad you guys know about this, and thanks for what you build. 😃

seanlynch · 5 months ago

This also prevents use of the sandbox if your project has a subdirectory called for example "config". And it's not overridable with your local config settings, meaning there is no workaround other than to not use the sandbox for any bash command that might need to write to one of the inappropriately denied files/directories.

This is also a security vulnerability in the sandbox so should probably be prioritized rather than being allowed to go stale.

timothy-20 · 5 months ago

Adding fs_usage evidence from a real-world case where this bug causes silent data loss.

Observed behavior

In an Elixir/Phoenix project, Claude Code's sandbox periodically deletes the project-root config/ directory (a standard framework directory) because the denyWithinAllow list targets /path/to/project/config instead of /path/to/project/.git/config.

fs_usage syscall trace

21:06:43.821015  unlinkat  [2]  /path/to/project/HEAD       2.1.87.736478  (ENOENT)
21:06:43.821036  unlinkat  [2]  /path/to/project/objects    2.1.87.736478  (ENOENT)
21:06:43.821041  unlinkat  [2]  /path/to/project/refs       2.1.87.736478  (ENOENT)
21:06:43.821044  unlinkat  [2]  /path/to/project/hooks      2.1.87.736478  (ENOENT)
21:06:43.821046  unlinkat  [1]  /path/to/project/config     2.1.87.736478  (EPERM → retry)
21:06:43.821475  unlinkat       config/config.exs           2.1.87.736478  (success)
21:06:43.821598  unlinkat       /path/to/project/config     2.1.87.736478  (success — dir removed)

The sandbox enforcement process (2.1.87.736478) iterates over the malformed deny list and calls unlinkat on each entry. HEAD, objects, refs, hooks fail with ENOENT (they don't exist at the project root), but config/ exists as a real project directory and gets deleted.

Impact in practice

  • Deletion recurs every ~10-20 seconds, making git checkout HEAD -- config/ ineffective
  • Persists across sessions
  • Affects any project with a top-level config/ directory (Elixir/Phoenix, Ruby on Rails, etc.)
  • Only reliable workaround: chflags -R uchg config/ (macOS immutable flag)

Related

Closing #40568 as duplicate of this issue.

cc @seanlynch @nf-matt — the chflags -R uchg config/ workaround may help until this is fixed.

snoblenet · 4 months ago

If you can believe it, I'm about to rename my config dir to notfig... 👎

github-actions[bot] · 3 months ago

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

alvincrespo · 2 months ago
bpirvu · 2 months ago
I opened a new issue here: #66288

I hope you have more luck with this than I did... 😅

nf-matt · 2 months ago

Me too. It's hard to imagine nobody should be able to use a directory named config in their own projects.

alvincrespo · 2 months ago
> I opened a new issue here: #66288 I hope you have more luck with this than I did... 😅

Disabled sandbox for now as it's a blocker. Going to be investigating using containerization around Claude Code. Tis Bonkers.

nf-matt · 2 months ago
Disabled sandbox for now as it's a blocker. Going to be investigating using containerization around Claude Code. Tis Bonkers.

You might check out nono -- I've been using it quite successfully for months now, and agent autonomy is fantastic with it. I am able to run in "bypass permissions" mode because nono has everything boxed in the way I want.

Showing cached comments. Read the full discussion on GitHub ↗