Bug
Since 26.15.0, the macOS zip target no longer preserves the symlink farm inside .framework bundles. After the zip is extracted (by Squirrel.Mac during auto-update, or plain ditto -x -k), frameworks such as Electron Framework.framework / Mantle.framework end up with a real directory where Versions/Current should be a symlink. codesign then rejects the whole app:
<App>.app: bundle format is ambiguous (could be app or framework)
In subcomponent: .../Contents/Frameworks/<Some>.framework
This is errSecCSBadBundleFormat. In practice it breaks electron-updater / Squirrel.Mac auto-update: the downloaded update fails code-signature validation and never installs. The on-disk (--dir) bundle is fine — only the zip round-trip is affected, which is exactly the path auto-update uses.
Minimal reproduction
👉 https://github.com/arvinxx/electron-builder-mac-zip-symlink-repro
git clone https://github.com/arvinxx/electron-builder-mac-zip-symlink-repro
cd electron-builder-mac-zip-symlink-repro
npm install
./repro.sh # builds the zip target with 26.14.0 (good) then 26.15.0 (bad)
The script builds the zip target unsigned (mac.identity: null), extracts it with ditto, and ad-hoc deep-signs the result so codesign classifies the structure exactly as Squirrel.Mac would. No Developer ID certificate is required.
Observed
|
electron-builder 26.14.0 |
electron-builder 26.15.0 |
| zip packer |
ditto |
7zip (downloads 7zip-darwin-arm64) |
| zip size (same app) |
~113 MB |
~321 MB |
Versions/Current after extract |
symlink ✅ |
real dir ❌ |
codesign on extracted app |
PASS |
bundle format is ambiguous |
================= electron-builder@26.14.0 =================
zip size: 113M
Versions/Current is a symlink: yes
>>> RESULT 26.14.0: PASS — valid, re-extractable bundle
================= electron-builder@26.15.0 =================
zip size: 321M
Versions/Current is a symlink: NO (framework structure broken)
EbZipRepro.app: bundle format is ambiguous (could be app or framework)
In subcomponent: .../Contents/Frameworks/Mantle.framework
>>> RESULT 26.15.0: FAIL — codesign rejected
Expected
The macOS zip target should preserve .framework Versions/Current symlinks so the extracted app passes codesign --verify --deep --strict and Squirrel.Mac can validate the update (as 26.14.0 and earlier do).
Suspected cause
The app-builder-bin Go→TS migration (#9829, shipped in 26.15.0) appears to have switched the macOS zip packer to 7zip, which doesn't preserve framework version symlinks the way ditto does. The ~2.8× zip-size increase is consistent with symlinked framework versions being dereferenced (content duplicated). 26.15.1 does not fix it (its only macOS-touching change, #9838, is a lint/refactor).
Environment
- electron-builder: 26.15.0 / 26.15.1 (regression); 26.14.0 OK
- electron: 41.3.0
- macOS arm64
Bug
Since 26.15.0, the macOS
ziptarget no longer preserves the symlink farm inside.frameworkbundles. After the zip is extracted (by Squirrel.Mac during auto-update, or plainditto -x -k), frameworks such asElectron Framework.framework/Mantle.frameworkend up with a real directory whereVersions/Currentshould be a symlink.codesignthen rejects the whole app:This is
errSecCSBadBundleFormat. In practice it breakselectron-updater/ Squirrel.Mac auto-update: the downloaded update fails code-signature validation and never installs. The on-disk (--dir) bundle is fine — only the zip round-trip is affected, which is exactly the path auto-update uses.Minimal reproduction
👉 https://github.com/arvinxx/electron-builder-mac-zip-symlink-repro
The script builds the
ziptarget unsigned (mac.identity: null), extracts it withditto, and ad-hoc deep-signs the result socodesignclassifies the structure exactly as Squirrel.Mac would. No Developer ID certificate is required.Observed
ditto7zip(downloads7zip-darwin-arm64)Versions/Currentafter extractcodesignon extracted appbundle format is ambiguousExpected
The macOS
ziptarget should preserve.frameworkVersions/Currentsymlinks so the extracted app passescodesign --verify --deep --strictand Squirrel.Mac can validate the update (as 26.14.0 and earlier do).Suspected cause
The app-builder-bin Go→TS migration (#9829, shipped in 26.15.0) appears to have switched the macOS
zippacker to 7zip, which doesn't preserve framework version symlinks the waydittodoes. The ~2.8× zip-size increase is consistent with symlinked framework versions being dereferenced (content duplicated). 26.15.1 does not fix it (its only macOS-touching change, #9838, is a lint/refactor).Environment