Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot code-sign compiled executable on macOS #7208

Open
paambaati opened this issue Nov 18, 2023 · 16 comments
Open

Cannot code-sign compiled executable on macOS #7208

paambaati opened this issue Nov 18, 2023 · 16 comments
Labels
bug Something isn't working bundler Something to do with the bundler

Comments

@paambaati
Copy link

What version of Bun is running?

1.0.13+f5bf67bd1

What platform is your computer?

Darwin 23.1.0 arm64 arm

What steps can reproduce the bug?

  1. Build a compiled executable by following https://bun.sh/docs/bundler/executables

  2. Create a self-signed certificate with code-signing capabilities by following https://support.apple.com/en-in/guide/keychain-access/kyca8916/mac

  3. Attempt to code-sign the compiled executable with the command –

    codesign -f -s "Acme Corp" ./mycli --deep
    
  4. See the error –

    ./mycli: replacing existing signature
    ./mycli: main executable failed strict validation
    

What is the expected behavior?

The executable should be code-signed correctly and runnable on the system without Gatekeeper blocks/prompts.

What do you see instead?

./mycli: replacing existing signature
./mycli: main executable failed strict validation

Additional information

FWIW, Deno's compiled binaries face the same issue (although I'm not sure if the root cause is the same) – see denoland/deno#575 and denoland/deno#17753

@paambaati paambaati added the bug Something isn't working label Nov 18, 2023
@paambaati paambaati changed the title Cannot codesign compiled executable on macOS Cannot code-sign compiled executable on macOS Nov 18, 2023
@Electroid Electroid added the bundler Something to do with the bundler label Nov 27, 2023
@YoavCodes
Copy link

//! Originally, we tried using LIEF to inject the module graph into a MachO segment
//! But this incurred a fixed 350ms overhead on every build, which is unacceptable
//! so we give up on codesigning support on macOS for now until we can find a better solution

👀

If it's possible to only incur the 350ms fixed build time increase when I pass in a --makeCodesignable flag or something I think that'd be a good solution (as apposed to finding a more performant solution).

@pauldvu
Copy link

pauldvu commented Jun 10, 2024

//! Originally, we tried using LIEF to inject the module graph into a MachO segment
//! But this incurred a fixed 350ms overhead on every build, which is unacceptable
//! so we give up on codesigning support on macOS for now until we can find a better solution

👀
If it's possible to only incur the 350ms fixed build time increase when I pass in a --makeCodesignable flag or something I think that'd be a good solution (as apposed to finding a more performant solution).

I agree a flag would be amazing, currently can't ship bun desktop applications without signing

@paambaati
Copy link
Author

@Electroid @Jarred-Sumner FWIW, Deno has landed support for codesigning Windows and macOS executables in denoland/deno#24604 and it is expected to land in Deno 1.46.

@ctjlewis
Copy link

ctjlewis commented Sep 2, 2024

cc @Jarred-Sumner - we cannot ship binaries to Mac ecosystem yet.

@ctjlewis
Copy link

ctjlewis commented Sep 2, 2024

We get:

$ codesign --force --sign ... compiled.bin

main executable failed strict validation

The most we have by way of actual documentation from Apple is from Technical Note TN2206: macOS Code Signing In Depth.

codesign says my main executable failed strict validation.

  • Your Mach-O executable does not conform to modern Mach-O layout rules.
  • You may be using a third party development product that hasn't been brought up to date, or post-processed your file in unsupported ways.

@codenoid
Copy link

codenoid commented Sep 13, 2024

ah, It's not just me, gotta try Deno I guess

edit: Deno single executable was worse

@edvald
Copy link

edvald commented Sep 18, 2024

This is pretty much a hard requirement for us, and we'd happily take a 350ms hit on build time, especially if it can be toggled only for distribution builds.

@edvald
Copy link

edvald commented Sep 18, 2024

Btw, Bun team, if you can provide some guidance as to what you tried previously (as per your code comment) we could potentially contribute something along the lines of what @YoavCodes suggested.

@YoavCodes
Copy link

YoavCodes commented Sep 18, 2024

for what it's worth in the meantime while building https://www.electrobun.dev I implemented code signing on mac. but it essentially builds a mac application bundle (ie: folder) and code signs/notarizes your bundle which includes the bun binary and separate bundled js and other binaries.

so creating an app bundle and code signing/notarizing that is a workaround for distributing a "single" code signed thing.

