[Bug] Native installer produces unsealed macOS app bundle rejected by code signature validation

Open 💬 4 comments Opened Jun 24, 2026 by jeroenvisser101

Bug Description

Bug: native installer produces a malformed (unsealed) ClaudeCode.app → macOS reports it as "damaged and can't be opened"

Summary

The Claude Code native installer creates ~/.local/share/claude/ClaudeCode.app without the code-signing seal (Contents/_CodeSignature/CodeResources). The bundle's Mach-O binary carries an Anthropic Developer ID signature whose CodeDirectory indicates sealed resources must be present, but the bundle on disk has none. macOS therefore fails signature validation and shows:

"ClaudeCode.app" is damaged and can't be opened. You should move it to the Trash.

The bundle is not quarantined — this is not a Gatekeeper/quarantine prompt, it's a broken/incomplete signature. It is reproducible: claude install latest --force regenerates the same malformed bundle.

Environment

  • Claude Code CLI: 2.1.190
  • Affected app bundle: ~/.local/share/claude/ClaudeCode.app (CFBundleIdentifier = com.anthropic.claude-code, LSUIElement = true)
  • macOS: 26.5.1 (build 25F80), Apple Silicon (arm64)
  • Installed native versions present: 2.1.183, 2.1.185, 2.1.186, 2.1.187, 2.1.190
  • Launcher: ~/.local/bin/claude → symlink → ~/.local/share/claude/versions/2.1.190

Steps to reproduce

  1. Have the CLI manage the native build (auto-update or claude install).
  2. Trigger whatever launches the helper app (or simply double-click ~/.local/share/claude/ClaudeCode.app).
  3. macOS shows the "damaged and can't be opened" dialog.
  4. claude install latest --force → reinstall succeeds, but the regenerated bundle is still malformed (same dialog).

Evidence

Malformed bundle layout (missing _CodeSignature/ and CodeResources):

ClaudeCode.app/Contents/
├── Info.plist
└── MacOS/claude          # 217 MB Mach-O, signed Developer ID Application: Anthropic PBC (Q6L2SF6YDW)

A healthy reference bundle (the claude.app bundled inside Claude Desktop, v2.1.181) — for contrast, it has the seal:

claude.app/Contents/
├── _CodeSignature/        # present
├── CodeResources          # present
├── Info.plist
└── MacOS/

Gatekeeper / codesign verdict on the malformed bundle:

$ spctl -a -vvv ClaudeCode.app
ClaudeCode.app: code has no resources but signature indicates they must be present

$ codesign --verify --deep --strict --verbose=2 ClaudeCode.app
ClaudeCode.app: code has no resources but signature indicates they must be present

No quarantine attribute (rules out a normal Gatekeeper download prompt):

$ xattr -l ClaudeCode.app
com.apple.macl: …        # only this (TCC); no com.apple.quarantine

The embedded signature is genuine Anthropic, with hardened runtime + entitlements — the binary is fine; only the bundle seal is missing:

Identifier=com.anthropic.claude-code
Authority=Developer ID Application: Anthropic PBC (Q6L2SF6YDW)
TeamIdentifier=Q6L2SF6YDW
CodeDirectory … flags=0x10000(runtime)
Entitlements: com.apple.security.device.audio-input,
              com.apple.security.automation.apple-events,
              com.apple.security.cs.allow-jit,
              com.apple.security.cs.allow-unsigned-executable-memory,
              com.apple.security.cs.disable-library-validation

Likely root cause

When the installer materializes ClaudeCode.app, it writes Info.plist and the (separately signed) MacOS/claude binary but does not include/produce the bundle's _CodeSignature/CodeResources seal. Because the binary's CodeDirectory expects sealed resources, the bundle fails validation as a whole and macOS marks it "damaged." The shipped/notarized bundle should include the seal (as the Claude Desktop reference bundle does).

Impact

  • The native helper app (voice dictation / URL opening / Apple Events) cannot be launched; users get a "damaged — move to Trash" dialog that wrongly implies malware/corruption.
  • Confusing because the CLI itself (~/.local/bin/claude) works perfectly — only the .app wrapper is broken.
  • Repeated trash-and-recreate by the updater left multiple stale ClaudeCode.app copies in ~/.Trash.

Suggested fix

Have the installer either (a) ship/copy the complete signed .app bundle including Contents/_CodeSignature/CodeResources, or (b) re-sign the bundle after assembling it on disk so the seal matches the contents. A post-install codesign --verify --deep --strict check would catch this regression.

Local workaround (temporary; undone by next update)

Re-sign the assembled bundle locally, preserving entitlements and hardened-runtime flags:

codesign --force --deep --preserve-metadata=entitlements,flags -s - \
  ~/.local/share/claude/ClaudeCode.app

After this, codesign --verify --deep --strict reports "valid on disk / satisfies its Designated Requirement" and the app launches (it is not quarantined). Note this…
Note: Content was truncated.

View original on GitHub ↗

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