Repository navigation
Conversation
Astro-Han
left a comment
There was a problem hiding this comment.
Automated review notice: This comment was posted by an automated review agent. It is not an independent human review and does not replace one.
Reviewed range: merge-base 6fa4851 (main) to head 59e615a, 2 commits, 9 files, +408/-7. This is a first review, so there are no prior findings.
Verdict: I found no P0-P2 defects. Three P3 notes are below.
What I verified
- Hook order. In the pinned electron-builder 26.17.0,
platformPackager.doPackruns the configafterPack, then the sanity check, thendoAddElectronFuses, thendoSignAfterPack. The stamped executables are what get signed (hardened runtime, Developer ID) and notarized, so the byte edit doesn't break the signature. - No unsigned arm64 output. Electron's stock arm64 executable is only linker-signed, and rewriting LC_UUID invalidates that signature. If electron-builder ever skipped signing afterwards, the result would be an arm64 app the kernel kills at launch. The mac config sets
forceCodeSigning: true, so a missing identity (reportError) oridentity: null(handleNullIdentity) fails the build instead. The ad-hocidentity: '-'path still signs. I don't see a supported path that ships a stamped, unsigned binary. - Fuses don't overlap. Fuses are flipped in
Electron Framework, which this hook doesn't touch. - Parser. It handles thin MH_MAGIC_64 and FAT_MAGIC 32-bit fat headers. It replaces the 16 UUID bytes in place, keeps the file length, and is idempotent. Out-of-range reads throw. FAT_MAGIC_64 isn't handled, but nothing ships it, so there is no impact.
- UUID derivation. The UUID is UUIDv5-style SHA-1 over a fixed namespace plus
appId/executable/cputype.appIdcomes frompackager.appInfo.id(com.maka.desktop) when stamping. The verifier reads it fromCFBundleIdentifierafter asserting it matches the expected id, so both sides agree. Nightly and formal share the app id, so they share UUIDs. That matches the documented "same application identity" policy. - Verifier coverage.
verify:macoscallsassertMacAppExecutableUuidsbeforecodesign --verify, so a hook that stops running fails the release check. - No crash-symbolication cost. No
crashReporter/Sentry/dSYM pipeline exists in the repo, so moving away from Electron's published UUIDs costs nothing there. - Supply chain and signing. There are no new dependencies and no lockfile change. No
.github/workflowsfiles changed. No signing secrets, entitlements or notarization settings were touched. The only supply-chain-relevant effect is intended: the shipped main and helper executables are no longer byte-identical to upstream Electron's prebuilt binaries. They differ only in the 16 LC_UUID bytes per slice, before signing. I found no release check that compares Desktop Mach-O bytes against upstream Electron. The RELEASE.json Mach-O inventory covers the CLI ZIP only.
Findings
- P3 (CI coverage). PR CI does not exercise the macOS change.
- The CI
testjob runscheck:releaseon ubuntu-24.04. There, the real-Electron test (rewrites the UUID of Electron's own executable) is skipped, and only the synthetic-buffer tests run. - The
packagecheck on this PR is the Windows release check. There the hook only proves it returns early off darwin. - The
owner (macos-latest)job is the Runtime Host owner-platform check and does not package the Desktop app. - The first real run of the hook is post-merge, in the signed Desktop Nightly on
macos-15(arm64) andmacos-15-intel(x64), followed byverify:macos. A failure there blocks the nightly rather than shipping a bad build. - The x64 path, and the full signed and notarized flow on either arch, have not been run by anyone. The PR states this. Please watch the first nightly after merge.
- The CI
- P3 (behavior change worth a release note). Every existing install currently carries Electron 43.4.1's stock UUID. The first update with this change moves Maka to a new, stable UUID. Users will likely see the Local Network prompt once more, and any earlier grant or denial recorded under the stock UUID stays attached to that shared UUID. That is the intended fix, but users should be told about the one-time re-prompt.
- P3 (permanence).
MAKA_EXECUTABLE_UUID_NAMESPACEand theappId/executableName/cputypename format are now a persistent identity contract, likeappId. RenamingproductName(which renames the main and helper executables) or changing the format re-keys every user's Local Network decision. The comment covers the namespace, but nothing pins the derived values. A golden-value test, for example the expected UUID forcom.maka.desktop/Maka/arm64, would catch an accidental change.
Protocol/epoch: No protocol files are touched, so there is no epoch impact.
Mergeability/CI: GitHub reports MERGEABLE, with merge state BLOCKED (awaiting required review). All six checks on 59e615a pass: audit, owner (macos-latest), owner (windows-latest), package (Release Windows check), package-linux, and test. The Windows test inventory was updated for the new darwin-only test, and Check Windows test inventory passes.
| artifactName: 'Maka-${version}-mac-${arch}.${ext}', | ||
| asar: true, | ||
| beforePack: stageReleaseManifests, | ||
| afterPack: stampMacExecutableUuids, |
There was a problem hiding this comment.
P3 note: I verified that in electron-builder 26.17.0 the config afterPack runs before fuses and doSignAfterPack, and mac.forceCodeSigning: true prevents an unsigned (linker-signature-invalidated) arm64 build. PR CI never runs this hook on macOS, though. The first real run is the post-merge signed Desktop Nightly (macos-15 / macos-15-intel), so please watch that run.
|
|
||
| // Fixed namespace for the UUIDv5 names below. Changing it changes every | ||
| // shipped UUID, which macOS treats as a different program. | ||
| const MAKA_EXECUTABLE_UUID_NAMESPACE = Buffer.from('4195730630d44e84a842a14db6f67a8f', 'hex'); |
There was a problem hiding this comment.
P3: this namespace and the appId/executableName/cputype name format are now a persistent identity contract, as is productName, because it names the executables. Consider a golden-value test, for example the expected UUID for com.maka.desktop/Maka/arm64, so a refactor can't silently re-key users' Local Network decisions.
Astro-Han
left a comment
There was a problem hiding this comment.
Automated review notice: This comment was posted by an automated review agent. It is not an independent human review and does not replace one.
Reviewed head 59e615a96c758bf7a8e0a1e4379c4f37dadf3267 against merge-base 6fa48516106b4e2de591aea4a96a538425c8aafa: 2 commits, 9 files, +408/-7.
I found no verified P0–P2 defect. This does not establish that the macOS permission behavior has been validated.
The installed app-builder-lib 26.17.0 invokes afterPack before fuses and signing. The normal macOS release wrapper requires signing/notarization credentials, and forceCodeSigning rejects a missing identity or explicit identity: null. I did not find a supported production path that ships the edited executable without re-signing. The actual configuration hook stamps the main and helper executables in a synthetic Darwin bundle and is a no-op off Darwin. The verifier uses the bundle identifier after checking its expected value. Nightly and formal builds share that identifier.
Earlier review notes: the missing signed/notarized macOS release evidence remains a P3 follow-up (apps/desktop/electron-builder.config.mjs:87, scripts/macos-executable-uuid.test.mjs:156). The author reports an ad-hoc-signed arm64 launch, not a full release. A golden-value UUID test is still useful. However, changing a UUID has not by itself been shown to reset every user's permission or produce a one-time re-prompt: Apple's current guidance also identifies applications through code signatures. Please present those consequences as unverified until tested. Apple TN3179
Two additional P3 follow-ups:
scripts/macos-executable-uuid.mjs:48: the derivation discards native-build identity. Different native payloads and upstream UUIDs receive the same stamped UUID for a fixed app/name/CPU. Apple's build-UUID guidance distinguishes different native images for symbol matching. Please retain build-specific identity in the derivation, or explain and validate the deliberate tradeoff. The absence of a repository crash-upload pipeline does not establish that OS crash reports or external symbol matching have no cost. I have not reproduced an application crash or a Local Network regression, so this is not a P2 claim. Apple TN3178scripts/macos-executable-uuid.mjs:65: a FAT header with zero slices produces an empty UUID list, and the UUID assertion accepts a helper containing only that header. AnLC_UUIDwithcmdsize=8is also accepted and stamped. Reject empty/out-of-bounds slice tables and require a complete 24-byte UUID command inside its declared slice/load-command region. These are malformed-input hardening cases, not a demonstrated bypass of subsequent signature, Gatekeeper or launch checks.
Local verification: Core, Storage, MCP and Runtime builds passed; the five changed/related script suites passed 98 tests with 1 macOS-only skip; Windows inventory passed 3 tests and is current at 121 declarations; scoped Biome and diff whitespace checks passed. An additional probe exercised the actual configuration hook, the native-image UUID collision and malformed helper acceptance. I ran these on Linux, not macOS. I did not execute Developer ID signing, notarization, Gatekeeper assessment, a DMG launch, or before/after-update Local Network grant/deny tests. Both supported architectures still need real release evidence.
No protocol files change; there is no compatibility-epoch impact.
All six checks on this exact head are successful, including CI. The macOS check tests the Runtime Host local-deployment owner, not Desktop packaging. The PR is now CONFLICTING/DIRTY against main c11a5336b; a read-only merge confirms the sole conflict is docs/windows-test-inventory.md. Rebase, regenerate that inventory and rerun checks before merging. Earlier MERGEABLE evidence is no longer current.
| * the CPU type keeps the arm64 and x64 builds apart. | ||
| */ | ||
| export function expectedExecutableUuid({ appId, executableName, cputype }) { | ||
| const digest = createHash('sha1') |
There was a problem hiding this comment.
[P3] Preserve native-build identity, or validate the deliberate loss of it. Two different native payloads/upstream UUIDs currently get the same output UUID for the same app/name/CPU. Apple's TN3178 distinguishes native images for symbol matching. There is no repository crash-upload pipeline, but that does not eliminate OS crash-report or external-symbol costs. I have not reproduced an application failure; this is a follow-up tradeoff, not a P2 regression claim.
|
|
||
| function sliceOffsets(binary) { | ||
| if (binary.length >= 4 && binary.readUInt32BE(0) === FAT_MAGIC) { | ||
| const count = binary.readUInt32BE(4); |
There was a problem hiding this comment.
[P3] Reject empty or malformed slices before treating the UUID check as successful. Buffer.from('cafebabe00000000', 'hex') yields [], so assertMacAppExecutableUuids accepts a helper containing only this zero-slice header. The parser also accepts an LC_UUID declaring cmdsize=8 and writes past that declared command. Require a nonempty bounded fat table, bounded slices/load commands, and a full 24-byte UUID command; add negative tests. Later codesign/Gatekeeper/launch checks remain, so this is parser hardening, not a demonstrated invalid-release bypass.
electron-builder ships Electron's prebuilt executables renamed but not relinked, so Maka's main executable and helpers carried Electron 43.4.1's stock Mach-O LC_UUID, shared with every other app on that Electron release. macOS Local Network Privacy identifies a program by that UUID, so another app's grant or denial could apply to Maka. An afterPack hook now stamps each executable, before signing, with a UUIDv5 derived from the app id, executable name and CPU type: unique to Maka, stable across releases so a user's decision survives updates. The macOS release verifier fails a package whose executables lack the stamp. Generated-by: Claude Code (Claude Opus 5.5) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Generated-by: Claude Code (Claude Opus 5.5) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reject a universal header with no slices or out-of-file slices, load commands outside sizeofcmds, and an LC_UUID whose cmdsize is not 24, so the release check can no longer pass an executable it did not read. A golden-value test pins the derived UUID, which is now part of the shipped identity. The rationale comment cites TN3178 and no longer claims a fixed UUID preserves Local Network decisions; TN3179 says those follow the code signature. Generated-by: Claude Code (Claude Opus 5.5) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
59e615a to
43054f8
Compare
Summary
electron-builder renames Electron's prebuilt executables without relinking them, so
Makaand its four helpers shipped Electron 43.4.1's stock Mach-OLC_UUID. Every other app on that Electron release has the same UUID. macOS Local Network Privacy identifies a program by that UUID, so a grant or denial for another app could apply to Maka. Details and a real collision are in the issue.afterPackhook (scripts/macos-executable-uuid.mjs). It rewrites theLC_UUIDof the main executable and every helper app before signing, so the stamped binaries are what electron-builder signs and notarizes.appId/executable name/CPU type. It is deterministic rather than random, so the UUID stays the same across releases and a user's Local Network decision survives updates. arm64 and x64 builds get different UUIDs.verify:macosnow rejects a package whose executables lack the expected UUID, so a hook that stops running fails the release check instead of shipping the stock UUID.darwin.Fixes #6026
Verification
node --test scripts/macos-executable-uuid.test.mjs: 12 passing. Covers synthetic thin and fat Mach-O, idempotence, rejection of the stock UUID, and Electron's real arm64 executable on macOS.node --test scripts/verify-packaged-app.test.mjs scripts/desktop-nightly.test.mjs scripts/desktop-release-targets.test.mjs scripts/ci-test-plan.test.mjs scripts/macos-executable-uuid.test.mjs: 99/99 passing.biome lint .,biome format .andknip --workspace apps/desktopare clean.electron-builder --mac dir --arm64(ad-hoc signed, not notarized):dwarfdump --uuidshows all five executables with new UUIDs. The main executable went from4C4C4470-5555-3144-A124-518576DD11E3toE08E3A84-68A1-5189-9663-A4FEC17A5EE5.codesign --verify --deep --strictpasses.package:macos-*/verify:macos, which needs the release signing credentials.AI use
Select exactly one:
Tool(s) and scope: Claude Code (Claude Opus 5.5) did the investigation, implementation and tests. A human reviewed the change. The commit carries a
Generated-bytrailer.Checklist
Does this PR entail a change in behavior?
🤖 Generated with Claude Code