Launcher: fail closed on a missing download checksum (engine triage C1)

Byte-identical sync of the engine repo's launchers: a freshly downloaded
engine binary now runs only after verifying against its .sha256 sidecar.
A sidecar that cannot be fetched, or a machine with no sha256 tool,
refuses the download instead of exec'ing an unverified binary; the
wget-only path fetches the sidecar too. Binaries already on PATH or in
the cache that pass engine-probe are unaffected.

Prepared with AI assistance (Claude Code).

Co-Authored-By: Claude Code <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WaJv2c4oN8wS7Ttq4XRqyx
This commit is contained in:
Paul Bakaus
2026-08-31 20:00:04 -07:00
co-authored by Claude Code
parent fe30578c8a
commit b9902222d9
2 changed files with 43 additions and 22 deletions
+26 -11
View File
@@ -112,17 +112,32 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
fetch_url "$url" && fetched=1
fi
if [ "$fetched" = 1 ]; then
if command -v curl >/dev/null 2>&1 && curl -fsSL -o "$tmp.sha256" "$url.sha256" 2>/dev/null; then
expected=$(cut -d' ' -f1 < "$tmp.sha256")
actual=""
if command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$tmp" | cut -d' ' -f1)
elif command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$tmp" | cut -d' ' -f1); fi
if [ -n "$actual" ] && [ "$actual" != "$expected" ]; then
rm -f "$tmp" "$tmp.sha256"
echo "impeccable: checksum mismatch downloading $url" >&2
exit 127
fi
rm -f "$tmp.sha256"
# Fail closed: a freshly downloaded binary runs only after verifying
# against its .sha256 sidecar. A sidecar that cannot be fetched, or a
# machine with no sha256 tool, refuses the download instead of exec'ing
# an unverified binary. (A binary already on PATH or in the cache that
# passes engine-probe is unaffected.)
sidecar_ok=0
if command -v curl >/dev/null 2>&1; then
curl -fsSL --retry 2 -o "$tmp.sha256" "$url.sha256" 2>/dev/null && sidecar_ok=1
elif command -v wget >/dev/null 2>&1; then
wget -q -O "$tmp.sha256" "$url.sha256" 2>/dev/null && sidecar_ok=1
fi
expected=""
[ "$sidecar_ok" = 1 ] && expected=$(cut -d' ' -f1 < "$tmp.sha256")
actual=""
if command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$tmp" | cut -d' ' -f1)
elif command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$tmp" | cut -d' ' -f1); fi
rm -f "$tmp.sha256"
if [ -z "$expected" ] || [ -z "$actual" ]; then
rm -f "$tmp"
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or no sha256 tool); refusing the unverified download" >&2
exit 127
fi
if [ "$actual" != "$expected" ]; then
rm -f "$tmp"
echo "impeccable: checksum mismatch downloading $url" >&2
exit 127
fi
chmod +x "$tmp" 2>/dev/null
mv -f "$tmp" "$cached" && exec "$cached" "$@"
+17 -11
View File
@@ -13,9 +13,10 @@ rem - The unversioned user binary and the PATH candidate are validated with
rem the engine-probe handshake (see :probe) so the retired 3.x npm CLI,
rem whose bin is also named impeccable, is never exec'd. IMPECCABLE_BIN,
rem the sibling binary, and the version-pinned cache stay trusted.
rem - Downloads are verified against the .sha256 sidecar via certutil when
rem the sidecar is served; on ARM64 the arm64 asset is tried first and the
rem x64 asset is the fallback (Windows on ARM runs x64 binaries).
rem - Downloads are verified against the .sha256 sidecar via certutil and
rem fail closed: a missing sidecar or hash tool refuses the download. On
rem ARM64 the arm64 asset is tried first and the x64 asset is the
rem fallback (Windows on ARM runs x64 binaries).
if not defined IMPECCABLE_SKILL_DIR set "IMPECCABLE_SKILL_DIR=%~dp0.."
if not defined IMPECCABLE_SELF set "IMPECCABLE_SELF=%~f0"
set "arch=x64"
@@ -81,27 +82,32 @@ curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
if errorlevel 1 goto fail
:verify
rem Mirrors the sh launcher: a missing sidecar or hash tool skips
rem verification; a mismatch is fatal.
rem Mirrors the sh launcher and fails closed: a freshly downloaded binary
rem runs only after verifying against its .sha256 sidecar. A sidecar that
rem cannot be fetched, or an empty certutil result, refuses the download
rem instead of running an unverified binary.
curl.exe -fsSL -o "%cached%.sha256" "%url%.sha256" >nul 2>nul
if not errorlevel 1 goto have_sidecar
del "%cached%.sha256" >nul 2>nul
goto place
:have_sidecar
if errorlevel 1 goto verify_refuse
set "expected="
set /p expected=<"%cached%.sha256"
for /f "tokens=1" %%h in ("%expected%") do set "expected=%%h"
set "actual="
for /f "skip=1 delims=" %%h in ('certutil -hashfile "%cached%.part" SHA256 2^>nul') do if not defined actual set "actual=%%h"
del "%cached%.sha256" >nul 2>nul
if not defined expected goto place
if not defined actual goto place
if not defined expected goto verify_refuse
if not defined actual goto verify_refuse
set "actual=%actual: =%"
if /I "%actual%"=="%expected%" goto place
del "%cached%.part" >nul 2>nul
echo impeccable: checksum mismatch downloading %url% 1>&2
exit /b 127
:verify_refuse
del "%cached%.part" >nul 2>nul
del "%cached%.sha256" >nul 2>nul
echo impeccable: cannot verify %url% against %url%.sha256; refusing the unverified download 1>&2
exit /b 127
:place
move /y "%cached%.part" "%cached%" >nul 2>nul
if not exist "%cached%" goto fail