Desktop-app-installed claude.app bundle has no published checksum and carries entitlements the bare CLI does not

Status Open
Reported on v2.1.270
Maintainer reply None cached
Activity 2 comments · opened Sep 16, 2026

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 stapled
  • spctl -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

  1. Publish checksums for the .app variant in manifest.json, or document why it

is excluded from the signed manifest.

  1. Document that the Desktop app installs a separate, more privileged copy of Claude

Code, where it lives, and which entitlements it holds.

  1. 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 launchctl jobs 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: false in ~/.claude.json appears 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)

View original on GitHub ↗

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