[BUG] sandbox.credentials.files protection can be bypassed on first access to a not-yet-existing deny-listed path

Status Open
Reported on v2.1.259
Maintainer reply None cached
Activity 0 comments · opened Sep 8, 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?

Environment: Claude Code CLI 2.1.259, sandbox.enabled: true, sandbox.enableWeakerNestedSandbox: true (bubblewrap), running inside a Debian container itself running inside a macOS container VM.

Config (managed-settings.json):

"sandbox": {
  "credentials": {
    "files": [
      { "path": "credentials.json", "mode": "deny" },
      { "path": "serviceAccountKey.json", "mode": "deny" },
      { "path": ".env", "mode": "deny" }
    ]
  }
}

Repro steps:

  1. In a directory with no credentials.json present, ask Claude to run via the Bash tool: echo "hi" > credentials.json && cat credentials.json succeeds, discloses "hi". Identically reproduced with serviceAccountKey.json and .env.
  2. Immediately after, ask Claude to run cat credentials.json (standalone) correctly blocked, Permission denied.
  3. Ask Claude to run: rm credentials.json at this point fails with Device or resource busy, not Permission denied - the path is now an active mount point.
  4. Deleting and recreating the file in a new invocation reproduces the bypass again on the same filename; the file is protected again on the very next invocation after that.

Analysis: Consistent with sandbox.credentials.files being enforced via a bind-mount established once per Bash-tool invocation, over whichever deny-listed paths already exist on disk at that moment (a bind-mount destination must pre-exist). A path that doesn't exist yet gets no mount for that invocation, so one compound command that creates and reads it slips through entirely.

Impact: Any deny-listed filename not yet present on disk can be created and read back in a single shell command, bypassing the protection on that first access - exactly the shape a prompt-injected instruction could exploit against a not-yet-created secrets file. Reproduced across three unrelated filenames, so this isn't file-specific.

What Should Happen?

Expected: Protection shouldn't depend on whether the file existed before the sandboxed command started.

Error Messages/Logs

Steps to Reproduce

Environment: Claude Code CLI 2.1.259, sandbox.enabled: true, sandbox.enableWeakerNestedSandbox: true (bubblewrap), running inside a Debian container itself running inside a macOS container VM.

Config (managed-settings.json):

"sandbox": {
  "credentials": {
    "files": [
      { "path": "credentials.json", "mode": "deny" },
      { "path": "serviceAccountKey.json", "mode": "deny" },
      { "path": ".env", "mode": "deny" }
    ]
  }
}

Repro steps:

  1. In a directory with no credentials.json present, ask Claude to run via the Bash tool: echo "hi" > credentials.json && cat credentials.json succeeds, discloses "hi". Identically reproduced with serviceAccountKey.json and .env.
  2. Immediately after, ask Claude to run cat credentials.json (standalone) correctly blocked, Permission denied.
  3. Ask Claude to run: rm credentials.json at this point fails with Device or resource busy, not Permission denied - the path is now an active mount point.
  4. Deleting and recreating the file in a new invocation reproduces the bypass again on the same filename; the file is protected again on the very next invocation after that.

Analysis: Consistent with sandbox.credentials.files being enforced via a bind-mount established once per Bash-tool invocation, over whichever deny-listed paths already exist on disk at that moment (a bind-mount destination must pre-exist). A path that doesn't exist yet gets no mount for that invocation, so one compound command that creates and reads it slips through entirely.

Impact: Any deny-listed filename not yet present on disk can be created and read back in a single shell command, bypassing the protection on that first access - exactly the shape a prompt-injected instruction could exploit against a not-yet-created secrets file. Reproduced across three unrelated filenames, so this isn't file-specific.

Claude Model

Sonnet (default)

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.259 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

_No response_

View original on GitHub ↗