ci: supply-chain hardening (Phase 1 closure — RED-1, RED-2, TEST-L2)

Three findings from the certctl architecture diligence audit's Phase 1
bundle (Supply-Chain Hardening) closed together in one PR since they all
touch .github/workflows/ + repo root.

RED-1 — delete tracked precompiled binary
  - deploy/test/f5-mock-icontrol/f5-mock-icontrol (8.6 MB ARM64 ELF) was
    tracked alongside the Go source that builds it. The fixture's
    Dockerfile already uses a multi-stage build that re-runs
    'go build' inside the container (line 13), so the tracked binary
    was vestigial — never actually consumed by the test wiring.
  - git rm'd. Path added to .gitignore so it doesn't re-land.
  - No Makefile target needed; the Dockerfile is the rebuild path.

RED-2 — SHA-pin every GitHub Action
  - Pre: 37 of 41 'uses:' lines were tag-pinned (@v4 etc); only
    4 were SHA-pinned (sigstore/cosign-installer + anchore/sbom-action).
  - Post: 0 / 41. Every 'uses:' line is now '@<40-char-sha>  # vN'
    (the trailing comment preserves the human-readable version for
    operator audit). SHA-pinning closes the standard supply-chain
    attack vector against GitHub Actions consumers.
  - SHAs resolved live via the GitHub API; spot-checked one.

TEST-L2 — npm audit hard gate
  - Added 'npm audit --omit=dev --audit-level=high' step to the
    Frontend Build job in ci.yml. --omit=dev excludes vitest/vite/
    eslint/etc which don't ship to operators.
  - Local run today: 0 vulnerabilities; gate enters with no triage
    backlog. Catches future regressions.

New CI guards (regression-prevention):
  - scripts/ci-guards/no-tag-pinned-actions.sh — fails the build if
    a future PR adds 'uses: foo/bar@v2' instead of SHA-pinning.
  - scripts/ci-guards/no-precompiled-binary.sh — runs file(1) over
    git ls-files output; fails on any tracked ELF/Mach-O/PE.
  - Both pass locally. CI's existing loop over scripts/ci-guards/*.sh
    picks them up automatically.

Closes: cowork/certctl-architecture-diligence-audit.html#fix-RED-1,
        cowork/certctl-architecture-diligence-audit.html#fix-RED-2,
        cowork/certctl-architecture-diligence-audit.html#fix-TEST-L2
This commit is contained in:
shankar0123
2026-05-13 19:30:53 +00:00
parent de8fac24a3
commit 95cb002905
9 changed files with 160 additions and 37 deletions
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env bash
# scripts/ci-guards/no-precompiled-binary.sh
#
# Phase 1 RED-1 closure (2026-05-13): no precompiled binary (ELF /
# Mach-O / PE) should ever be tracked in the repo. The original
# Phase 1 trigger was `deploy/test/f5-mock-icontrol/f5-mock-icontrol`
# — an 8.6 MB ARM64 ELF that lived in git alongside the Go source
# that builds it. The Dockerfile for that fixture already runs
# `go build` from source inside the container, so the tracked
# binary was vestigial. Deleting it cost nothing; tracking it cost
# 8.6 MB per clone forever.
#
# This guard scans every TRACKED file (i.e. what an external clone
# sees, not what's in the operator's working tree) and uses `file(1)`
# to detect compiled executables. Any hit fails the build with a
# clear pointer to the right fix.
#
# Allowlist:
# - PNG / JPG / PDF / SVG / GIF / WebP — image assets are not
# binaries in the supply-chain sense even though `file` reports
# them as "executable" in some encodings.
# - Specific large fixtures that legitimately need to be tracked
# (e.g. canonical certificate test vectors). Add to the
# allowlist with a rationale comment.
#
# Mirror of the B6-no-private-keys-in-tree.sh pattern.
set -e
# What `file(1)` outputs we treat as a binary smell. ELF / Mach-O /
# PE / Java class / WebAssembly all qualify. Image / archive / text
# formats do NOT.
BAD_TYPES='ELF|Mach-O|PE32|PE32\+|compiled Java class|WebAssembly'
VIOLATIONS=$(git ls-files -z \
| xargs -0 file --brief --separator='|' --print0 2>/dev/null \
| tr '\0' '\n' \
| grep -E "$BAD_TYPES" \
| grep -vE '^$' \
|| true)
if [ -n "$VIOLATIONS" ]; then
echo "::error::no-precompiled-binary regression: tracked executable file(s) found:"
echo ""
echo "$VIOLATIONS"
echo ""
echo "Precompiled binaries must not be tracked. If this is a test"
echo "fixture, route the build through a Dockerfile / Makefile target"
echo "that rebuilds from source. If it is a legitimate exception,"
echo "add the path to the allowlist in scripts/ci-guards/no-precompiled-binary.sh"
echo "with a rationale comment."
exit 1
fi
echo "no-precompiled-binary guard OK: no tracked ELF / Mach-O / PE / class / wasm binaries"