@@ -79,6 +79,19 @@ rl_note() { printf ' %s\n' "$*"; }
7979rl_step () { printf ' ==> %s\n' " $* " ; }
8080rl_skip () { RL_SKIPPED+=(" $1 " ); printf ' skipped: %s\n' " $1 " ; }
8181
82+ # `producer | grep -q pattern` is a trap in this file, because `set -o pipefail`
83+ # is on: grep exits at the first match, the producer is killed by SIGPIPE, and
84+ # the pipeline reports that failure — so a SUCCESSFUL match returns non-zero.
85+ # It only bites when the producer is still writing when grep leaves, which is
86+ # why it looks intermittent: `file -b` on one binary is fine, `unzip -l` on a
87+ # 5,000-entry Electron bundle is not. That silently skipped the payload inside
88+ # WebLinked's launcher and produced an unsignable release.
89+ #
90+ # So: never pipe into grep -q here. Capture first, match against a here-string.
91+ rl_grep () { grep -qE -- " $1 " <<< " $2" ; } # rl_grep <ere> <text>
92+ rl_grepF () { grep -qF -- " $1 " <<< " $2" ; } # rl_grepF <literal> <text>
93+ rl_grepi () { grep -qiE -- " $1 " <<< " $2" ; } # rl_grepi <ere, case-insensitive> <text>
94+
8295# NSIS wants a 4-part numeric version (1.2.3 -> 1.2.3.0) for VIProductVersion.
8396rl_numver () {
8497 local v=" ${RL_VERSION%% -* } " n
@@ -400,10 +413,11 @@ rl_sign_file() { # rl_sign_file <path-to-exe-or-dll>
400413 # malformed signature is exactly the failure that stays invisible until a
401414 # user reports it weeks later.
402415 if command -v osslsigncode > /dev/null 2>&1 ; then
403- if ! osslsigncode verify " $f " 2>&1 | grep -q ' Signature verification: ok' ; then
416+ local vout; vout=" $( osslsigncode verify " $f " 2>&1 || true) "
417+ if ! rl_grepF ' Signature verification: ok' " $vout " ; then
404418 echo " signature did not verify: $f " >&2 ; return 1
405419 fi
406- if ! osslsigncode verify " $f " 2>&1 | grep -qi ' timestamp ' ; then
420+ if ! rl_grepi ' timestamp ' " $vout " ; then
407421 echo " signed but NOT timestamped (expires in 72h): $f " >&2 ; return 1
408422 fi
409423 fi
@@ -813,25 +827,39 @@ rl_mac_sign() { # rl_mac_sign <path-to-.app-or-binary>
813827 # when APPLE_SIGNING_IDENTITY is exported. Do NOT re-sign: replacing the
814828 # signature changes the CDHash, and any DMG built from the earlier copy
815829 # would no longer be covered by this app's notarisation.
816- if codesign --verify --strict --deep " $app " > /dev/null 2>&1 \
817- && codesign -dvv " $app " 2>&1 | grep -q " Authority=$RL_MAC_SIGN_IDENTITY " \
818- && codesign -d --verbose=2 " $app " 2>&1 | grep -q ' flags=.*runtime' ; then
830+ # RL_MAC_FORCE_SIGN=1 bypasses this — for repairing something this identity
831+ # previously signed wrongly (a valid signature says nothing about whether
832+ # the entitlements inside it are right).
833+ local desc; desc=" $( codesign -dvv " $app " 2>&1 || true) "
834+ if [[ " ${RL_MAC_FORCE_SIGN:- 0} " != " 1" ]] \
835+ && codesign --verify --strict --deep " $app " > /dev/null 2>&1 \
836+ && rl_grepF " Authority=$RL_MAC_SIGN_IDENTITY " " $desc " \
837+ && rl_grep ' flags=.*runtime' " $desc " ; then
819838 RL_MAC_SIGNED_COUNT=$(( RL_MAC_SIGNED_COUNT + 1 ))
820839 rl_note " already signed with this identity, left untouched"
821840 return 0
822841 fi
823842
824843 if [[ -d " $app " ]]; then
825- # Nested code: everything executable or Mach-O shaped that is not the main
826- # binary. file(1) is the arbiter — resources are not re-signed.
844+ # Nested .app bundles first (Electron/CEF helper apps), recursively and
845+ # WITH the same entitlements: a renderer helper without allow-jit means V8
846+ # aborts at launch — the app notarises fine and then crashes on first run,
847+ # which is strictly worse than the warning this replaces. The -prune below
848+ # keeps the flat passes out of these bundles so this signature survives.
849+ while IFS= read -r f; do
850+ rl_mac_sign " $f " || return 1
851+ done < <( find " $app /Contents" -mindepth 2 -type d -name ' *.app' -prune 2> /dev/null | sort)
852+ # Nested loose code: everything executable or Mach-O shaped that is not the
853+ # main binary. file(1) is the arbiter — resources are not re-signed.
827854 while IFS= read -r f; do
828- file -b " $f " 2> /dev/null | grep -q ' Mach-O ' || continue
855+ rl_grep ' Mach-O ' " $( file -b " $f " 2> /dev/null || true ) " || continue
829856 " ${sign[@]} " " $f " > /dev/null 2>&1 \
830857 || { echo " codesign failed on nested $f " >&2 ; return 1; }
831- done < <( find " $app /Contents" -type f \
832- \( -perm -u+x -o -name ' *.dylib' -o -name ' *.so' \) \
833- ! -path " $app /Contents/MacOS/*" 2> /dev/null | sort)
834- find " $app /Contents" -name ' *.framework' -maxdepth 3 -type d 2> /dev/null \
858+ done < <( find " $app /Contents" -type d -name ' *.app' -prune -o -type f \
859+ \( -perm -u+x -o -name ' *.dylib' -o -name ' *.so' -o -name ' *.node' \) \
860+ ! -path " $app /Contents/MacOS/*" -print 2> /dev/null | sort)
861+ find " $app /Contents" -maxdepth 3 -type d -name ' *.app' -prune -o \
862+ -maxdepth 3 -type d -name ' *.framework' -print 2> /dev/null \
835863 | while IFS= read -r f; do
836864 " ${sign[@]} " " $f " > /dev/null 2>&1 \
837865 || { echo " codesign failed on framework $f " >&2 ; exit 1; }
@@ -906,9 +934,9 @@ rl_mac_sign_tree() { # rl_mac_sign_tree <dir>
906934 rl_mac_sign_ready || return 0
907935 local f
908936 while IFS= read -r f; do
909- file -b " $f " 2> /dev/null | grep -q ' Mach-O ' || continue
937+ rl_grep ' Mach-O ' " $( file -b " $f " 2> /dev/null || true ) " || continue
910938 if codesign --verify --strict " $f " > /dev/null 2>&1 \
911- && codesign -dvv " $f " 2>&1 | grep -q ' Authority= ' ; then
939+ && rl_grepF ' Authority= ' " $( codesign -dvv " $f " 2>&1 || true ) " ; then
912940 continue
913941 fi
914942 rl_mac_sign " $f " || return 1
0 commit comments