[Tahoe 26.x] terminal process tree EPERM in ~/Documents — root cause analysis & data

Open 💬 3 comments Opened May 14, 2026 by s9405418

TL;DR

On macOS Tahoe 26.3, Claude Code sessions running inside a terminal (originally iTerm, later switched to Ghostty — both affected) intermittently trigger Operation not permitted for any read/exec under ~/Documents, across every shell in that terminal's process tree. cmd+Q + restart reliably recovers; no in-place fix works.

Over ~6 days I've collected 5 incidents and tested 4 hypotheses to refute. I'm filing this primarily to share refuted hypotheses so others don't redo the work, and to ask what additional data Anthropic / community would find useful.

Environment

  • macOS 26.3 (Tahoe, build 25D125)
  • Claude Code 2.1.139 (auto-update enabled)
  • Terminal: Ghostty 1.3.1 (after migrating from iTerm2 stable — both exhibit the issue)
  • Shell: zsh 5.9 (/bin/zsh system default)
  • FDA grants in place: iTerm, Ghostty, claude.exe (added manually after first major incident)
  • Other relevant: company-issued machine with EndpointProtector DLP (CoSoSys) — but colleagues with same DLP + Claude Code don't see this, so DLP is not the sole cause

Symptoms

Same as #49820 / #21942 / #21654:

  • git, bash <script>, cat <file>, ls <dir> all return Operation not permitted for any pre-existing file under ~/Documents
  • Only inside the affected terminal's process tree — opening a fresh terminal of a different app is fine
  • ~/Desktop, ~/Downloads, /tmp unaffected even during incident
  • Fresh-write into ~/Documents succeeds, and fresh-exec of newly-written files succeeds — only pre-existing files are denied (this last point conflicts with the simple "kernel taints the tree" mental model)
  • No TCC prompt; no entry in log show --predicate 'subsystem == "com.apple.TCC"' corresponding to the deny
  • cmd+Q the whole terminal app + restart → fully recovers
  • Recurrence interval: 1-4 days, no obvious trigger from user side

Reproduction

I don't have a clean repro recipe. The trigger appears non-deterministic. One distinctive observation from the most recent incident: claude.exe directory was rewritten (mtime of every file under /opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/ updated within minutes of incident detection) without any npm install log → presumably Claude Code's built-in self-updater. The timing correlation is suggestive but not proven causal.

Hypotheses tested and refuted

I want to surface these so others can skip them.

❌ H1: claude.exe missing TCC entry → terminal tree gets tainted ("guilt by hosting")

  • Initial hypothesis after first deep incident
  • Adding /opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/bin/claude.exe to FDA gave 4 days of no recurrence → seemed confirmed
  • Refuted day 5: FDA entry still in system TCC.db (SELECT auth_value FROM access WHERE client LIKE '%claude%.exe%' returns 2), incident recurred with identical symptoms

❌ H2: TCC entry binds CDHash, gets invalidated on update

  • Hypothesized after H1 refute: maybe npm/self-update changes CDHash and breaks entry
  • Decoded csreq blob in /Library/Application Support/com.apple.TCC/TCC.db: it's identifier "com.anthropic.claude-code" and anchor apple generic and certificate leaf[subject.OU] = "Q6L2SF6YDW" — identifier + Team ID binding, not CDHash
  • New binary still matches the requirement
  • Refuted: csreq is content-agnostic w.r.t. CDHash; npm updates don't invalidate the entry

❌ H3: Tahoe AllFiles no longer auto-subsumes DocumentsFolder

  • Ghostty has kTCCServiceSystemPolicyAllFiles=allow in system TCC.db but no explicit kTCCServiceSystemPolicyDocumentsFolder entry
  • iTerm has both explicitly
  • Theory: Tahoe split the supersede relationship
  • Refuted: System Settings → Privacy → Files and Folders shows Ghostty with "Full Disk Access" tag (locked, inherited from FDA setting), confirming AllFiles still subsumes Documents

❌ H4: DLP / EndpointSecurity extension is the gatekeeper

  • Reported EndpointProtectorClient in Files and Folders permission list
  • Theory: third-party DLP hooking file ops below TCC layer (which would explain why TCC logs show no deny)
  • Refuted: Colleagues with the same DLP + Claude Code combo don't see this

Surviving but unprovable hypotheses

  • H5: claude.exe is not the responsible subject at all — H1's 4-day stability was coincidental. No clear path to falsify without an A/B comparison.
  • H6: Another macOS layer (CoreServices? launchd-tracked file attribution?) is gatekeeping. systemextensionsctl list shows only Fortinet VPN; no Endpoint Security extensions present.
  • H7 (weak): Claude Code's silent self-updater rewrites the binary directory, which invalidates some per-inode kernel cache, which re-evaluates incorrectly under Tahoe. Time-line evidence only; no proof.

Workarounds tried

| Workaround | Effect | Cost |
|---|---|---|
| cmd+Q + restart terminal app | Reliable | Lose unsaved session state |
| Add claude.exe to FDA | Helped initially, recurred after 4 days | Manual repeat after each update? unclear |
| Switch terminal (iTerm → Ghostty) | No effect (both fail) | One-time migration |
| Force bash via CLAUDE_CODE_SHELL=/bin/bash | Reported elsewhere; haven't tried | Lose zsh |
| Disable Claude Code auto-update | Untested but planned | Manual updates required |

Diagnostic data collected

I've kept structured logs of each incident in a local repo: process chain dumps, TCC.db state snapshots, log show excerpts, xattr traces, fresh-exec boundary tests. Happy to share specific excerpts on request — I can post sanitized snippets here if there's interest, or attach a .tar.gz.

Particularly distinctive on the most recent incident: TCC log over 30 minutes around the incident contains zero denies for claude.exe or ~/Documents access — contradicting the assumption that this is a TCC-layer denial.

Asks for maintainers

  1. What additional data would help you root-cause this? I'm willing to instrument further.
  2. Is the silent self-updater documented anywhere? I want to be sure it's not coincidental that claude.exe's mtime gets rewritten without npm install logs.
  3. Can claude ship with a --disable-autoupdater or autoUpdates: false config that's discoverable in claude doctor? I'd opt in if I knew it existed.
  4. Is anyone tracking this against Apple Feedback Assistant? If the root cause is Tahoe-side, this might need parallel reporting.

Related issues

  • #49820 — Tahoe zsh sysctl sandbox
  • #21942 — com.apple.provenance
  • #21654 — cwd-* op not permitted
  • #22109 — zsh writes to /tmp/claude-501
  • #22008 — hooks ignored on iTerm

All overlap in symptom but none isolate the root cause.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