Skip to content

Stop stamping hardened runtime onto ad-hoc builds - #4

Merged
dallasbpeters merged 1 commit into
mainfrom
rolemodel/adhoc-launchable
Aug 24, 2026
Merged

Stop stamping hardened runtime onto ad-hoc builds#4
dallasbpeters merged 1 commit into
mainfrom
rolemodel/adhoc-launchable

Conversation

@dallasbpeters

Copy link
Copy Markdown
Member

v0.0.1 could not be opened by anyone. The DMG installed, the app landed in /Applications, and it exited before drawing a window. Confirmed on a wiped machine installing from the release.

Cause

The ad-hoc signing step passed --options runtime, matching what electron-builder applies to a certificate-signed build — on the reasoning that the two should differ only in the identity. That reasoning is what shipped an unopenable app.

Hardened runtime plus an ad-hoc signature is fatal to Electron. Electron validates its helper processes' code signature, that validation needs the task port, and hardened runtime is what denies it:

electron/shell/common/mac/codesign_util.cc:79] task_name_for_pid: (os/kern) failure (5)

The evidence is a pair of flag sets on one machine:

build flags launches?
v0.0.1 release 0x10002(adhoc,runtime) ❌ exits immediately
dev build (npm run dev) 0x20002(adhoc,linker-signed) ✅ ran for hours

Same ad-hoc signature. The only difference is hardened runtime.

Worth noting the bundle was never corrupt — codesign --verify --deep --strict reported valid on disk and satisfies its Designated Requirement throughout. It's the signature type, not its integrity.

Fix

Drop --options runtime from the ad-hoc path only. It stays on the signed path, where it's mandatory for notarization and where it belongs. Entitlements are still applied.

TCC is unaffected — grants key to a stable signature, which this still produces, not to hardened runtime. That was the original concern behind matching the flags, and it doesn't apply.

The step now also fails the build if the flag appears anyway. The symptom of getting this wrong is a green release nobody can open, which is precisely how it shipped the first time.

What this does and doesn't fix

It makes unsigned builds launchable. It does not remove the Gatekeeper dialog — that needs a Developer ID certificate and notarization, which build.yml already performs when its six signing secrets are present. Until then the cask strips the quarantine flag (guarded on the signature, so it becomes a no-op once builds are notarized).

🤖 Generated with Claude Code

v0.0.1 could not be opened by anyone. The DMG installed, the app landed in
/Applications, and it exited before drawing a window.

The ad-hoc signing step passed --options runtime, matching what electron-builder
applies to a certificate-signed build on the reasoning that the two should differ
only in the identity. That reasoning is what shipped an unopenable app.

Hardened runtime plus an ad-hoc signature is fatal to Electron. Electron validates
its helper processes' code signature, that validation needs the task port, and
hardened runtime denies it:

  codesign_util.cc] task_name_for_pid: (os/kern) failure (5)

The evidence is a pair of flag sets on one machine. The release was
flags=0x10002(adhoc,runtime) and would not start. The dev build, which runs
perfectly and has all along, is flags=0x20002(adhoc,linker-signed) — the same
ad-hoc signature without hardened runtime.

Hardened runtime is mandatory for notarization and buys nothing without a real
identity, so it belongs on the signed path only, where it already is. TCC is
unaffected: grants key to a stable signature, which this still produces, not to
hardened runtime.

The step now also fails the build if the flag turns up anyway, because the
symptom of getting this wrong is a green release that nobody can open — which is
exactly how it shipped the first time.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@dallasbpeters
dallasbpeters merged commit 1840038 into main Aug 24, 2026
13 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant