Merge bitcoin/bitcoin#34914: contrib: replace deprecated --deep codesign flag, fix accidental --verify skip on ci
What changed, and why it matters
This change fixes how Bitcoin Core's macOS app bundle is digitally signed during automated builds. It replaces an outdated 'deep' signing method with explicit signing of each framework, plugin, and the main app bundle. It also fixes a CI script bug that was accidentally skipping the signature verification step entirely, and makes that verification stricter. The practical security effect is that macOS is more likely to detect tampered or improperly signed release binaries, and the build pipeline now actually performs that check.
Treat this as a hardening and build-integrity fix. Ensure the updated macdeployqtplus is used for all macOS release builds and that CI logs confirm the codesign --verify --deep --strict step runs and passes. No immediate user action is required, but release managers should verify the next macOS binary's signature with `codesign --verify --deep --strict --verbose=4`.
Security signals we found
Fixes accidental skip of macOS code-signature verification in CI
Replaces deprecated codesign --deep with explicit per-component signing
Adds --strict to CI signature verification
Addresses signature invalidation from strip/install_name_tool on frameworks and plugins
Fixes GitHub issue #32486
Evidence from the diff
The commit modifies two files. In contrib/macdeploy/macdeployqtplus, it removes the deprecated codesign --deep flag and instead signs each Framework, each Plugin, and finally the top-level .app bundle explicitly. This addresses signature invalidation caused by earlier strip and install_name_tool operations. In ci/test/03_test_script.sh, it introduces a separate BUILD_TARGETS variable so that adding all to the build target list no longer mutates GOAL, which had the side effect of preventing the macOS-specific codesign --verify branch from executing. The verification now uses --deep --strict.
Changed components
Bitcoin-Qt.app macOS bundle signing (contrib/macdeploy/macdeployqtplus)CI build and signature verification script (ci/test/03_test_script.sh)Inspect captured patch +18 / −5
### ci/test/03_test_script.sh
@@ -123,15 +123,16 @@ cmake -S "$BASE_ROOT_DIR" -B "$BASE_BUILD_DIR" "${CMAKE_ARGS[@]}" || (
false
)
+BUILD_TARGETS="${GOAL}"
if [[ "${GOAL}" != all && "${GOAL}" != *codegen* ]]; then
- GOAL="all ${GOAL}"
+ BUILD_TARGETS="all ${GOAL}"
fi
# shellcheck disable=SC2086
-cmake --build "${BASE_BUILD_DIR}" "$MAKEJOBS" --target $GOAL || (
+cmake --build "${BASE_BUILD_DIR}" "$MAKEJOBS" --target $BUILD_TARGETS || (
echo "Build failure. Verbose build follows."
# shellcheck disable=SC2086
- cmake --build "${BASE_BUILD_DIR}" -j1 --target $GOAL --verbose
+ cmake --build "${BASE_BUILD_DIR}" -j1 --target $BUILD_TARGETS --verbose
false
)
@@ -182,7 +183,7 @@ fi
if [[ "$CI_OS_NAME" == "macos" && "${GOAL}" = "install deploy" ]]; then
unzip "${BASE_BUILD_DIR}/bitcoin-macos-app.zip" -d "${BASE_BUILD_DIR}/deploy"
- if ! ( codesign --verify "${BASE_BUILD_DIR}/deploy/Bitcoin-Qt.app" ); then
+ if ! ( codesign --verify --deep --strict "${BASE_BUILD_DIR}/deploy/Bitcoin-Qt.app" ); then
echo "Codesigning failed."
false
fi
### contrib/macdeploy/macdeployqtplus
@@ -488,7 +488,19 @@ with open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb") as f:
# ------------------------------------------------
if platform.system() == "Darwin":
- subprocess.check_call(f"codesign --deep --force --sign - {target}", shell=True)
+ # The earlier strip and install_name_tool calls invalidated existing framework
+ # and plugin code signatures.
+ print("+ Signing app bundle +")
+ sign_targets = [
+ path
+ for pattern in ("Frameworks/*", "PlugIns/*/*")
+ for path in Path(target, "Contents").glob(pattern)
+ if path.is_file() or path.name.endswith(".framework")
+ ]
+ # Sign the app bundle last
+ sign_targets.append(Path(target))
+ for sign_target in sign_targets:
+ subprocess.check_call(["codesign", "--force", "--sign", "-", sign_target.as_posix()])
# ------------------------------------------------
Why this scored 35/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.