fix(install): do not resolve jq/awk through the downloaded release - #8
fix(install): do not resolve jq/awk through the downloaded release#8fxmedus wants to merge 1 commit into
Conversation
export PATH="$DEST:$PATH" put a just-extracted release tarball ahead of the system PATH, so every later jq and awk resolved out of it. Those compute the readiness score, risk score, finding count and max severity, so a release asset shipping its own jq would control the gate decision without touching the scanner binary. Bind the binary by path instead. jq is already required before the download exists (the latest-version lookup uses it), so it is a system prerequisite and nothing depended on the tarball providing it. Also match the asset name literally in the checksum lookup: $ASSET contains dots, which grep treats as wildcards, so an entry differing only at those positions could be selected. bash -n clean. No behaviour change for any input that works today.
|
Thanks @fxmedus. Flagging that this is being read rather than sitting unlooked-at. We are reviewing all 52 open PRs together instead of one at a time. 31 of them edit Queued in the security cluster. Resolving The order we are working to: the test harness in #1 first, since twelve PRs depend on it and nothing is verifiable without it, then the fixes that close fail-open paths, then behaviour changes, then docs. A verdict on this one follows once its cluster is read. Apologies for the wait, and thanks for the contribution. |
sairenchristianbuerano
left a comment
There was a problem hiding this comment.
Thanks @fxmedus — approving the substance, but this needs a rebase.
#7 is on main now and rewrote the checksum block, which is where this conflicts
— scan/trustabl-scan.sh, around
if curl -fsSL "${AUTH[@]}" -o "$DEST/checksums.txt".
The concern here still stands after that change, and arguably matters more: #7
makes us trust the downloaded archive's integrity, but resolving jq or awk
through the extracted release path means a substituted archive could still supply
the tools we then use to check it. Worth keeping the two separate.
main has the test harness from #1, so bash test/run-tests.sh will verify the
rebase — 19 passing there right now.
What
Two changes to
scan/trustabl-scan.sh, both about what the script assumes it can trustfrom a freshly downloaded release.
1. The extracted tarball shadows system
jqandawk$DESTholds a just-extracted release tarball. Line 108 prepends it toPATH:Every later helper in the script then resolves through that
PATHfirst. Lines 145onward use
jqandawkto compute every number the wrapper reports:A release asset shipping its own
jqwould therefore control the readiness score, therisk score, the finding count and the max severity — the gate decision itself — without
touching the scanner binary. Checksum verification does not help: the checksum attests
that the tarball is the one the release published, not that its contents are only
trustabl.Fix: bind the binary by path and drop the
PATHmutation.Why this is safe:
jqis already required before the download exists — thelatestversion lookup at line 60 pipes the GitHub API response through it. Sojqisnecessarily a system prerequisite and nothing in the script ever depended on the tarball
supplying it.
trustablitself resolves identically, since$DESTwas prepended andalready won.
Those two call sites are the only bare
trustablinvocations in the file; verified witha grep after the change.
2. Checksum lookup matches the asset name as a regex
EXPECTED=$(grep " ${ASSET}\$" "$DEST/checksums.txt" | awk '{print $1}' | head -1)$ASSETistrustabl_${VNUM}_${OS}_${ARCH}.tar.gzand is interpolated straight into aregex, where its dots are wildcards. An entry that differs from the wanted asset only at
those positions satisfies the match, and
head -1takes whichever comes first.Demonstrated against a two-line
checksums.txtwhere the decoy has its dots substitutedand underscores left intact:
A mismatch here aborts the run rather than passing a bad binary, so the practical
consequence is a confusing failure rather than a bypass. Worth correcting regardless,
since it is the integrity check.
Fix: compare field 2 for equality instead of pattern-matching, allowing
sha256sum'sbinary-mode
*prefix.EXPECTED=$(awk -v a="$ASSET" '$2 == a || $2 == "*" a { print $1 }' "$DEST/checksums.txt" | head -1)Verification
Scope
One file, +15 / -4. No behaviour change on any input that works today: the same binary
runs, the same checksum is compared, the same exit codes are produced. Nothing outside
the download and invocation path is touched.
Related
Two further fail-open behaviours in this same file are filed separately as an issue,
since hardening either one changes results for existing pipelines and is a maintainer
call rather than something to land unannounced.