fix(install): validate --commit SHA and fail hard on fetch/checkout errors (#87268)

Three problems with install.sh --commit:

1. No validation: non-hex or too-short arguments passed through to git,
   producing misleading errors.

2. Fetch failure swallowed by || true: abbreviated SHAs are refused by
   GitHub's server ("couldn't find remote ref"), but the error was
   silently ignored.

3. Checkout failure not checked: git checkout --detach with a missing
   object produces a misleading "does not take a path argument" error
   and the install continues unpinned, exiting 0.

Fix:
- Validate --commit is a 7-40 hex string up front
- Remove || true from fetch; fail with actionable message directing
  users to full 40-char SHAs
- Check git checkout --detach result and fail hard on error

Fixes #87268
This commit is contained in:
RelaxJonh
2026-08-16 10:43:40 +07:00
committed by Teknium
parent f887819421
commit eac1f65340

View File

@@ -1384,6 +1384,13 @@ EOF
cd "$INSTALL_DIR"
if [ -n "$INSTALL_COMMIT" ]; then
# Validate the commit argument: must look like a hex SHA (full 40-char
# or abbreviated 7-39 char). Reject anything else early so the user
# gets a clear error instead of a misleading git message (#87268).
if ! printf '%s' "$INSTALL_COMMIT" | grep -qE '^[0-9a-fA-F]{7,40}$'; then
log_error "--commit expects a hex SHA (7-40 chars), got: $INSTALL_COMMIT"
return 1
fi
# A commit pin must never move an existing install BACKWARDS. The
# bootstrap installer bakes its build-time commit into the binary
# (BUILD_PIN_COMMIT) and passes it as --commit on every install-mode
@@ -1393,21 +1400,32 @@ EOF
# current venv. Only pin when the target is not already an ancestor of
# HEAD; a fresh clone has no such ancestry and pins normally.
if ! git cat-file -e "$INSTALL_COMMIT^{commit}" 2>/dev/null; then
git fetch origin "$INSTALL_COMMIT" || true
if ! git fetch origin "$INSTALL_COMMIT"; then
log_error "Could not fetch commit $INSTALL_COMMIT from origin."
log_error "Abbreviated SHAs are not supported — use the full 40-char hash."
log_error "Find it with: git ls-remote origin | grep <short-sha>"
return 1
fi
fi
if git rev-parse --verify --quiet HEAD >/dev/null 2>&1 \
&& git merge-base --is-ancestor "$INSTALL_COMMIT" HEAD 2>/dev/null \
&& [ "$(git rev-parse "$INSTALL_COMMIT^{commit}" 2>/dev/null)" != "$(git rev-parse HEAD)" ]; then
if [ "$FORCE_COMMIT" = true ]; then
log_warn "--force-commit: rolling this install back to $INSTALL_COMMIT."
git checkout --detach "$INSTALL_COMMIT"
if ! git checkout --detach "$INSTALL_COMMIT"; then
log_error "Failed to detach at $INSTALL_COMMIT"
return 1
fi
else
log_warn "Ignoring --commit $INSTALL_COMMIT: the checkout is already newer."
log_warn "Pinning to it would roll this install back. Pass --force-commit to override."
fi
else
log_info "Pinning checkout to commit $INSTALL_COMMIT..."
git checkout --detach "$INSTALL_COMMIT"
if ! git checkout --detach "$INSTALL_COMMIT"; then
log_error "Failed to detach at $INSTALL_COMMIT"
return 1
fi
fi
fi