Skip to content

macOS zip target dereferences .framework symlinks in 26.15.0 → "bundle format is ambiguous" breaks Squirrel.Mac auto-update #9846

@arvinxx

Description

@arvinxx

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions