mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-27 11:22:03 +00:00
fix(desktop): ad-hoc sign macOS self-update rebuilds
The desktop self-updater rebuilds and re-signs the .app on each user's own machine (`hermes desktop --build-only` -> electron-builder `--dir`). With CSC_IDENTITY_AUTO_DISCOVERY on (its default), electron-builder signs the type=distribution, hardened-runtime bundle with whatever identity is in that user's keychain -- typically a personal "Apple Development" cert -- which stalls/fails the sign step (no Developer ID, no provisioning profile) or clobbers the original notarized signature with an unusable one, tripping Gatekeeper on every post-update launch. Force ad-hoc signing for the local packaged rebuild instead: deterministic, and exactly what _desktop_macos_relaunchable_fixup already finishes off. No-op for source runs, off-macOS, when a real identity is configured (CSC_LINK / APPLE_SIGNING_IDENTITY), or when the caller already pinned the flag.
This commit is contained in:
parent
a6a28ce3e2
commit
1d9ed7f48a
2 changed files with 68 additions and 0 deletions
|
|
@ -5404,6 +5404,34 @@ def _desktop_macos_relaunchable_fixup(desktop_dir: Path) -> None:
|
|||
print(f" (warning: macOS relaunch fixup skipped: {exc})")
|
||||
|
||||
|
||||
def _force_adhoc_macos_signing(env: dict, *, source_mode: bool) -> bool:
|
||||
"""Stop electron-builder grabbing a random keychain identity on self-update.
|
||||
|
||||
The desktop self-updater rebuilds *and re-signs the .app on the end user's
|
||||
machine* (``hermes desktop --build-only`` → electron-builder ``--dir``).
|
||||
With ``CSC_IDENTITY_AUTO_DISCOVERY`` on (its default), electron-builder
|
||||
signs the ``type=distribution``, hardened-runtime bundle with whatever it
|
||||
finds in that user's keychain — typically a personal "Apple Development"
|
||||
cert. That stalls/fails the sign step (no Developer ID + no provisioning
|
||||
profile) or clobbers your real notarized signature with an unusable one, so
|
||||
every post-update launch trips Gatekeeper.
|
||||
|
||||
Force ad-hoc signing for the local packaged rebuild instead: deterministic,
|
||||
and exactly what ``_desktop_macos_relaunchable_fixup`` already finishes off.
|
||||
No-op for source runs, off-macOS, when a real identity is configured
|
||||
(``CSC_LINK`` / ``APPLE_SIGNING_IDENTITY``), or when the caller already
|
||||
pinned the flag. Mutates ``env``; returns True when it set the flag.
|
||||
"""
|
||||
if sys.platform != "darwin" or source_mode:
|
||||
return False
|
||||
if env.get("CSC_LINK") or env.get("APPLE_SIGNING_IDENTITY"):
|
||||
return False
|
||||
if "CSC_IDENTITY_AUTO_DISCOVERY" in env:
|
||||
return False
|
||||
env["CSC_IDENTITY_AUTO_DISCOVERY"] = "false"
|
||||
return True
|
||||
|
||||
|
||||
def _desktop_linux_sandbox_fixup(packaged_executable: Path) -> bool:
|
||||
"""Configure Electron's Linux SUID sandbox helper when required."""
|
||||
if sys.platform != "linux":
|
||||
|
|
@ -5535,6 +5563,9 @@ def cmd_gui(args: argparse.Namespace):
|
|||
build_label = "source build" if source_mode else "packaged app"
|
||||
print(f"→ Building desktop {build_label}...")
|
||||
build_script = "build" if source_mode else "pack"
|
||||
if _force_adhoc_macos_signing(env, source_mode=source_mode):
|
||||
print(" → No Developer ID configured; ad-hoc signing this local rebuild "
|
||||
"(CSC_IDENTITY_AUTO_DISCOVERY=false)")
|
||||
if not source_mode:
|
||||
# A running desktop instance launched from release/win-unpacked
|
||||
# holds Hermes.exe locked on Windows, so the pack can't replace
|
||||
|
|
|
|||
|
|
@ -877,3 +877,40 @@ def test_stop_desktop_build_lock_no_release_dir(tmp_path, monkeypatch):
|
|||
with patch("psutil.process_iter") as it:
|
||||
assert cli_main._stop_desktop_processes_locking_build(desktop_dir) == []
|
||||
it.assert_not_called()
|
||||
|
||||
|
||||
def test_force_adhoc_signing_disables_discovery_on_local_packaged_rebuild(monkeypatch):
|
||||
monkeypatch.setattr(cli_main.sys, "platform", "darwin")
|
||||
env = {}
|
||||
assert cli_main._force_adhoc_macos_signing(env, source_mode=False) is True
|
||||
assert env["CSC_IDENTITY_AUTO_DISCOVERY"] == "false"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("platform", ["linux", "win32"])
|
||||
def test_force_adhoc_signing_noop_off_macos(monkeypatch, platform):
|
||||
monkeypatch.setattr(cli_main.sys, "platform", platform)
|
||||
env = {}
|
||||
assert cli_main._force_adhoc_macos_signing(env, source_mode=False) is False
|
||||
assert "CSC_IDENTITY_AUTO_DISCOVERY" not in env
|
||||
|
||||
|
||||
def test_force_adhoc_signing_noop_for_source_mode(monkeypatch):
|
||||
monkeypatch.setattr(cli_main.sys, "platform", "darwin")
|
||||
env = {}
|
||||
assert cli_main._force_adhoc_macos_signing(env, source_mode=True) is False
|
||||
assert "CSC_IDENTITY_AUTO_DISCOVERY" not in env
|
||||
|
||||
|
||||
@pytest.mark.parametrize("key", ["CSC_LINK", "APPLE_SIGNING_IDENTITY"])
|
||||
def test_force_adhoc_signing_preserves_real_identity(monkeypatch, key):
|
||||
monkeypatch.setattr(cli_main.sys, "platform", "darwin")
|
||||
env = {key: "secret"}
|
||||
assert cli_main._force_adhoc_macos_signing(env, source_mode=False) is False
|
||||
assert "CSC_IDENTITY_AUTO_DISCOVERY" not in env
|
||||
|
||||
|
||||
def test_force_adhoc_signing_respects_explicit_caller_flag(monkeypatch):
|
||||
monkeypatch.setattr(cli_main.sys, "platform", "darwin")
|
||||
env = {"CSC_IDENTITY_AUTO_DISCOVERY": "true"}
|
||||
assert cli_main._force_adhoc_macos_signing(env, source_mode=False) is False
|
||||
assert env["CSC_IDENTITY_AUTO_DISCOVERY"] == "true"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue