Skip to content

Conversation

@tsteven4
Copy link

@tsteven4 tsteven4 commented Nov 8, 2025

codesign verification or codesign signing errors can occur with macdeployqt. The errors can only occur if multiple executables exist in the root binary path (../MacOS/Contents) as one would expect if the -executables option is used. Furthermore, the errors depend on the unsorted order of the binaries returned by QDir.

To avoid these errors this PR ensures that the app binary is signed after any other binaries in the root binaries path.

This avoids a potential codesign verification error, e.g.

ERROR: codesign verification error:
ERROR: "GPSBabelFE.app: nested code is modified or invalid\n"

This was observed with Qt 6.10.0, System Version: macOS 26.1 (25B78), Model Name: Mac mini, Model Identifier: Macmini9,1, Model Number: MGNR3LL/A, Chip: Apple M1

Alternatively, a potential codesign signing error should be avoided as well, e.g.

ERROR: Codesign signing error:
ERROR: "/Users/runner/work/gpsbabel/gpsbabel/gui/GPSBabelFE.app/Contents/MacOS/GPSBabelFE: replacing existing signature\n/Users/runner/work/gpsbabel/gpsbabel/gui/GPSBabelFE.app/Contents/MacOS/GPSBabelFE: code object is not signed at all\nIn subcomponent: /Users/runner/work/gpsbabel/gpsbabel/gui/GPSBabelFE.app/Contents/MacOS/gpsbabel\n"

This was observed on github with Qt 6.10.0, macOS 26.0.1 (25A362), Image: macos-26-arm64, Version: 20251103.0095

It is not clear to me why I see the first locally and the second on github actions. I have verified the fix locally but not on github actions.

These errors can only occur when there are multiple binaries in the rootBinariesPath (.../Contents/MacOS/). Multiple binaries can be expected if the --executables option is used, although the value of that option is not used in codesignBundle.
Note that the appBinaryName may or may not be first in the unsorted foundRootBinaries. In existing code the occurrence of the error will depend on the order of foundRootBinaries, so some test cases could fail and other pass.

…ot binaries path.

This avoids a codesign verification error that may appear as
"nested code is modified or invalid".
@cla-assistant
Copy link

cla-assistant bot commented Nov 8, 2025

CLA assistant check
All committers have signed the CLA.

@tsteven4
Copy link
Author

@kkoehne can you please look at this? With your recent commit 👍 d4ee081
many more cases will be impacted by the issue fixed here.

@kkoehne
Copy link
Contributor

kkoehne commented Nov 10, 2025

I can have a look. Anyhow, do you have insights on the root issue?Why does it matter in which order the binaries inside Contents/MacOS are signed?

@tsteven4
Copy link
Author

I can have a look. Anyhow, do you have insights on the root issue?Why does it matter in which order the binaries inside Contents/MacOS are signed?

My only insight is the two error messages I quoted above, and their absence when I changed the order. https://developer.apple.com/documentation/xcode/creating-distribution-signed-code-for-the-mac#Determine-the-signing-order discusses the signing order but implies either order is acceptable if the two executables are independent. In my case GPSBabelFE starts gpsbabel as a process but I don't see how codesign could know that. codesign can see that GPSBabelFE is the CFBundleExecutable in Info.plist. I do see that gpsbabel appears in _CodeSignatures/CodeResources, while GPSBabelFE does not.

@tsteven4
Copy link
Author

I replaced the standalone app "gpsbabel" in Contents/MacOS with another standalone app "aprog" that doesn't have any dependencies. Furthermore, the bundle executable "GPSBabelFE" doesn't know anything about "aprog". I dropped the executable option from macdeployqt. I can still create the errors, and I can change the build to get the two variations on the failure based on building universal binary or an apple binary. If I name the extra binary "zprog" instead of "aprog" no errors are generated as one might expect from the unsorted directory list.

I suspect the app bundle executable needs to be signed last to "seal" the bundle.

The difference between the two error messages has to do with what architectures are targeted.
If I target x86_64 and arm64:

Log: "codesign" "/Users/administrator/ts4-2/bldd/gui/GPSBabelFE.app/Contents/MacOS/GPSBabelFE"
ERROR: Codesign signing error:
ERROR: "/Users/administrator/ts4-2/bldd/gui/GPSBabelFE.app/Contents/MacOS/GPSBabelFE: replacing existing signature\n/Users/administrator/ts4-2/bldd/gui/GPSBabelFE.app/Contents/MacOS/GPSBabelFE: code object is not signed at all\nIn subcomponent: /Users/administrator/ts4-2/bldd/gui/GPSBabelFE.app/Contents/MacOS/aprog\n"
Log: Using otool:
Log:  inspecting "/Users/administrator/ts4-2/bldd/gui/GPSBabelFE.app/Contents/MacOS/aprog"
Log: Could not parse otool output line: "/Users/administrator/ts4-2/bldd/gui/GPSBabelFE.app/Contents/MacOS/aprog (architecture arm64):"
Log: "codesign" "/Users/administrator/ts4-2/bldd/gui/GPSBabelFE.app/Contents/MacOS/aprog"
Log: "/Users/administrator/ts4-2/bldd/gui/GPSBabelFE.app/Contents/MacOS/aprog: replacing existing signature\n"
Log: Finished codesigning  "GPSBabelFE.app" with identity "-"
ERROR: codesign verification error:
ERROR: "GPSBabelFE.app: code object is not signed at all\n"

If I just target arm64:

Log: "codesign" "/Users/administrator/ts4-2/bld/gui/GPSBabelFE.app/Contents/MacOS/GPSBabelFE"
Log: "/Users/administrator/ts4-2/bld/gui/GPSBabelFE.app/Contents/MacOS/GPSBabelFE: replacing existing signature\n"
Log: Using otool:
Log:  inspecting "/Users/administrator/ts4-2/bld/gui/GPSBabelFE.app/Contents/MacOS/aprog"
Log: "codesign" "/Users/administrator/ts4-2/bld/gui/GPSBabelFE.app/Contents/MacOS/aprog"
Log: "/Users/administrator/ts4-2/bld/gui/GPSBabelFE.app/Contents/MacOS/aprog: replacing existing signature\n"
Log: Finished codesigning  "GPSBabelFE.app" with identity "-"
ERROR: codesign verification error:
ERROR: "GPSBabelFE.app: nested code is modified or invalid\n"

@tsteven4
Copy link
Author

There is a very simple testcase here: https://github.com/tsteven4/csbug
You can see the error at https://github.com/tsteven4/csbug/actions/runs/19242630126/job/55008764682

@tsteven4
Copy link
Author

I can have a look. Anyhow, do you have insights on the root issue?Why does it matter in which order the binaries inside Contents/MacOS are signed?

From the codesign man page

 Code nested within bundle directories must already be signed or the signing operation will fail ...

There is also a definition of nested code. In this PR we are only addressing Contents/MacOS.

 •   Nested code content is a special term that only applies to
                 macOS style bundles with a Contents folder. Only bare Mach-Os
                 and well structured bundles qualify as nested code content.
                 Non-bundle directories in nested code content locations will
                 cause an error when signing. The codesign tool will only
                 discover nested code content in the following directories:

                 •   Contents
                 •   Contents/Frameworks
                 •   Contents/SharedFrameworks
                 •   Contents/PlugIns
                 •   Contents/Plug-ins
                 •   Contents/XPCServices
                 •   Contents/Helpers
                 •   Contents/MacOS
                 •   Contents/Library/Automator
                 •   Contents/Library/Spotlight
                 •   Contents/Library/LoginItems

@kkoehne
Copy link
Contributor

kkoehne commented Nov 13, 2025

Thanks for the detailed investigation! With the example application, it was indeed easy to verify that macOS considers all binaries inside the Contents/MacOS folder as 'inner dependencies' ...

We don't use github for development of qt, but codereview.qt-project.org. I created now a proposed patch there:
https://codereview.qt-project.org/c/qt/qtbase/+/691086

Anyhow, I couldn't keep your authorship in the git metadata, as our system doesn't like pseudonymous github.com addresses. If you want to be properly attributed, you therefore need to log into codereview.qt-project.org with your Qt account, and amend /resubmit the patch yourself. Please let me know what you prefer.

@tsteven4
Copy link
Author

@kkoehne Please proceed with your authorship of the patch. thanks.

qtprojectorg pushed a commit that referenced this pull request Nov 14, 2025
This avoids a codesign verification error that may appear as
"nested code is modified or invalid".

This commit was originally created by
    https://github.com/tsteven4

#125

Pick-to: 6.5 6.8 6.10
Change-Id: Ifa0b4ed9da1d7b36cb54f9d2fa6aee48c1fe519c
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
@kkoehne
Copy link
Contributor

kkoehne commented Nov 17, 2025

Change in qtbase has been merged. Thanks !

@tsteven4
Copy link
Author

I see it in dev, but not 6.10. It appears https://codereview.qt-project.org/c/qt/qtbase/+/691413 may need some intervention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants