[BUG] Bash sandbox: TCC attribution fails for the live claude process (stale audit token), Documents access lost until TCC toggle

Status Open
Reported on v2.1.248
Maintainer reply None cached
Activity 4 comments · opened Aug 27, 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?

Bash sandbox loses macOS Documents-folder access mid-session; only a TCC toggle restores it

Environment

  • Claude Code 2.1.248, installed via npm (~/.nvm/versions/node/v22.22.2/lib/node_modules/@anthropic-ai/claude-code/bin/claude.exe), Node v22.22.2
  • macOS 15.7.7 (24G720)
  • Terminal: Ghostty 1.3.1, which holds the "Files and Folders -> Documents Folder" grant
  • Project directory under ~/Documents/... (a TCC-protected folder)
  • Bash sandbox enabled (default)

What happens

Several times per session, every file access inside the project directory starts failing with Operation not permitted -- from Bash commands, from uv run python, and from the Read tool (which runs in the main Claude Code process, not in a shell). The first symptom is usually Current directory does not exist from a command that includes a cd into the project, then EPERM on everything under ~/Documents. It never recovers on its own. The only fix is to open System Settings -> Privacy & Security -> Files and Folders and toggle Ghostty's "Documents Folder" switch off and on. It happened five times on 2026-08-27 (10:19, 10:26, 10:28, 17:32, 17:42), all within one Claude Code process (pid 51837, started 09:11).

Nothing in the project changed permissions (owner uid 501, mode unchanged), and Ghostty's TCC record for the Documents folder was NOT modified between the user's toggles -- the only writes to that record all day are the toggles themselves (10:26, 11:48, 17:42).

Evidence (unified log, log show --info --predicate 'process == "tccd" OR process == "sandboxd"')

The same sequence every time. This is the 17:32:51 occurrence, trimmed:

17:32:51 sandboxd: (TCC) SEND: 0/7 synchronous to com.apple.tccd: request: msgID=373.2347,
         function=TCCAccessRequest, service=kTCCServiceSystemPolicyDocumentsFolder,
17:32:51 tccd: REQUEST: tccd_uid=501, sender_pid=373, sender_uid=0, sender_auid=-1,
         function=TCCAccessRequest, msgID=373.2347
17:32:51 tccd: REQUEST_MSG: msgID=373.2347, msg={
             service="kTCCServiceSystemPolicyDocumentsFolder"
             TCC_MSG_REQUEST_AUTHORIZATION_SUBJECT_CREDENTIAL_DICTIONARY_KEY={
                 TCCD_MSG_CREDENTIAL_AUTHENTICATOR_TYPE_KEY=1 (0x1)
                 TCCD_MSG_CREDENTIAL_AUTHENTICATOR_AUDIT_TOKEN_KEY={pid:51837, auid:501, euid:501}
             }
         }
