Summary
Extend reusable_ci.yml with a new verify-action-shas job that validates all
SHA-pinned action references in .github/workflows/*.yml resolve to real commits
in their referenced repositories. This prevents workflows from breaking at runtime
due to invalid, hallucinated, or typo'd commit SHAs.
Motivation
In PR complytime/.github#114,
actions/setup-node was pinned to a SHA that did not exist in the repository. The
YAML was syntactically valid, so all local checks (lint, build, tests) passed. The
error was only discovered when the workflow executed and GitHub could not resolve
the SHA.
This failure mode is increasingly common with AI-assisted workflow authoring, where
agents may write SHAs from training data rather than sourcing them from the API.
No validation exists today -- locally or in CI -- to catch invalid SHAs before merge.
Proposed Change
Add a verify-action-shas job to reusable_ci.yml that runs in parallel with
the existing megalinter job. The job:
- Checks out the repository
- Parses all
.github/workflows/*.yml files for uses: references
- Extracts
owner/repo@sha patterns (skipping local ./ and docker://
references)
- For each unique
owner/repo@sha, verifies the SHA resolves via the GitHub API
- When a version comment is present (e.g.,
# v6.0.2), verifies the SHA
matches the resolved tag
- When a version comment is absent, warns the author to include one as a best
practice (does not fail)
Input
inputs:
enable_action_sha_verify:
description: 'Enable GitHub Actions SHA verification'
type: boolean
default: true
Verification Behavior
| Condition |
Result |
Severity |
| SHA does not resolve (404) |
Fail |
Error |
| SHA resolves, version comment present, tag matches |
Pass |
-- |
| SHA resolves, version comment present, tag mismatch |
Fail |
Error |
| SHA resolves, no version comment |
Pass with warning |
Warning |
| Cross-org private repo (404 but may be auth) |
Pass with warning |
Warning |
Local action (./path) |
Skip |
-- |
Docker action (docker://) |
Skip |
-- |
Edge Cases
| Case |
Handling |
Reusable workflow paths (owner/repo/.github/workflows/file.yml@sha) |
Strip path, verify against owner/repo |
| Annotated tags (tag object SHA != commit SHA) |
Dereference: fetch tag object, follow .object.url to get commit SHA |
| Lightweight tags (ref points directly to commit) |
Direct comparison |
| Rate limiting |
Deduplicate owner/repo@sha pairs before verification; typical repo has <20 unique refs |
Self-referencing (uses: ./.github/workflows/...) |
Skip (local path) |
Failure Mode
The verify-action-shas job SHOULD be configured as a required status check
in branch protection rules. An invalid SHA will break the workflow at runtime
regardless -- failing the check early is strictly better than discovering the
problem post-merge.
Impact on Consumers
- Zero integration burden: existing consumers get SHA verification
automatically on next SHA bump to a version that includes this change
- Opt-out available:
enable_action_sha_verify: false disables the check
- No new permissions: the job needs only
contents: read (already granted);
the default GITHUB_TOKEN authenticates API calls to public repos (5000
req/hr rate limit)
- Non-blocking to existing job: runs in parallel with
megalinter
Consumers (9 repos)
- complytime/.github
- complytime/complyctl
- complytime/complytime-demos
- complytime/org-infra
- complytime/complytime-collector-components
- complytime/gemara-content-service
- complytime/complytime-website
- unbound-force/unbound-force
- complytime/complytime-providers
Acceptance Criteria
Related
- Convention pack rule:
CI-002 in the Unbound Force ci.md convention
pack (being developed separately) codifies the authoring-time prevention for
AI agents and human authors. This CI job is the enforcement layer.
- Severity classification: The Adversary severity table already classifies
"unpinned CI action on mutable tag" as HIGH. An invalid SHA is CRITICAL --
the workflow will fail to execute.
Summary
Extend
reusable_ci.ymlwith a newverify-action-shasjob that validates allSHA-pinned action references in
.github/workflows/*.ymlresolve to real commitsin their referenced repositories. This prevents workflows from breaking at runtime
due to invalid, hallucinated, or typo'd commit SHAs.
Motivation
In PR complytime/.github#114,
actions/setup-nodewas pinned to a SHA that did not exist in the repository. TheYAML was syntactically valid, so all local checks (lint, build, tests) passed. The
error was only discovered when the workflow executed and GitHub could not resolve
the SHA.
This failure mode is increasingly common with AI-assisted workflow authoring, where
agents may write SHAs from training data rather than sourcing them from the API.
No validation exists today -- locally or in CI -- to catch invalid SHAs before merge.
Proposed Change
Add a
verify-action-shasjob toreusable_ci.ymlthat runs in parallel withthe existing
megalinterjob. The job:.github/workflows/*.ymlfiles foruses:referencesowner/repo@shapatterns (skipping local./anddocker://references)
owner/repo@sha, verifies the SHA resolves via the GitHub API# v6.0.2), verifies the SHAmatches the resolved tag
practice (does not fail)
Input
Verification Behavior
./path)docker://)Edge Cases
owner/repo/.github/workflows/file.yml@sha)owner/repo.object.urlto get commit SHAowner/repo@shapairs before verification; typical repo has <20 unique refsuses: ./.github/workflows/...)Failure Mode
The
verify-action-shasjob SHOULD be configured as a required status checkin branch protection rules. An invalid SHA will break the workflow at runtime
regardless -- failing the check early is strictly better than discovering the
problem post-merge.
Impact on Consumers
automatically on next SHA bump to a version that includes this change
enable_action_sha_verify: falsedisables the checkcontents: read(already granted);the default
GITHUB_TOKENauthenticates API calls to public repos (5000req/hr rate limit)
megalinterConsumers (9 repos)
Acceptance Criteria
reusable_ci.ymlhas averify-action-shasjob that runs in parallelwith
megalinter.github/workflows/*.ymland verifies each SHA-pinnedaction resolves to a real commit
(
owner/repo/.github/workflows/file.yml@sha)./) and Docker (docker://) referencestag (handling annotated tag dereferencing)
::warningannotationrecommending the author add one
::warning, not afailure
enable_action_sha_verifyinput (default:true)::errorannotations with the offending file, linenumber, owner/repo, and SHA
Related
CI-002in the Unbound Forceci.mdconventionpack (being developed separately) codifies the authoring-time prevention for
AI agents and human authors. This CI job is the enforcement layer.
"unpinned CI action on mutable tag" as HIGH. An invalid SHA is CRITICAL --
the workflow will fail to execute.