Notarization error: differing behavior based on machine.

We're attempting to update on of our apps from Unity 2019 to Unity 2021. Attempting to notarize the built app fails. This is on our main build machine running macOS Catalina 10.15.7. An independent contractor working with us builds the exact same project on his laptop running macOS Catalina 10.15.7. He can notarize the app successfully.

Now, her's the interesting part. As a test, the two of us built new apps and transferred them to each other's systems. The app transferred from the build machine to the laptop notarized successfully, while the one transferred the other way failed. Would love to get some insight on what's going on. Why does notarization succeed on one machine but fail on another?

Log output:

{
  "logFormatVersion": 1,
  "jobId": "b48937dd-37cb-4833-9d2b-5c64b5b9f75c",
  "status": "Invalid",
  "statusSummary": "Archive contains critical validation errors",
  "statusCode": 4000,
  "archiveFilename": "AppName.zip",
  "uploadDate": "2021-08-16T20:01:39Z",
  "sha256": "78a71ec70e906480b9817580672b59e4a4c5f7ccb46b292314a6ad4a6c0b1acc",
  "ticketContents": null,
  "issues": [
    {
      "severity": "error",
      "code": null,
      "path": "AppName.zip/AppName.app/Contents/MacOS/AppNameGame",
      "message": "The signature of the binary is invalid.",
      "docUrl": null,
      "architecture": "x86_64"
    }
  ]
}

And our notarization script:

export APPLICATION_NAME=AppName
export APPLICATION_FILE=${APPLICATION_NAME}.app
export APPLICATION_ZIP=${APPLICATION_NAME}.zip
export APPLICATION_ENTITLEMENTS=${APPLICATION_NAME}.entitlements
export APPLICATION_BUNDLE_ID=unity.Dev.AppName

export APPLE_USERNAME=user@name.com
export APPLE_PASSWORD=NOT_A_REAL_PASSWORD
export APPLE_PROVIDER=AppProducer
export APPLE_SIGNATURE="Developer ID Application: AppProducer, Inc. (ABCD123456)"

rm ${APPLICATION_NAME}.zip

codesign --deep --force --verify --verbose --timestamp --options runtime --entitlements ${APPLICATION_ENTITLEMENTS} --sign "${APPLE_SIGNATURE}" "${APPLICATION_FILE}/Contents/Plugins/CustomRulesLib-OSX.bundle/Contents/MacOS/CustomRulesLib-OSX"

codesign --deep --force --verify --verbose --timestamp --options runtime --entitlements ${APPLICATION_ENTITLEMENTS} --sign "${APPLE_SIGNATURE}" "${APPLICATION_FILE}/Contents/Plugins/steam_api.bundle/Contents/MacOS/libsteam_api.dylib"

codesign --deep --force --verify --verbose --timestamp --options runtime --entitlements ${APPLICATION_ENTITLEMENTS} --sign "${APPLE_SIGNATURE}" "${APPLICATION_FILE}/Contents/Plugins/unitypurchasing.bundle/Contents/MacOS/unitypurchasing"

codesign --deep --force --verify --verbose --timestamp --options runtime --entitlements ${APPLICATION_ENTITLEMENTS} --sign "${APPLE_SIGNATURE}" ${APPLICATION_FILE}

zip -q -r ${APPLICATION_ZIP} ${APPLICATION_FILE}

xcrun altool --notarize-app --username ${APPLE_USERNAME} --password ${APPLE_PASSWORD} --asc-provider ${APPLE_PROVIDER} --primary-bundle-id ${APPLICATION_BUNDLE_ID} --file ${APPLICATION_ZIP}

It's hard to say exactly what's going on here, but I can provide you some insight based on what you have posted:

  1. The Notary Service does provide the error message that points out that your main executable has a bad signature:
"path": "AppName.zip/AppName.app/Contents/MacOS/AppNameGame",
"message": "The signature of the binary is invalid.",

Take a look at this signature compared to the successful version with:

# Signature view:
$ codesign -dvvvvv AppName.app/Contents/MacOS/AppNameGame

# Entitlements on that executable:
$ codesign -d --entitlements :- AppName.app/Contents/MacOS/AppNameGame
  1. Do not use the --deep argument when code signing. Quinn has an excellent post describing why you should avoid this.

  2. This path looks off:

/Contents/Plugins/steam_api.bundle/Contents/MacOS/libsteam_api.dylib

The outer path for steam_api.bundle looks fine, but the nested path for the libsteam_api.dylib should reside in a path that looks like this:

/Contents/Plugins/steam_api.bundle/Contents/Frameworks/libsteam_api.dylib

This is based on the Nested Code locations of macOS Code Signing In Depth.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

Here's the signature view & entitlements for the failed notarization:

