electron / electron/packager

[macOS] Universal build fails because arm64 app is ad-hoc signed while x64 app is unsigned when osxSign is undefined

Open
#1,952 0 comments 0 reactions 0 assignees View on GitHub
bug :bug:
Dominant language
TypeScript
Stars
302
Forks
42
Avg merge
5h 40m
Merged PRs (30d)
7

Description

### Preflight Checklist

* [X] I have read the [contribution documentation](https://github.com/electron/packager/blob/main/CONTRIBUTING.md) for this project.
* [X] I agree to follow the [code of conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project follows, as appropriate.
* [X] I have searched the issue tracker for a bug that matches the one I want to file, without success.

### Issue Details

* **Electron Packager Version:**
* 18.4.4
* **Electron Forge Version:**
* 7.11.2
* **Electron Version:**
* 43.2.0
* **Operating System:**
* macOS Sequoia (Apple Silicon / arm64)
* **Last Known Working Electron Packager version:**:
* Unknown

### Expected Behavior

When building a universal macOS application with:

```ts
packagerConfig: {
osxUniversal: {
x64ArchFiles: "**/Resources/backend/**",
},
osxSign: undefined,
}
```

I would expect no code signing to occur at all as explained in [Electron Packager documentation](https://deepwiki.com/electron/packager/7.2-universal-macos-binaries#signing-and-notarization).

Both architecture-specific bundles should therefore be generated in the same state:

```text
arm64.app => unsigned
x64.app => unsigned
```

Alternatively, if ad-hoc signing is intentionally applied automatically by Electron Packager, I would expect it to be applied consistently to both architectures.

### Actual Behavior

When:

```ts
osxSign: undefined
```

the generated application bundles have different signing states.

The arm64 application bundle is ad-hoc signed:

```bash
codesign -dv MyApp-darwin-arm64/MyApp.app
```

returns:

```text
Signature=adhoc
```

while the x64 application bundle is not signed:

```bash
codesign -dv MyApp-darwin-x64/MyApp.app
```

returns:

```text
code object is not signed at all
```

As a result, the arm64 bundle contains `_CodeSignature` resources that are not present in the x64 bundle.

The universal merge then fails with:

```text
uniqueToX64: [],
uniqueToArm64: [
'Contents/Frameworks/Electron Framework.framework/Versions/A/_CodeSignature/CodeResources',
'Contents/Frameworks/Mantle.framework/Versions/A/_CodeSignature/CodeResources',
'Contents/Frameworks/ReactiveObjC.framework/Versions/A/_CodeSignature/CodeResources',
'Contents/Frameworks/Squirrel.framework/Versions/A/_CodeSignature/CodeResources',
'Contents/Frameworks/MyApp Helper (GPU).app/Contents/_CodeSignature/CodeResources',
'Contents/Frameworks/MyApp Helper (Plugin).app/Contents/_CodeSignature/CodeResources',
'Contents/Frameworks/MyApp Helper (Renderer).app/Contents/_CodeSignature/CodeResources',
'Contents/Frameworks/MyApp Helper.app/Contents/_CodeSignature/CodeResources',
'Contents/_CodeSignature/CodeResources'
]
```

followed by:

```text
Error: While trying to merge mach-o files across your apps we found a mismatch,
the number of mach-o files is not the same between the arm64 and x64 builds
```

### To Reproduce

Configuration:

```ts
packagerConfig: {
osxUniversal: {
x64ArchFiles: "**/Resources/backend/**",
},
osxSign: undefined,
}
```

Build a universal application on an Apple Silicon Mac:

```bash
electron-forge package --platform=darwin --arch=universal
```

Inspect the generated architecture-specific application bundles:

```bash
codesign -dv MyApp-darwin-arm64/MyApp.app
codesign -dv MyApp-darwin-x64/MyApp.app
```

Observed result:

```text
arm64.app => Signature=adhoc
x64.app => code object is not signed at all
```

The universal merge then fails because `_CodeSignature` resources exist only in the arm64 bundle.

### Additional Information

I initially suspected `@electron/universal`, but reproduced the issue with both:

- `@electron/universal@2.0.3`
- `@electron/universal@3.0.6`

The behavior is identical with both versions.

I also removed all makers (including `MakerPKG`) and replaced them with a dummy maker. The behavior remained unchanged.

This indicates that the inconsistency is introduced before the maker phase, during packaging.

As a workaround, the following configuration succeeds:

```ts
osxSign: {
identity: "-",
identityValidation: false,
}
```

With this configuration:

```text
arm64.app => ad-hoc signed
x64.app => ad-hoc signed
```

and the universal stitching succeeds.

I also verified that manually ad-hoc signing the generated x64 application before performing the universal merge allows the merge to complete successfully:

```bash
codesign --force --deep --sign -
```

This suggests that the root cause is the asymmetric signing state of the arm64 and x64 bundles when `osxSign` is undefined.

Contributor guide

Open the contributing guide

Research direction

Reproduce the issue with the shown packagerConfig and `electron-forge package --platform=darwin --arch=universal`, then inspect the architecture-specific bundles with `codesign -dv`. Trace the packaging and universal merge paths to determine why `osxSign: undefined` produces different signing states; done means both bundles have the same state and the universal merge succeeds.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, typescript
Domain
build-system, desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.