17:32:51 tccd: proc_pidpath_audittoken() failed from PID[51837]: (#3) No such process
17:32:51 tccd: Failed to build 'accessingProcess' from indirect_object_token in message from
         <TCCDProcess: identifier=com.apple.sandboxd, pid=373, auid=0, euid=0,
         binary_path=/usr/libexec/sandboxd>
17:32:51 tccd: REPLY_MSG: msg={
             auth_error_string="Failed to create Attribution Chain from message."
             auth_value=0 (0x0)
             auth_error_code=5 (0x5)
             result=false
             auth_reason=1 (0x1)
         }
17:32:51 sandboxd: tcc_server_message_request_authorization(kTCCServiceSystemPolicyDocumentsFolder)
         failed: Error Domain=kTCCErrorDomain Code=5 "server error: Failed to create Attribution
         Chain from message."
17:32:51 sandboxd: kTCCServiceSystemPolicyDocumentsFolder denied by TCC for claude.exe

Points to note:

  1. The audit token names pid 51837. That process is alive -- it is the Claude Code process itself: ps -p 51837 -> claude --name ... (started Thu Aug 27 09:11:14 2026). Yet tccd's proc_pidpath_audittoken() returns "No such process", which is what it returns when the token's pid/pidversion pair no longer matches the live process (a stale token).
  1. Because tccd cannot attribute the request, it never consults the TCC database at all (auth_reason=1, error code 5); the request fails on attribution, not on a stored decision.
  1. sandboxd turns that error into a denial for claude.exe, and from then on every access from the process is refused -- including the Read tool, which does not go through the sandbox.
  1. Toggling Ghostty's Documents switch publishes a TCCDEvent: type=Modify for the Documents service, which makes tccd/sandboxd drop the cached denial. That is why the toggle "fixes" it even though the stored grant was never changed. During the seconds the switch is off, the same log shows the expected Auth Right: Denied (System Set) for Ghostty and a denied by TCC for jq from a hook script -- those are consequences of the toggle, not the cause.
  1. The same PID[51837]: (#3) No such process -> Failed to create Attribution Chain pair appears at each of the five outage times.

The commands that were running when it tripped were ordinary project commands (cd <project> && uv run python ...). uv run spawns short-lived interpreter probes (the log also shows Apple's /usr/bin/python3 being launched from the project directory), which is consistent with the sandbox handing tccd a token for a process that has already changed or gone.

Suggested fix in the sandbox

  1. When sandboxd's TCC request fails with kTCCErrorDomain Code=5 ("Failed to create Attribution Chain"), treat it as an attribution error, not as a policy decision: do not record or cache a denial for the Claude Code process. Retry the request with a fresh audit token of the live process (or of the responsible application), and fall back to the responsible app's existing grant, which in this case is "Allowed".
  1. Obtain the audit token used for TCC requests at request time from the live main process rather than from a token captured earlier (at sandbox setup or from a transient child). A pid can be reused and a pidversion changes on exec; the "No such process" reply here is the stale-token signature.
  1. Alternatively, avoid per-command TCC consultation entirely: at session start, when the working directory is inside a TCC-protected folder and the main process already has access, extend that access into the sandbox (a file-read/write sandbox extension for the working directory) so sandboxed children do not re-request Documents access on every command.

Workaround in use

Toggle the terminal app's "Documents Folder" switch in System Settings each time.

Not acceptable workarounds

  1. Moving the project out of ~/Documents avoids the TCC check altogether.
  2. Granting Full Disk Access to the terminal.

What Should Happen?

Sandboxed commands and the Read tool should keep access to the project directory for the whole session, as the terminal app's existing "Documents Folder" grant allows. When the sandbox's TCC request fails on attribution (kTCCErrorDomain Code=5, "Failed to create Attribution Chain"), Claude Code should treat that as an error and retry with a valid audit token, or fall back to the responsible app's grant — not cache a denial for the main process. Access should never require the user to toggle a Privacy & Security switch to recover.

Error Messages/Logs

17:32:51 sandboxd: (TCC) SEND: 0/7 synchronous to com.apple.tccd: request: msgID=
373.2347,
         function=TCCAccessRequest, service=kTCCServiceSystemPolicyDocumentsFolde
         r,
17:32:51 tccd: REQUEST: tccd_uid=501, sender_pid=373, sender_uid=0, sender_auid=-
1,
         function=TCCAccessRequest, msgID=373.2347
17:32:51 tccd: REQUEST_MSG: msgID=373.2347, msg={
             service="kTCCServiceSystemPolicyDocumentsFolder"
             TCC_MSG_REQUEST_AUTHORIZATION_SUBJECT_CREDENTIAL_DICTIONARY_KEY={
                 TCCD_MSG_CREDENTIAL_AUTHENTICATOR_TYPE_KEY=1 (0x1)
                 TCCD_MSG_CREDENTIAL_AUTHENTICATOR_AUDIT_TOKEN_KEY={pid:51837, au
                 id:501, euid:501}
             }
         }
17:32:51 tccd: proc_pidpath_audittoken() failed from PID[51837]: (#3) No such pro
cess
17:32:51 tccd: Failed to build 'accessingProcess' from indirect_object_token in m
essage from
         <TCCDProcess: identifier=com.apple.sandboxd, pid=373, auid=0, euid=0,
         binary_path=/usr/libexec/sandboxd>
17:32:51 tccd: REPLY_MSG: msg={
             auth_error_string="Failed to create Attribution Chain from message."
             auth_value=0 (0x0)
             auth_error_code=5 (0x5)
             result=false
             auth_reason=1 (0x1)
         }
17:32:51 sandboxd: tcc_server_message_request_authorization(kTCCServiceSystemPoli
cyDocumentsFolder)
         failed: Error Domain=kTCCErrorDomain Code=5 "server error: Failed to cre         ate Attribution
         Chain from message."
17:32:51 sandboxd: kTCCServiceSystemPolicyDocumentsFolder denied by TCC for claude.exe

Steps to Reproduce

Several times per session, every file access inside the project directory starts failing with Operation not permitted -- from Bash commands, from uv run python, and from the Read tool (which runs in the main Claude Code process, not in a shell). The first symptom is usually Current directory does not exist from a command that includes a cd into the project, then EPERM on everything under ~/Documents. It never recovers on its own. The only fix is to open System Settings -> Privacy & Security -> Files and Folders and toggle Ghostty's "Documents Folder" switch off and on. It happened five times on 2026-08-27 (10:19, 10:26, 10:28, 17:32, 17:42), all within one Claude Code process (pid 51837, started 09:11).

Nothing in the project changed permissions (owner uid 501, mode unchanged), and Ghostty's TCC record for the Documents folder was NOT modified between the user's toggles -- the only writes to that record all day are the toggles themselves (10:26, 11:48, 17:42).

Claude Model

Other

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

2.1.248 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Other

Additional Information

_No response_

View original on GitHub ↗

3 Comments

BA88 · 1 month ago

Is this a bug you will investigate?

BA88 · 1 month ago

Reproduced on Claude Code 2.1.263 (latest as of Sun, 06 Sep 2026), macOS Darwin 24.6.0, Ghostty, npm install, Bash sandbox on, project under ~/Documents.

Trigger this time was identifiable. A Bash command did cd into a session-scratchpad directory under /private/tmp/claude-501/... to run LibreOffice, and a later command deleted that directory. The persistent shell was left in a deleted cwd. From then on:

  1. Every PreToolUse hook (all python3 scripts) failed with Fatal Python error: error evaluating path ... OSError: failed to make path absolute and Current directory does not exist, reported as a non-blocking hook error.
  2. Within a few commands, every path under ~/Documents/<project> returned Operation not permitted: from sandboxed Bash, from Bash with the sandbox disabled, and from the Read tool in the main process (EPERM: operation not permitted, open ...). Paths outside ~/Documents stayed readable.
  3. It did not recover on its own. Toggling Ghostty's Documents Folder grant off and on in System Settings restored access immediately, same as before.

So a shell left in a nonexistent cwd appears to be one way to hit the attribution failure. Noting that the only "merged" item on this issue's timeline is a third-party repository's docs PR citing this issue, not a Claude Code change; nothing in the 2.1.249 to 2.1.263 changelog covers this.

BA88 · 1 month ago

Update: Docker confirms TCC is the root cause, not sandbox logic

I spent a session trying to move Claude Code into a Docker container (OrbStack, Linux, project mounted via VirtioFS) specifically to avoid this bug. It works — the TCC attribution failure cannot trigger inside a container because VirtioFS bypasses TCC entirely.

But Docker is not a viable workaround. The platform split (Linux vs macOS) means the Python venv built for macOS doesn't work inside the container. Maintaining two venvs per project defeats the purpose. I abandoned the approach.

This confirms the bug is purely a TCC/sandboxd interaction — nothing about Claude Code's own sandbox logic or permission system. The failure path is:

  1. Claude Code spawns a short-lived child (e.g. uv run interpreter probe, or a shell left in a deleted cwd)
  2. sandboxd captures the child's audit token
  3. The child exits
  4. sandboxd sends a TCC request using the now-stale token
  5. tccd fails with proc_pidpath_audittoken() ... (#3) No such process → error code 5 ("Failed to create Attribution Chain")
  6. sandboxd caches the denial against the parent Claude Code process
  7. All file access under ~/Documents dies — Bash, Read tool, everything

Impact

  • Happens multiple times per session, unpredictably
  • Only workaround is toggling the terminal's Documents Folder permission in System Settings, which kills the session
  • Affects anyone with a project in a TCC-protected folder (~/Documents, ~/Desktop, ~/Downloads)
  • Forces users to either move projects out of standard macOS locations or accept frequent session interruptions
  • This is the #1 reason I cannot use auto mode or sandbox mode — I turned both off to reduce child process spawning, which only reduces frequency, doesn't eliminate it

blockReadsOutsideWorkingDirectories makes the prompting worse

Setting blockReadsOutsideWorkingDirectories: true — the recommended way to keep Claude inside the project — triggers a permission prompt on every compound Bash command. Pipes, subshells, variable expansion, PIPESTATUS checks — anything the static analyzer can't fully parse gets flagged as "Contains expansion; under the read block ... a command the shell parser cannot analyze asks the person." This is most Bash commands in practice.

So the two mitigations fight each other:

  • Without blockReadsOutsideWorkingDirectories, Claude can read anywhere on the machine.
  • With it, I get prompted dozens of times per session on commands that touch nothing outside the project.
  • autoAllowBashIfSandboxed would fix the prompts, but enabling the sandbox risks increasing TCC failures.

There is no configuration that gives me "stay inside the project, don't ask me about it, and don't break" on macOS with a ~/Documents project.

Why this matters now

Four months ago I didn't worry much about Claude staying inside the project directory. With each model upgrade, the behavior has gotten more aggressive. Claude now reads and writes files outside the project, modifies shell configs, and runs commands with side effects beyond the working directory — unless actively restrained.

So I went to restrain it, and found there's no working configuration on macOS:

  • blockReadsOutsideWorkingDirectories creates a wall of permission prompts on normal commands
  • The sandbox risks TCC failures that lock out the entire session
  • Docker requires a platform split that breaks the Python toolchain
  • Moving projects out of ~/Documents is a workaround for a macOS integration bug, not a solution

The models are getting more capable and more autonomous, but the guardrails haven't kept up. I have no way to tell Claude "work freely inside this directory, hard stop at the boundary" on a Mac with projects in ~/Documents — which is where macOS expects users to put their work.

Related

  • #91793 groups this with #88576, #87061, #49282, #80899 — all the same TCC root cause through different trigger paths
  • No response from Anthropic on any of these in 2-3 weeks

Ask

Can someone from the team acknowledge this cluster and say whether it's being investigated? The suggested fixes from the original report still stand:

  1. Obtain audit tokens at request time from the live process, not from captured child tokens
  2. Don't cache TCC denials on attribution failures (error code 5)
  3. Pre-authorize TCC-protected working directories at session start

Showing cached comments. Read the full discussion on GitHub ↗