Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions .github/workflows/governance-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1131,27 +1131,22 @@ jobs:
done
[ $failed -eq 1 ] && { echo "Add SPDX header + permissions:"; exit 1; }
echo "All workflows have SPDX headers + permissions"
- name: Check SHA-pinned actions
- name: Check locked or SHA-pinned actions
env:
GH_TOKEN: ${{ github.token }}
run: |
if [ -f .github/workflows/actions.lock ]; then
# The lockfile records transitive dependency evidence, while direct
# workflow references remain visibly SHA-pinned. Keep both layers:
# external analysers and GitHub's sha_pinning_required setting do
# not infer direct pins from actions.lock.
# actions.lock is the authoritative immutable resolution for both
# direct actions and their transitive dependencies. Do not also
# rewrite direct refs to raw SHAs: gh actions-lock omits refs that
# no tag or branch contains, and GitHub then rejects the workflow
# at startup. Measured in oikosbot PR #78 on 2026-08-29: five
# previously executable workflows became startup_failure after the
# redundant direct-SHA conversion; restoring their locked version
# refs made GitHub's native resolver accept them again.
gh extension install github/gh-actions-lock
bash "$RUNNER_TEMP/update-actions-lock.sh" --verify-local
unpinned=$(grep -rnE --include='*.yml' --include='*.yaml' \
"^[[:space:]]+uses:" .github/workflows/ | \
grep -v "@[a-f0-9]\{40\}" | \
grep -v "uses: \./\|uses: docker://\|uses: hyperpolymath/standards/" || true)
if [ -n "$unpinned" ]; then
echo "ERROR: direct workflow references not SHA-pinned:"
echo "$unpinned"
exit 1
fi
echo "Lockfile coverage verified; direct references SHA-pinned"
echo "Immutable direct and transitive lockfile coverage verified"
else
unpinned=$(grep -rnE --include='*.yml' --include='*.yaml' \
"^[[:space:]]+uses:" .github/workflows/ | \
Expand Down
7 changes: 4 additions & 3 deletions scripts/check-action-pins-resolve.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ set -uo pipefail
# check-action-pins-resolve.sh — verify every SHA-pinned action actually EXISTS.
#
# ── Why this gate exists ────────────────────────────────────────────────────
# The governance linter's "Check SHA-pinned actions" step verifies the *shape*
# of a pin (`@` + 40 hex chars). It cannot tell a real commit from an invented
# one, because a fabricated SHA is a perfectly well-formed 40-hex string.
# The governance linter's "Check locked or SHA-pinned actions" step delegates
# lockfile integrity to gh actions-lock. For repositories without a lockfile it
# verifies the *shape* of each direct pin (`@` + 40 hex chars), but cannot tell
# a real commit from an invented one: a fabricated SHA is still well formed.
#
# That gap is not theoretical. Measured across the estate on 2026-07-28:
#
Expand Down
Loading