Desktop-app-installed claude.app bundle has no published checksum and carries entitlements the bare CLI does not
Summary
The Claude Desktop app installs a second, .app-wrapped copy of Claude Code at:
~/Library/Application Support/Claude/claude-code/<version>/claude.app
This bundle carries privileges the bare CLI does not, but it is the one artifact that
cannot be verified using the procedure documented at
https://code.claude.com/docs/en/setup#binary-integrity-and-code-signing
The signature itself checks out. This is a documentation and verifiability request,
not a vulnerability report.
Entitlements on the bundle
com.apple.security.device.audio-input true
com.apple.security.automation.apple-events true
com.apple.security.cs.allow-jit true
com.apple.security.cs.allow-unsigned-executable-memory true
com.apple.security.cs.disable-library-validation true
Info.plist adds NSMicrophoneUsageDescription, NSAppleEventsUsageDescription,
and NSLocalNetworkUsageDescription, with LSBackgroundOnly=true.
The bare CLI at ~/.local/share/claude/versions/<version> is a plain Mach-O with
no bundle identity and therefore none of these.
The verification gap
manifest.json for 2.1.270 lists only the bare CLI:
darwin-arm64 checksum a506b6d970a4cf44f6abdb53a81ddcd5d3b0ce042a95c502fe9d1f946bdb8807
size 207500480
The bundle's Mach-O has the identical size (207500480) but a different SHA-256:
8c445eb97212efb868308c953d73a2b127c03ab1791e6a9e379d3fb85d4c68b1
Presumably the same compiled code re-signed with the additional entitlements, but
there is no published checksum for this variant, so a user cannot confirm that.
What does verify:
codesign:Anthropic PBC (Q6L2SF6YDW), notarized, ticket stapledspctl -a -vvv -t exec: accepted, source = Notarized Developer ID- Signing timestamp predates local install, so it was not re-signed on-device
Why the entitlement combination is worth documenting
macOS TCC grants attach to the bundle identity, not to individual code within the
process. With disable-library-validation set, code loaded into the process from a
library signed by any identity inherits the bundle's grants, including microphone.
I recognise the JIT/unsigned-memory/library-validation trio is standard for an app
embedding a JS runtime that loads native addons (MCP servers, native npm modules),
and that the marginal risk is limited given Claude Code executes user-approved shell
commands by design. It is still a privileged surface that currently ships
undocumented and unverifiable.
Requests
- Publish checksums for the
.appvariant inmanifest.json, or document why it
is excluded from the signed manifest.
- Document that the Desktop app installs a separate, more privileged copy of Claude
Code, where it lives, and which entitlements it holds.
- Clarify whether the microphone entitlement is dormant until voice mode is invoked,
and whether denying or revoking the grant degrades any other functionality.
Notes
- No launch agents or daemons are installed; no
launchctljobs reference it. log show --predicate 'subsystem == "com.apple.TCC"' --last 7d | grep -i claude
returns nothing in the 7 days since install, suggesting the microphone grant has
not been requested.
- Legacy
autoUpdates: falsein~/.claude.jsonappears inert:claude doctor
reports Auto-updates: enabled. Possibly worth a separate issue.
Environment
macOS 15 (Darwin 25.6.0), arm64
Desktop app 1.52386.6
Bundled Claude Code 2.1.270
CLI 2.1.267 (stable channel, native install)
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