fdroid-publish: find_tool must test its result (ls|tail exits 0 on no match)

An empty SDK build-tools glob was reported as found, so the signer check ran
nothing and refused a correctly signed APK with an empty signer. An unreadable
signer now warns and defers to the host's pinned-cert check; only a real
mismatch fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
sysadminandClaude Opus 5.5 committed 2026-09-30 21:56:03 +01:00
1 parent 624415406f
commit 3d3f8360ae
1 file changed
+15 -6
+15 -6
View File
@@ -54,17 +54,26 @@ find_tool() { # newest build-tools copy of $1 under the Android SDK, or PATH
command -v "$1" 2>/dev/null && return 0
for sdk in "${ANDROID_HOME:-}" "${ANDROID_SDK_ROOT:-}" /opt/android-sdk /opt/android/sdk /usr/lib/android-sdk; do
[ -n "$sdk" ] && [ -d "$sdk/build-tools" ] || continue
ls -d "$sdk"/build-tools/*/"$1" 2>/dev/null | sort -V | tail -n1 && return 0
# Test the RESULT, not the pipeline: `ls … | tail` exits 0 even when ls found
# nothing, which once reported an empty path as found (empty signer → refusal).
p=$(ls -d "$sdk"/build-tools/*/"$1" 2>/dev/null | sort -V | tail -n1)
[ -n "$p" ] && [ -x "$p" ] && { printf '%s
' "$p"; return 0; }
done
return 1
}
# Signer check before anything leaves the runner, so a mis-signed build fails
# here with a clear message instead of as CERT_MISMATCH on the host.
if apksigner=$(find_tool apksigner); then
got=$("$apksigner" verify --print-certs "$apk" 2>/dev/null | sed -n 's/^Signer #1 certificate SHA-256 digest: //p' | head -n1 | tr 'A-F' 'a-f')
[ "$got" = "$cert" ] || fail "APK signer $got is not the pinned $app cert $cert — refusing to publish"
say "signer cert: OK ($cert)"
if apksigner=$(find_tool apksigner) && [ -n "$apksigner" ]; then
got=$("$apksigner" verify --print-certs "$apk" 2>/dev/null | sed -n 's/^Signer #1 certificate SHA-256 digest: //p' | head -n1 | tr 'A-F' 'a-f' || true)
if [ -z "$got" ]; then
say "::warning::apksigner at $apksigner printed no signer; the repo host verifies the cert"
elif [ "$got" != "$cert" ]; then
fail "APK signer $got is not the pinned $app cert $cert — refusing to publish"
else
say "signer cert: OK ($cert)"
fi
else
say "signer cert: apksigner not found here; the repo host verifies it"
fi
@@ -72,7 +81,7 @@ fi
if [ -z "$version_code" ]; then
# Needed for the no-downgrade guard below. A bare runner image (the promote
# workflow's) has no Android SDK, so fetch Debian's aapt rather than guess.
if ! aapt=$(find_tool aapt2 || find_tool aapt); then
if ! aapt=$(find_tool aapt2 || find_tool aapt) || [ -z "$aapt" ]; then
SUDO=; [ "$(id -u)" -eq 0 ] || SUDO=sudo
{ $SUDO apt-get update -qq && $SUDO apt-get install -y -qq aapt; } >/dev/null 2>&1 || true
aapt=$(command -v aapt || true)