Thu 24 June 2021

Debugging Broken Signed/Notarized Apps on macOS

Consider the following: you've built a macOS app (perhaps outside of Xcode), signed and notarized it, and see no errors in your build log. This is a common scenario for CI (Continuous Integration) build pipelines.

Now you run the resulting .app bundle... and the OS screams at you that the bundle is broken, and should be moved to the trash. What gives?

A Green Frog

One project I poke at from time to time - mostly with odd and/or esoteric macOS-related things - is Project Slippi. Earlier this week, they released a new Launcher, which helps with a number of things related to viewing replays, automatic updating, and more. Initial testing across the various Operating Systems seemingly went okay, but on release users started reporting that the macOS build started throwing up the aforementioned "bundle is broken" notification.

Nikhil reached out to me fairly quickly, and we went back and forth for a few minutes debugging. Poking and prodding at the bundle structure brought up nothing special, with nothing out of place (i.e, it was a well-formed bundle). I decided to then see if maybe signing or notarizing had broken somehow. The steps I tend to default to are below, but if you want to do some more reading about the various incantations, I highly recommend this Eclectic Light post.

# Checks and displays signature information
codesign -dvvv /path/to/app

# Checks and displays notarization status
spctl -a -vv -t install /path/to/app

Running the latter ultimately produced something useful to go on: a sealed resource is missing or invalid.

Resource Oddities

Unfortunately, that error message is a little light on details. Still, we can debug further. Scanning CI build pipeline instructions verified it hadn't been changed, and the output had no warning or error messages. We also reviewed the CI build to make sure the bundle wasn't tampered with after being built/signed/notarized, and this too checked out... so what on earth is this error?

One piece of Apple documentation that never seems to show up in search engines (for me, at least) is how to actually troubleshoot failing signatures. It's a shame, too, because there's an incredibly useful codesign incantation in here that leads right to the error:

codesign --verify \
    -vvvv \
    -R='anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.1] exists and (certificate leaf[field.1.2.840.113635.100.6.1.2] exists or certificate leaf[field.1.2.840.113635.100.6.1.4] exists)' \
    /path/to/the.app

Running the above brings us a slightly confusing (but still useful) error message:

Wat.

Special Character Issues...?

These are files used in showing what stage a game was played on. The app uses the filename as a key to display the appropriate image... and for whatever reason, the accented é causes issues in signature verification.

Vinceau thankfully had a quick fix: just rename all the images to key on stage ID. After kicking CI to rebuild, the resulting bundle successfully passed signature verification.

This post illustrates a seemingly simple to debug issue, but one that I've found elusive on details for discerning the root cause. Hopefully this helps someone else in the future.

Ryan around the Web