Skip to content

Commit 3216933

Browse files
hyperpolymathclaude
andcommitted
fix(ci): harden ci-pipeline downloads and bun installs (#899)
Clears all 6 MAJOR findings behind SonarCloud's failing quality gate on PR #899 (new_security_rating 3 = C, required <= 1 = A). All six are in this file, which this PR introduced, so none is pre-existing debt. S6506 x2 -- curl followed redirects with no scheme restriction, so a redirect could downgrade https to http. Both downloads are sha256 checked, which bounds the damage but does not remove the exposure: the bytes still travel in clear. Now --proto '=https' --proto-redir '=https' --tlsv1.2, which refuses the downgrade on the initial request AND on every hop. S6505 -- `bun install` ran lifecycle scripts. The comment defending that is falsified: MEASURED against the registry today, rescript 11.1.4 declares postinstall 'node scripts/rescript_postinstall.js' but 12.3.1 declares none, shipping per-platform optionalDependencies instead. The flag therefore only costs anything on the superseded major, and ReScript is a banned language here regardless -- this job lints grandfathered sources. Scripts now off, with a hard error (not a silent skip) if the compiler is absent afterwards. S8543 x3 -- `bun install` could resolve a floating range and `bunx rescript` fetches latest from the registry. Together those let CI lint with a DIFFERENT compiler than the repo pins, so this is a correctness defect as much as a supply-chain one. Now --frozen-lockfile, and `bunx --no-install` at all four call sites (Sonar flagged two; the other two share the defect and are fixed with them). Verified: YAML parses; all 14 run blocks pass `bash -n`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ji1bq3TypfycfUPAR7hSxR
1 parent 0f904e1 commit 3216933

1 file changed

Lines changed: 27 additions & 8 deletions

File tree

‎.github/workflows/ci-pipeline.yml‎

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ jobs:
338338
run: |
339339
set -euo pipefail
340340
URL="https://github.com/tweag/nickel/releases/download/${NICKEL_VERSION}/nickel-x86_64-linux"
341-
curl -sSfL --retry 3 -o "$RUNNER_TEMP/nickel" "$URL"
341+
curl -sSfL --proto '=https' --proto-redir '=https' --tlsv1.2 --retry 3 -o "$RUNNER_TEMP/nickel" "$URL"
342342
echo "${NICKEL_SHA256} ${RUNNER_TEMP}/nickel" | sha256sum -c -
343343
chmod +x "$RUNNER_TEMP/nickel"
344344
echo "$RUNNER_TEMP" >> "$GITHUB_PATH"
@@ -536,9 +536,28 @@ jobs:
536536
shell: bash
537537
run: |
538538
set -euo pipefail
539-
# ReScript's compiler binary arrives via a postinstall script, so
540-
# --ignore-scripts would leave nothing to run.
541-
bun install
539+
# An npm lifecycle script is arbitrary code execution at CI
540+
# privilege, so scripts stay off. MEASURED 2026-09-22 against the
541+
# registry: rescript 11.1.4 declares postinstall
542+
# 'node scripts/rescript_postinstall.js', but 12.3.1 declares NO
543+
# postinstall at all -- it ships the compiler as per-platform
544+
# optionalDependencies. So the flag only costs anything on the
545+
# superseded major, and ReScript is a banned language here in any
546+
# case: this job exists to lint grandfathered sources, not to make
547+
# legacy installs convenient.
548+
#
549+
# --frozen-lockfile is the other half: without it bun may resolve a
550+
# floating range, and CI would then be testing a compiler the repo
551+
# does not pin.
552+
bun install --frozen-lockfile --ignore-scripts
553+
554+
# A missing binary after that install must be an ERROR, not a
555+
# silent fall-through to a build step that cannot run. A skip is
556+
# not a pass.
557+
if ! bunx --no-install rescript -h >/dev/null 2>&1; then
558+
echo "::error::rescript is not present after a --frozen-lockfile --ignore-scripts install. Upgrade to rescript >= 12, which needs no lifecycle script, or add the compiler to the lockfile. Lifecycle scripts are deliberately not enabled in this workflow."
559+
exit 1
560+
fi
542561
543562
- name: ReScript build (warnings are errors) + format check
544563
shell: bash
@@ -549,14 +568,14 @@ jobs:
549568
# A compile IS the lint for ReScript; -warn-error +a promotes every
550569
# warning. This writes to lib/, which is compiler output and not a
551570
# tracked source file.
552-
bunx rescript build -with-deps -warn-error +a || FAILED=1
571+
bunx --no-install rescript build -with-deps -warn-error +a || FAILED=1
553572
554573
# `rescript format` gained -check at different points in different
555574
# majors. Probe for the capability rather than assume it: a gate that
556575
# fails because the flag does not exist tells you nothing about the
557576
# code, and one that silently passes tells you less.
558-
if bunx rescript format --help 2>&1 | grep -q -- '-check'; then
559-
bunx rescript format -all -check || { echo "::error::ReScript sources are not formatted"; FAILED=1; }
577+
if bunx --no-install rescript format --help 2>&1 | grep -q -- '-check'; then
578+
bunx --no-install rescript format -all -check || { echo "::error::ReScript sources are not formatted"; FAILED=1; }
560579
FMT='checked'
561580
else
562581
echo "::warning::The installed rescript CLI has no 'format -check'; the format gate did NOT run. This is a skip, not a pass."
@@ -601,7 +620,7 @@ jobs:
601620
run: |
602621
set -euo pipefail
603622
URL="https://github.com/vlang/v/releases/download/${V_VERSION}/v_linux.zip"
604-
curl -sSfL --retry 3 -o "$RUNNER_TEMP/v_linux.zip" "$URL"
623+
curl -sSfL --proto '=https' --proto-redir '=https' --tlsv1.2 --retry 3 -o "$RUNNER_TEMP/v_linux.zip" "$URL"
605624
echo "${V_SHA256} ${RUNNER_TEMP}/v_linux.zip" | sha256sum -c -
606625
unzip -q "$RUNNER_TEMP/v_linux.zip" -d "$RUNNER_TEMP"
607626
echo "$RUNNER_TEMP/v" >> "$GITHUB_PATH"

0 commit comments

Comments
 (0)