Codesigned app gets "developer not confirmed" on macOS Sierra
I build and codesign my Qt 5.6.1 app on Yosemite 10.10.3 using a bash script. I upload the dmg to my OneDrive, then download it on OS X or MacOS. On a clean Yosemite (10.10.3), it works great, as expected: when I try to run it the first time, I get the message that the app is downloaded from the internet, and gives me the option to open it.
However, on El Capitan 10.11.1 and Sierra 10.12.3, when I try to run it the first time it gives me the dreaded, "[My app] can't be opened because the identity of the developer cannot be confirmed." I know I can give users instructions on how they can open it anyway, but that's not a great solution. I am codesigning the app, so I'd like Gatekeeper to be happy with it.
The basic checks I found make it seem that my app is fine (running on Sierra, pointing to my binary inside the [my app].app/Contents/MacOS folder):
codesign --verify --deep --strict --verbose=2 <code-path>
<code-path>: valid on disk <code-path>: satisfies its Designated Requirement
spctl -a -t exec -vv <code-path>
<code-path>: accepted source=Developer ID origin=<identity>
In the "Checking Gatekeeper Conformance" section here, I found a few new requirements since OS X 10.10.3. Using
otool -LI discovered I do indeed have 8
@rpath's in my app, all for Qt items in the Frameworks folder in my bundle. From a command line on my build machine (10.10.3), I can use
install_name_tool -changeto change the
@executable_path/../and verify the change with
otool -L, but when I put the exact same command to change one of the
@rpathsin a one-line script, it does nothing:
otool -Lstill shows
@rpathfor the item that should have been changed.
For example: the command:
install_name_tool -change @rpath/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore /Users/david/dev/git/map-creator-qt/build/mac/pkg-root/Applications/MapCreator.app/Contents/MacOS/MapCreator
successfully changes the output of
otool -L, but this script does not:
#!/bin/sh install_name_tool -change @rpath/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore /Users/david/dev/git/map-creator-qt/build/mac/pkg-root/Applications/MapCreator.app/Contents/MacOS/MapCreator
The script fails with "No such file or directory".
- Am I even on the right track? I think I need to replace all my
@executable_path/../. Is that correct?
- If I am on the right track, what should I do next, since the exact same command works from a command prompt, but not when run from a script?
- Am I even on the right track? I think I need to replace all my
- Seems like you are yes.
- You should rather pass the path to your application executable to your script, that will avoid having to change it when you change your build folder.
- Thanks - that is helpful.
- Actually, for my real script I do pass in the path. Since it didn't work I was eliminating all variables. Even with the full path hardcoded, it works fine from the command line but not in the 1-line script. Any idea why that would be?
Can you show your orignal script content ?
I'm now past the first hurdle: apparently I had some weird line-ending issue that caused the script to fail. Once I basically retyped the new commands, the script to worked as expected. In both a small test and my real script, I can now remove the rpath from the executable using
install_name_tool -delete_rpath, and replace all
install_name_tool -change. Sorry for the (very lengthy for me) rabbit trail!
Unfortunately, though, that does not solve my real problem. When I download from OneDrive, on first run on Sierra still gives the same "developer not confirmed" message. On closer reading here and here, it seems to me that the Qt rpath's shouldn't be a problem anyway, since they point to the Framework folder inside my app bundle. Also, I'm unable to find "Fails dylib check" in the system log after attempting to open the application.
I do find this error in the system log (in Diagnostic and Usage Data in Console):
11:06:46.309195 -0400 CoreServicesUIAgent com.apple.message.domain: com.apple.usage.gatekeeper.open-unsafe-executable-type com.apple.message.signature: com.apple.application-bundle com.apple.message.signature2: LSRiskCategoryUnsafeExecutable
followed immediately by:
11:06:48.372426 -0400 syspolicyd assessment granted for .app by Developer ID com.apple.message.domain: com.apple.security.assessment.outcome2 com.apple.message.signature2: bundle:com.fmosoft.mapcreator com.apple.message.signature3: .app com.apple.message.signature5: UNKNOWN com.apple.message.signature4: 1 com.apple.message.signature: granted:Developer ID
I haven't found anything helpful on what signature5 is. But another possibility: I had checked on my build machine in KeyChain Access that my Developer ID Application and Installation certificates are valid. They expire Dec. 12, 2017. However, it appears that our Developer Program Membership has expired, when I try to log in at https://developer.apple.com.
I'm unclear: should a certificate that is not expired be sufficient for signing my app, or do I have to also have a currently active membership in Apple's Developer Program when I sign my app?
We renewed our Apple Developer Program membership this afternoon. After that was complete and I verified I could log in to the Apple Developer web site again, I tried building my app again, this time on Sierra instead of on Yosemite.
The build completed successfully. I uploaded the dmg to OneDrive, then downloaded it to the same Sierra build machine. I got the same "developer not confirmed" result on first run, same system log messages as above. So building on Sierra made no difference as far as I can tell, nor did paying Apple their money.
spctl -a -t exec -vv <my app.app>,
codesign --verify --deep --strict --verbose=2 <my app.app>, and
check-signature(from Apple here) all indicate that everything is fine.
I'm stumped. I've been Googling the
LSRiskCategoryUnsafeExecutableerror and haven't turned up anything.
Here's the part of my build script that does the code signing. We sign the main app and the help file app in our script but I'm focusing at this point on just the part for the main app, MapCreator.app. I'm including the comments in the script in case they are helpful to someone.
# Sign the bundles # Currently due to concurrency bug (20497047 and 20249918) in Apple's code somewhere, we can't simply codesign and be done. # A workaround is to use the flag --timestamp=none but apparently that will cause the app's signature to break as soon as our certificate expires. # The current workaround is to loop until codesign succeeds. But apparently codesign can do something and fail, then all attempts to codesign that folder will fail. # So, we have to copy the .app's and start with a fresh copy for each codesign attempt. # See http://stackoverflow.com/questions/29687605/segmentation-fault-11-when-attempting-to-codesign-app # and https://devforums.apple.com/message/1124508#1124508 # Create a clean backup of both .app's cp -R "$BUILDDIR/pkg-root/Applications/MapCreator.app" "$BUILDDIR/pkg-root/Applications/MapCreatorUnsigned.app" cp -R "$BUILDDIR/pkg-root/Applications/MapCreatorHelp.app" "$BUILDDIR/pkg-root/Applications/MapCreatorHelpUnsigned.app" # repeat signing Map Creator until the exit value is true (i.e. no crash) until codesign --deep --force --verify --verbose --sign "[our ID]" "$BUILDDIR/pkg-root/Applications/MapCreator.app"; do echo Failure. Trying again... rm -rf "$BUILDDIR/pkg-root/Applications/MapCreator.app" cp -R "$BUILDDIR/pkg-root/Applications/MapCreatorUnsigned.app" "$BUILDDIR/pkg-root/Applications/MapCreator.app" done
Any ideas what the problem could be, or how to try to track it down?
Did you also sign all the frameworks and plugins ?
--deeptakes care of signing the frameworks and plugins (and everything else). When I look in the bundle, there's "_CodeSignature" folders in the Frameworks, and at the top level (under Contents).
There isn't any "_CodeSignature" folder in the PlugIns, SharedLibraries, or Resources folders. However, they appear to all be represented in the top-level _CodeSignature/CodeResources file.
However, I notice there is no _CodeSignature folder in MacOS, where my executable resides. Could that be the problem?
Except, I remember reading that the code signature actually gets embedded in the executable, rather than being a separate folder.
In an effort to satisfy Sierra's Gatekeeper, I have switched to building and codesigning on macOS 10.12.3. I still have the same problem, but since I'm not building on Yosemite anymore, I have opened a new question here, with a minimal sample app and build script.
The solution that worked for me turned out to be using
otool -lto find which frameworks had LC_RPATH outside the bundle, and removing them. I'm now building on Sierra, but I tested and the same solution I noted here works on Yosemite.