mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-19 09:36:59 +03:00
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:
co-authored by
Claude Code
parent
fe30578c8a
commit
b9902222d9
+26
-11
@@ -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" "$@"
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user