Claude Desktop: binaryName platform-switch causes macOS TCC prompt for 'Claude.exe'
Summary
Claude Desktop on macOS intermittently triggers a TCC (permission) prompt labelled "Claude.exe" would like to access data from other apps. The Windows executable name appears on macOS because a helper/subprocess path inside the packaged app falls through into the win32 branch of a platform-switch when resolving the embedded CLI binary.
Repro
- macOS 15.x (Darwin 25.5.0), Claude Desktop installed via
/Applications/Claude.app - Reproduced across three consecutive releases (observed over multiple versions during Sprint 200-217, 2026-03 → 2026-04)
- Trigger: happens during helper-process startup for certain session types (long-running Claude Code sessions with background tools / hooks)
- User-visible effect: macOS surfaces a permission dialog with the Windows binary name
Claude.exe, which is confusing and looks like malware to non-technical users
Suspected source
Inside /Applications/Claude.app/Contents/Resources/app.asar at approximately offset 8471026 there is a platform switch that resolves the embedded CLI binary name:
binaryName: process.platform === "win32" ? "claude.exe" : "claude"
A subsequent code path references binaryName before process.platform has been reliably set (or from a worker/forked context where process.platform returns something unexpected, so the ternary defaults to the Windows branch). The name is then surfaced by the OS when the macOS TCC subsystem labels the unsigned/unknown-to-TCC binary requesting access.
Why this matters
- On macOS the string
Claude.exeis a strong anti-signal for users — it looks like Windows malware masquerading as Claude. - A fraction of users will deny the prompt, breaking Claude Desktop functionality for them.
- The error is confusing even for technical users (reproduced in our environment 3 releases in a row, filed Sprint 217).
Recommended fix
Prefer a bundle-/OS-based resolution that cannot fall through to win32:
- Info.plist / bundle-based lookup on macOS: resolve the CLI binary name via the app bundle (
NSBundle.mainBundle.executablePath/process.resourcesPath) rather than viaprocess.platform. - Defensive default to the POSIX name: switch the ternary so Windows is the explicit case and every non-win32 platform (including when
process.platformis temporarily empty/undefined in a forked worker) lands onclaude:
``js``
binaryName: process.platform === "win32" ? "claude.exe" : "claude"
// becomes (safer default):
const isWin = process.platform === "win32";
binaryName: isWin && process.arch.startsWith("x") ? "claude.exe" : "claude";
- Platform + arch combined check: macOS reports
darwin+arm64/x64, neverwin32. Combiningprocess.platformwithprocess.archand asserting both catches any corner case where one dimension is unset.
Option 1 (bundle-based) is the cleanest because it removes the platform-switch entirely on macOS.
Additional context
- No sensitive info is leaked by the prompt, but it severely damages perceived trust.
- Filed as part of Sprint 217 Claude-Desktop stability review.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