Executable=/Location/AppName.app/Contents/MacOS/AppNameGame
Identifier=unity.Dev.AppName
Format=app bundle with Mach-O thin (x86_64)
CodeDirectory v=20500 size=579 flags=0x10000(runtime) hashes=9+5 location=embedded
VersionPlatform=1
VersionMin=658688
VersionSDK=720896
Hash type=sha256 size=32
CandidateCDHash sha256=1125693fd24c9a5d8eb5983d6bc93dc657f0265c
CandidateCDHashFull sha256=1125693fd24c9a5d8eb5983d6bc93dc657f0265c412d9e07ec0b55cea1a53bbc
Hash choices=sha256
CMSDigest=1125693fd24c9a5d8eb5983d6bc93dc657f0265c412d9e07ec0b55cea1a53bbc
CMSDigestType=2
Page size=4096
  -5=19e2e9e7ccf84a26e946323b89319eeb1a008dc7a58cdaa9f49bf0794d90ce8b
  -4=0000000000000000000000000000000000000000000000000000000000000000
  -3=5211b7b83b1c890974319fbc5f6154cfc1a5eef66343735676fe60d2eb042d6f
  -2=41e34ca9203b69c0c277cbe6b861e57a0edc2abe4264542e2205a5b13e736f1e
CDHash=1125693fd24c9a5d8eb5983d6bc93dc657f0265c
Signature size=8976
Authority=Developer ID Application: AppProducer, Inc. (ABCD123456)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=Aug 18, 2021 at 10:58:00 AM
Info.plist entries=19
TeamIdentifier=ABCD123456
Runtime Version=11.0.0
Sealed Resources version=2 rules=13 files=89
Internal requirements count=1 size=184


Executable=/Location/AppName.app/Contents/MacOS/AppNameGame
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
      <key>com.apple.security.network.client</key>
      <true/>
      <key>com.apple.security.cs.disable-library-validation</key>
      <true/>
      <key>com.apple.security.cs.disable-executable-page-protection</key>
      <true/>
      <key>com.apple.security.cs.allow-dyld-environment-variables</key>
      <true/>
  </dict>
</plist>

And this is from a successful notarization, taken from a Unity 2019 build:

Executable=/Location/AppName.app/Contents/MacOS/AppNameGame
Identifier=unity.Dev.AppName
Format=app bundle with Mach-O thin (x86_64)
CodeDirectory v=20500 size=387 flags=0x10000(runtime) hashes=3+5 location=embedded
VersionPlatform=1
VersionMin=657664
VersionSDK=658944
Hash type=sha256 size=32
CandidateCDHash sha1=b3b5aa6933c083f3433319f03820e3644ec1d970
CandidateCDHashFull sha1=b3b5aa6933c083f3433319f03820e3644ec1d970
CandidateCDHash sha256=8828c7e4b18c0d1e7a2b556793e6d7c9bdac96ef
CandidateCDHashFull sha256=8828c7e4b18c0d1e7a2b556793e6d7c9bdac96ef1a47c79179a574b8d179bbf3
Hash choices=sha1,sha256
CMSDigest=6cbb44621800c8a9b25d6f744f2c44d318958c252459a9e339f2e3b5c5c1cd8f
CMSDigestType=2
Page size=4096
  -5=19e2e9e7ccf84a26e946323b89319eeb1a008dc7a58cdaa9f49bf0794d90ce8b
  -4=0000000000000000000000000000000000000000000000000000000000000000
  -3=469fc9387aed76f4b7fc1f9a030f68d5fdce03010f283e46b7b60893d953f4fe
  -2=41e34ca9203b69c0c277cbe6b861e57a0edc2abe4264542e2205a5b13e736f1e
CDHash=8828c7e4b18c0d1e7a2b556793e6d7c9bdac96ef
Signature size=9057
Authority=Developer ID Application: AppProducer, Inc. (ABCD123456)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=Jun 23, 2021 at 2:53:26 PM
Info.plist entries=19
TeamIdentifier=ABCD123456
Runtime Version=10.14.0
Sealed Resources version=2 rules=13 files=98
Internal requirements count=1 size=184


Executable=/Location/AppName.app/Contents/MacOS/AppNameGame
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
      <key>com.apple.security.network.client</key>
      <true/>
      <key>com.apple.security.cs.disable-library-validation</key>
      <true/>
      <key>com.apple.security.cs.disable-executable-page-protection</key>
      <true/>
      <key>com.apple.security.cs.allow-dyld-environment-variables</key>
      <true/>
  </dict>
</plist>

Also, double-checked the location of that steamworks bundle and it's actually correct.

Regarding the following entitlement:

<key>com.apple.security.cs.disable-library-validation</key>
<true/>

I would recommend removing this entitlement as I suspect it is not needed. You will only need to use this entitlement if you are loading a library (dylib) that is either outside of your bundle on disk or if the library has a different code signature than your bundle does. If you are doing either of these things I would strongly advise that you stop doing this and move your library inside your bundle. In my experience I typically see this entitlement being used to workaround a loading issue inside of your app's bundle. I would recommend that you go back to your build .app and right click it in Finder to do "Show Package Contents." In the Finder navigate to the Contents directory and expand it to make sure all of your compiled code fits the requirements from the Nested Code section here.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Notarization error: differing behavior based on machine.
 
 
Q