Skip to content

emrg: upgrade prompt: re-seal GUI bundle + clear xattrs before deploy (Gatekeeper quarantine fix) - #968

Merged
argszero merged 1 commit into
masterfrom
feature/upgrade-gui-resign-xattr
Aug 25, 2026
Merged

emrg: upgrade prompt: re-seal GUI bundle + clear xattrs before deploy (Gatekeeper quarantine fix)#968
argszero merged 1 commit into
masterfrom
feature/upgrade-gui-resign-xattr

Conversation

@argszero

Copy link
Copy Markdown
Owner

Fixes the macOS Gatekeeper quarantine of EMRG.app during auto-upgrade (rant 2026-08-25T09:18:19).

Problem: After the v0.2.77 upgrade, ~/Applications/EMRG.app was judged malware and moved to Trash ("已阻止恶意软件并移到废纸篓"). Root causes (host-verified):

  1. electron-builder dir output only ad-hoc signs the main binary — the bundle is unsealed (codesign -d shows Identifier=Electron, Info.plist=not bound, Sealed Resources=none; codesign --verify --deep --strict fails with "code has no resources but signature indicates they must be present").
  2. The deployed copy carries xattrs (e.g. com.apple.provenance).
  3. macOS 26 treats provenance/quarantine attributes combined with an invalid signature as malware.

Fix (in emrg/server/prompts/upgrade_prompt.j2):

  • New mandatory step 3c: after the GUI build, re-seal the bundle with codesign --force --deep --sign - --timestamp=none (full ad-hoc re-sign → Identifier=com.emrg.gui, sealed resources present) and clear xattrs with xattr -cr on the built artifact BEFORE any copy; sanity-check with codesign --verify --deep --strict (fail → do not copy, roll back).
  • Step 4: also clear xattrs on the run copy ~/Applications/EMRG.app (ditto preserves source attributes).
  • Step 5: add mandatory codesign --verify --deep --strict on both deployed copies; any failure = upgrade failure → restore from backup. Log the signature verification result (acceptance: upgrade log must show it).
  • Step 6: clarify the safety boundary — Developer ID signing/notarization stays release-side; local ad-hoc re-signing is required, not a substitute.

Verification: upgrade_prompt.j2 renders (Jinja2 smoke test, contains the new steps); uv run pytest tests/ -q → 1050 passed / 1 skipped; from emrg.client.app import run_client + python -m emrg --help OK.

Acceptance: next upgrade with a GUI update deploys an EMRG.app that opens normally (no Gatekeeper interception), and the upgrade log records the signature verification pass.

… so Gatekeeper does not quarantine (rant 2026-08-25T09:18:19)

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle

Re-verified against the rant (2026-08-25T09:18:19) acceptance items:

  • Built artifact is re-sealed with codesign --force --deep --sign - --timestamp=none (full ad-hoc re-sign → Identifier=com.emrg.gui, sealed resources) and xattr-cleared with xattr -cr BEFORE any copy (step 3c).
  • Run copy ~/Applications/EMRG.app also xattr-cleared (ditto propagates source attributes).
  • Verify step requires codesign --verify --deep --strict to pass on both deployed copies; any failure = upgrade failure → rollback; result logged.
  • Safety boundary clarified: Developer ID signing/notarization stays release-side; ad-hoc re-sign is required for macOS 26 Gatekeeper compatibility, not a substitute.
  • CI: test + test-windows both green (run 32799507262). Local pytest 1050 passed / 1 skipped; template renders.

Merging this unblocks the acceptance item: next GUI-including upgrade deploys a sealed, xattr-clean EMRG.app that Gatekeeper accepts.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle (2/3)

Re-checked this cycle: head 6e92db6 unchanged, CI test + test-windows still green (run 32799507262). The four acceptance items of rant 2026-08-25T09:18:19 are all addressed:

  1. Built artifact re-sealed (codesign --force --deep --sign - --timestamp=none) + xattr-cleared (xattr -cr) before copy — step 3c.
  2. Run copy ~/Applications/EMRG.app xattr-cleared after ditto — step 4.
  3. codesign --verify --deep --strict mandatory on both copies, failure → rollback + log — step 5.
  4. Safety boundary clarified (Developer ID/notarization stays release-side).

No issues found; ready to merge once the 3rd LGTM lands.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle (3/3)

Final re-check: head 6e92db6 unchanged, CI test + test-windows green (run 32799507262), MERGEABLE. Three consecutive LGTMs from distinct cycles (100311, 101045, 101729) with no ❌. Rant 2026-08-25T09:18:19 acceptance items all covered — merging.

@argszero
argszero merged commit 1ae4630 into masterAug 25, 2026
2 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@argszero