Uh oh!
There was an error while loading. Please reload this page.
fix(desktop): keep a development build's Keychain grant across rebuilds - #247
fix(desktop): keep a development build's Keychain grant across rebuilds#247charleslpan wants to merge 2 commits into
Conversation
An ad-hoc signature carries no identity, so macOS derives the designated requirement from the bytes themselves — a bare cdhash, new on every build. Both the Keychain and TCC bind a grant to that requirement, so every rebuild is a program neither has seen before: the login-password dialog returns however many times "Always Allow" was pressed, and a capture run hangs indefinitely because Screen Recording was never granted to that hash. LUKE_DEV_CODESIGN_IDENTITY names an identity to sign development builds with, moving the requirement onto the certificate, which every later build satisfies. It decides nothing else: resolveSigningMode still reads ad-hoc, so the build is still not a release, still answers to the development name, and still keeps its Keychain entry apart from the released app's. LUKE_CODESIGN_IDENTITY stays release-only, with a test pinning that. Electron's prebuilt bundle needs the same treatment for `electron .` runs: it ships linker-signed ad-hoc with no sealed resources, so it fails `codesign --verify` outright and the Keychain can never hold a durable entry for it. sidecar_sign_development_electron re-signs it after install, and leaves it alone when no identity is named. Without an identity nothing changes: the packager signs ad-hoc exactly as before and the Electron bundle is left as Electron shipped it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit e4ff435. Configure here.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
`codesign --display` reports only the executable path; the signature line comes from `-dvv`. The ad-hoc half of the skip test therefore matched nothing, so a bundle that verifies while still ad-hoc — one already re-signed `--sign -` — was left without the stable identity. The identity is trimmed here the way `developmentSigningIdentity` trims it too. A padded value would otherwise package fine and then reach codesign as a name wrapped in spaces, failing the lookup and taking the launch down with it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Risk: high. Left a non-blocking comment; this still changes codesigning and Keychain/TCC trust, so it stays above the approval threshold even though Bugbot and Security Agent passed and the prior findings are resolved. dastratakos is already assigned; no additional reviewers were added.
Sent by Cursor Approval Agent: Pull Request Router and Approver
Uh oh!
There was an error while loading. Please reload this page.



Problem
A development build is signed ad-hoc, which carries no identity — so macOS derives the designated requirement from the bytes themselves, a bare
cdhashthat is new on every build. Both the Keychain and TCC bind a grant to that requirement, so every rebuild is a program neither has seen before.Two symptoms, one cause:
Luke Dev Safe Storagelogin-password dialog returns on every launch, however many times "Always Allow" was pressed. The item's ACL accumulates one dead entry per build path (-67068 cannot find code object on disk), all pinned bycdhash, while the released app's single entry is pinned by identity and survives every update../scripts/evidence.shhangs indefinitely with no error. The capture app launches, loads ScreenCaptureKit, and never writes a PNG, because Screen Recording was never granted to that hash. Apple states the rule directly: TCC uses the code signature to decide that version N+1 is the same code as version N, and an ad-hoc signed app has no stable identity to remember.electron .runs are worse: Electron's prebuilt bundle is linker-signed ad-hoc with no sealed resources, so it failscodesign --verifyoutright ("code has no resources but signature indicates they must be present") and the Keychain can never hold a durable entry for it at all.Change
LUKE_DEV_CODESIGN_IDENTITYnames an identity to sign development builds with, moving the requirement onto the certificate.sidecar_sign_development_electrongives Electron's bundle the same treatment after install.It decides nothing else —
resolveSigningModestill reads ad-hoc, so the build is still not a release, still answers to the development name, and still keeps its Keychain entry apart from the released app's.LUKE_CODESIGN_IDENTITYstays release-only, with a test pinning that.Without an identity named, nothing changes: the packager signs ad-hoc exactly as before, and the Electron bundle is left as Electron shipped it. The release path is untouched.
For review
This adds a third state to a boundary the project guards deliberately — signed, but still not a release.
app-identity.tsandresolveSigningModewere built around a two-way split. The tests pin the new state so it cannot drift, but it is a widening worth deciding rather than assuming.Also worth a look:
sidecar_ensure_dependenciesnow signs as well as bootstraps, so its name no longer covers what it does. Callingsidecar_sign_development_electronfromrun.shandevidence.shdirectly would keep each function to one job.Verification
./scripts/check.sh— passes./scripts/evidence.sh— passes, six PNGs, expanded frame inspected and unchanged. This only completes withLUKE_DEV_CODESIGN_IDENTITYset; without it the capture hangs on this machine, which is the second symptom above.buildCarriesDeveloperIdSigning()still compiles tofalse, so it keeps the development name, state directory, and Keychain entry.🤖 Generated with Claude Code
Automated visual evidence
Download the deterministic macOS evidence · workflow run
4c926586c310c1738bbb72cad23ba0d747e74dd1smoke