mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2026-08-17 16:34:44 -05:00
fix(mac): prune dangling symlinks before codesign so Gatekeeper accepts the bundle (#10108)
A signed, notarised and stapled pgAdmin 4.app was rejected by Gatekeeper with "invalid destination for symbolic link in bundle". Gatekeeper walks every symlink in the bundle and rejects the whole app if any link does not resolve to a real file inside it; notarisation does not catch this, so a broken link slips through stapling and only surfaces as a Gatekeeper failure on the end user's machine. The embedded Python.framework ships such links: an arm64-only build still carries a bin/python3-intel64 launcher symlink (whose target _strip_architecture deletes when it removes the foreign-arch files), and the bundled Tcl/Tk frameworks carry PrivateHeaders links pointing at a Versions/Current that has none. Add a _prune_dangling_symlinks step that removes every dangling symlink in the bundle after architecture stripping and before signing, then fails the build if any remain, so this cannot slip past notarisation again.
This commit is contained in:
@@ -427,6 +427,36 @@ _strip_architecture() {
|
||||
done < <(find "${BUNDLE_DIR}" -type f)
|
||||
}
|
||||
|
||||
_prune_dangling_symlinks() {
|
||||
# Gatekeeper walks every symlink in the bundle and rejects the whole app
|
||||
# with "invalid destination for symbolic link in bundle" if any link does
|
||||
# not resolve to a real file inside the app. Notarisation does NOT catch
|
||||
# this, so a broken link slips through stapling and only surfaces as a
|
||||
# Gatekeeper failure on the end user's machine.
|
||||
#
|
||||
# The embedded Python.framework ships such links: an arm64-only build still
|
||||
# carries a bin/python*-intel64 launcher symlink (whose target we delete in
|
||||
# _strip_architecture), and the bundled Tcl/Tk frameworks carry
|
||||
# PrivateHeaders links pointing at a Versions/Current that has none. Rather
|
||||
# than hunt individual offenders, prune EVERY dangling symlink so a future
|
||||
# stray link cannot reintroduce the bug.
|
||||
#
|
||||
# NB: this MUST run after _strip_architecture (which orphans links by
|
||||
# deleting their targets) and before _codesign_binaries / _codesign_bundle.
|
||||
|
||||
echo "Pruning dangling symlinks before signing..."
|
||||
# -type l selects symlinks; "! -exec test -e {} \;" keeps only those whose
|
||||
# target does not exist (test -e follows the link). BSD find on macOS.
|
||||
find "${BUNDLE_DIR}" -type l ! -exec test -e {} \; -print -delete
|
||||
|
||||
# Belt and braces: fail the build if anything still dangles, so this can
|
||||
# never silently slip past notarisation into a shipped bundle again.
|
||||
if find "${BUNDLE_DIR}" -type l ! -exec test -e {} \; -print | grep -q .; then
|
||||
echo "ERROR: bundle still contains dangling symlinks (Gatekeeper will reject)" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
_generate_sbom() {
|
||||
echo "Generating SBOM..."
|
||||
syft "${BUNDLE_DIR}/Contents/" -o cyclonedx-json > "${BUNDLE_DIR}/Contents/sbom.json"
|
||||
|
||||
@@ -93,6 +93,7 @@ _create_python_env
|
||||
_build_docs
|
||||
_complete_bundle
|
||||
_strip_architecture
|
||||
_prune_dangling_symlinks
|
||||
_generate_sbom
|
||||
_codesign_binaries
|
||||
_codesign_bundle
|
||||
|
||||
Reference in New Issue
Block a user