fix(desktop): refuse hardened-runtime sign when entitlement plists are missing

Hardened-runtime restrictions are enforced even for ad-hoc signatures,
so signing with --options runtime without the allow-jit entitlements
would leave Electron/V8 crashing on launch — strictly worse than the
legacy plain ad-hoc sign. Raise instead, so the fixup falls back to the
legacy path and the bundle always stays launchable.
This commit is contained in:
Brooklyn Nicholson 2026-07-28 17:34:43 -05:00
parent bc1c168d49
commit 812b75fdfc
2 changed files with 27 additions and 0 deletions

View file

@ -6475,6 +6475,15 @@ def _desktop_macos_local_codesign(
ent_main = desktop_dir / "electron" / "entitlements.mac.plist"
ent_inherit = desktop_dir / "electron" / "entitlements.mac.inherit.plist"
if not (ent_main.exists() and ent_inherit.exists()):
# Hardened-runtime restrictions are enforced even for ad-hoc
# signatures. Signing with --options runtime but WITHOUT the allow-jit
# entitlements would leave Electron/V8 crashing on launch — strictly
# worse than the legacy plain ad-hoc sign. Bail out so the caller
# falls back to that legacy path instead.
raise FileNotFoundError(
f"desktop entitlement plists missing under {desktop_dir / 'electron'}"
)
def sign_path(
path: Path,

View file

@ -1170,6 +1170,24 @@ def test_desktop_macos_local_codesign_false_without_codesign(tmp_path, monkeypat
assert cli_main._desktop_macos_local_codesign(app, desktop_dir=desktop_dir) is False
def test_desktop_macos_local_codesign_refuses_without_entitlements(tmp_path, monkeypatch):
"""Hardened runtime without allow-jit bricks Electron — must raise, not sign.
Hardened-runtime restrictions are enforced even for ad-hoc signatures, so
signing with --options runtime while the entitlement plists are missing
would produce a bundle that crashes on launch. The fixup catches the raise
and falls back to the legacy plain ad-hoc sign instead.
"""
desktop_dir = tmp_path / "apps" / "desktop"
app = _make_signable_app(desktop_dir)
(desktop_dir / "electron" / "entitlements.mac.plist").unlink()
calls = _collect_codesign_calls(monkeypatch)
with pytest.raises(FileNotFoundError):
cli_main._desktop_macos_local_codesign(app, desktop_dir=desktop_dir)
assert calls == [] # nothing was signed with a runtime flag sans entitlements
def test_relaunchable_fixup_noop_when_publisher_signing_configured(tmp_path, monkeypatch):
root = _make_desktop_tree(tmp_path)
monkeypatch.setattr(cli_main, "PROJECT_ROOT", root)