but it'd be nice to be able to compile and sign/notarize a single binary for cli apps and terminal based utilities.

@edvald
Copy link

edvald commented Sep 18, 2024

That's interesting, thanks for sharing @YoavCodes! We'll take a closer look.

But still agreed, I think the CLI tool use-case is broadly important for a tool like this. Bun does a lot of stuff super well, not least in the context of CLIs—faster startup times than alternatives and generally very smooth compilation+bundling, among other things—so it'd be a shame to get blocked on a last-mile thing like this.

It'd be a bit difficult to work it out from scratch, but any notes on prior attempts from the Bun team would be great to help others contribute.

Btw I'd also argue that a fixed 350ms cost is not exactly terrible for binary builds, since a lot of rapid iteration happens without those. At any rate an option to make the binary signable at the expense of marginally slower build time would make a lot of sense.

@ctjlewis
Copy link

Hey guys, just as an update, I’ve talked to Jared about this a few times and everyone is on some page that we gotta be able to sign binaries.

build —binary currently breaks whatever metadata block and that’s why it doesn’t work. I expect within a few versions this will be fixed.

@YoavCodes I was looking into that, do you have any links or notes on distributing the codesigned app folder? The simplest form is actually just App.app/App, no other files.

@codenoid
Copy link

Here's the way I distribute WebhookPrinter.com Mac package while waiting Bun sign support

image

@YoavCodes
Copy link

@YoavCodes I was looking into that, do you have any links or notes on distributing the codesigned app folder?

Can take a look at the build command of the Electrobun cli (which is actually an unsigned single-file bun executable itself, distributed via npm that I'd love to sign)

I'm just a guy building an Electron alternative so the code is a bit messy and I probably went further than you'll want to but essentially for distribution it's:

  • building the app bundle with a bunch of binaries including the bun binary and js files. there's also a zig launcher binary I wrote that just calls $ <path to bundled bun> <path to entrypoint.js> and acts as the main entrypoint for the bundle
  • code signs and notarizes the bundle but this ends up being like 50MB because of the bun binary
  • So the cli tars the whole bundle and uses zstd to compress it it to around 17MB
  • It then creates a second bundle that just has a little zig zstd self-extractor i wrote and the compressed tar file.
    • when the end user opens it for the first time it extracts and replaces itself then runs the extracted version so the user just sees a delay of a couple seconds the first time they open your app
  • it then code signs and notarizes that self-extracting bundle
  • it then puts it in a DMG since these are desktop apps and people need a visual to drag it into the applications folder, you can also notarize a binary by just zipping it and uploading that so dmg for a single file binary is optional
  • Electrobun also has its own update mechanism. So wherever you've uploaded the artifacts to it'll download the latest version and use an optimized bsdiff I wrote in zig to create a tiny patch file from the last version as small as 4KB

Notes:

  • For running an app bundle in terminal you can usually just call $ open <path to app bundle> or run the main binary directly $ <path to app bundle>/Contents/MacOS/yourBinary
  • for the open command or double clicking you typically need a plist file that tells it which binary in the bundle is the one that'll open
  • obv for single binaries or just code signing you're probably distributing via homebrew, npm, or direct download and can skip all the other stuff. for code signing—the apple terminal command, i think, automatically just does a deep dive of your bundle generating a hash for each thing.
  • If you want to notarize a bundle you need to put things in specific folders and have a plist file with entitlements for protected system resources you need access to and the terminal command apple provides will just staple it to the bundle or the binary or whatever you're notarizing
  • I have a feeling that as soon as Oven resolves this code signing issue for single-file executables a significant amount of people that are then unblocked will start complaining about the single-file-executable file size and ask for a minimal build.
    • Aside from distribution cost if you do anything like process fork then you're getting the whole runtime duplicated in memory for each process. and single-file-executables probably don't need a lost of the other stuff bun does like package management.

@max-leuthaeuser
Copy link

max-leuthaeuser commented Oct 7, 2024

I am running into the same problem as the author of this issue when signing compiled executables on macos
(codesign ... or ldid -S. ldid reports unknown header magic, are you sure that is a mach-O?) even with the latest bun v1.1.29.
Any progress here?

@pedsmoreira
Copy link

pedsmoreira commented Nov 26, 2024

I'm running into the same issue on v1.1.37

@ctjlewis
Copy link

@YoavCodes You are a god damn genius. @Jarred-Sumner have you seen this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working bundler Something to do with the bundler
Projects
None yet
Development

No branches or pull requests

9 participants