Skip to content

fix(pins): read action definitions from the raw host, not the contents API - #180

Merged
rldyourmnd merged 1 commit into
mainfrom
fix/pins-read-raw
Aug 15, 2026
Merged

fix(pins): read action definitions from the raw host, not the contents API#180
rldyourmnd merged 1 commit into
mainfrom
fix/pins-read-raw

Conversation

@rldyourmnd

Copy link
Copy Markdown
Contributor

Follow-up to #179, found by running the sweep it fixed.

What the corrected walk still could not do

With the graph walk fixed, the sweep still failed — but now with an honest message:

aquasecurity/trivy-action@ed142fd...: nested pins unverified, HTTP 403 after 1 attempt(s)
bridgecrewio/checkov-action@9b70310...: nested pins unverified, HTTP 403 after 1 attempt(s)

after 1 attempt(s) is the tell: the new rate-limit classifier correctly declined to
retry, because this is not throttling. Two of forty-three pins, consistently.

Both repositories are public, not archived, not disabled, and both serve fine:

repos/…/contents/action.yml
personal token 200
no credential 200
Actions GITHUB_TOKEN 403

The difference is the credential. Actions' GITHUB_TOKEN is an installation token
scoped to this repository; those two repositories refuse it for cross-repository
content reads while forty-one others do not. The check could never complete in the
job that owns it
— and that was invisible until the sweep first ran.

Fix

raw.githubusercontent.com serves every definition at the exact pinned commit with
no credential, and the host was already in the sweep's egress allow-list:

aquasecurity/trivy-action    action.yaml  -> 200
bridgecrewio/checkov-action  action.yml   -> 200

(The action.yml / action.yaml split is real and already handled by the existing
candidate logic.)

So the check now needs no token. That also removes the 60-requests-an-hour
unauthenticated ceiling that made a token necessary in the first place, so it can no
longer be throttled into reporting a third party as broken.

$ env -u GH_TOKEN -u GITHUB_TOKEN … --tier scheduled
[ OK ] transitive-action-pins

Honest limit

A private action would 404 here and be reported as having no definition. That is
correct for a tree that pins only public actions, and it is a visible failure rather
than a silent pass. Stated rather than discovered later.

Contract

catalog/validation-tiers.yml records the swap: transitive-action-pins now needs
network:raw.githubusercontent.com and nothing else. api.github.com stays for
anchor-contexts, which reads the live ruleset.

Removing the host from the allow-list is caught:

maintenance.yml: job 'sweep' runs the 'scheduled' tier, which reaches
raw.githubusercontent.com, but the harden-runner allow-list does not include it

Verification

  • validate_all — all tiers OK; --tier scheduled now passes without any token
    except anchor-contexts, which legitimately needs one
  • actionlint — clean

…s API

With the graph walk corrected, the first real sweep still failed on two of
forty-three pins -- aquasecurity/trivy-action and bridgecrewio/checkov-action
-- with a plain 403 that was not a rate limit. Both serve normally to a
personal token and to no token at all.

The difference is the credential. Actions' GITHUB_TOKEN is an installation
token scoped to this repository, and those two repositories refuse it for
cross-repository content while forty-one others do not. The check could
therefore never complete in the very job that owns it.

raw.githubusercontent.com serves all of them at the exact pinned commit with
no credential, and the host was already in the sweep's egress allow-list. The
check now needs no token at all, which also removes the 60-requests-an-hour
ceiling that made a token necessary to begin with -- it can no longer be
throttled into reporting a third party as broken.

A private action would 404 here and be reported as having no definition. That
is correct for a tree pinning only public actions, and it fails visibly.

catalog/validation-tiers.yml records the swap; api.github.com stays for
anchor-contexts reading the live ruleset.
@github-actions github-actions Bot added ci Continuous integration and removed ci Continuous integration labels Aug 15, 2026
@rldyourmnd
rldyourmnd merged commit 6ce6f3f into main Aug 15, 2026
29 checks passed
@rldyourmnd
rldyourmnd deleted the fix/pins-read-raw branch August 15, 2026 00:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant