Skip to content

Commit 6279782

Browse files
committed
verify-action-build: treat verifier-action refs as trust leaves
The sibling-step recognition added in the previous commit handles the caller of a verifier (e.g. sbt/setup-sbt using carabiner-dev/actions/ ampel/verify), but the recursive walker still descended into the verifier action itself and surfaced its bootstrap installer (carabiner-dev/actions/install/ampel) as an unverified download. The bootstrap installer cannot itself verify the verifier binary (chicken-and-egg). Treat the hash-pinned verifier ref as a trust leaf — same handling as TRUSTED_ORGS — so the walker stops there. The trust anchor is the hash-pinned commit of the verifier action itself; ASF's separate allowlist review covers admission of new verifier refs to the trust set. Generated-by: Claude Opus 4.7 (1M context) <[email protected]>
1 parent 6acddcc commit 6279782

2 files changed

Lines changed: 46 additions & 1 deletion

File tree

utils/tests/verify_action_build/test_security.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,33 @@ def fake_action_yml(org, repo, commit, sub_path=""):
482482
)
483483
assert failures == []
484484

485+
def test_skips_trusted_verifier_ref(self):
486+
# Mirrors sbt/setup-sbt → carabiner-dev/actions/ampel/verify →
487+
# install/ampel: descending into the verifier surfaces a bootstrap
488+
# installer that can't verify itself. The walker treats the verifier
489+
# ref as a trust leaf and stops there.
490+
root_yml = """\
491+
name: Root
492+
runs:
493+
using: composite
494+
steps:
495+
- uses: carabiner-dev/actions/ampel/verify@dddddddddddddddddddddddddddddddddddddddd
496+
"""
497+
498+
def fake_action_yml(org, repo, commit, sub_path=""):
499+
if org == "myorg":
500+
return root_yml
501+
raise AssertionError(
502+
f"should not fetch nested yml for {org}/{repo}/{sub_path}"
503+
)
504+
505+
with mock.patch("verify_action_build.security.fetch_action_yml", side_effect=fake_action_yml):
506+
with mock.patch("verify_action_build.security.fetch_file_from_github", return_value=None):
507+
warnings, failures = analyze_binary_downloads_recursive(
508+
"myorg", "rootrepo", "b" * 40,
509+
)
510+
assert failures == []
511+
485512

486513
class TestAnalyzeRepoMetadata:
487514
def test_mit_license_detected(self):

utils/verify_action_build/security.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,24 @@
4141
# Orgs we trust to the point of not descending into their nested action graph.
4242
TRUSTED_ORGS = {"actions", "github"}
4343

44+
# Verifier-action references that are treated as trust leaves. When a parent
45+
# action.yml `uses:` one of these, the walker yields the visit as a stub and
46+
# does not descend into the verifier's own action graph.
47+
#
48+
# Why: a verification action is itself the root of the artifact-trust chain
49+
# from its caller's perspective. Descending in would surface its bootstrap
50+
# installer (e.g. carabiner-dev/actions/install/ampel), which downloads the
51+
# verifier binary without an inline checksum/signature — a chicken-and-egg
52+
# problem the installer cannot solve. We accept the verifier ref's
53+
# hash-pinned commit as the trust anchor instead.
54+
#
55+
# Each entry is (org, repo, sub_path). Keep in sync with
56+
# `_VERIFICATION_USES_PATTERNS` below — same identities, different layer.
57+
TRUSTED_VERIFIER_REFS: set[tuple[str, str, str]] = {
58+
("carabiner-dev", "actions", "ampel/verify"),
59+
("slsa-framework", "slsa-verifier-action", ""),
60+
}
61+
4462
# Exemptions file for the lock-file-presence check. Path matches the
4563
# convention used by approved_actions.ACTIONS_YML.
4664
LOCK_FILE_EXEMPTIONS_YML = (
@@ -161,7 +179,7 @@ def _walk(
161179
)
162180
return
163181

164-
trusted = o in TRUSTED_ORGS
182+
trusted = o in TRUSTED_ORGS or (o, r, s) in TRUSTED_VERIFIER_REFS
165183
if depth > 0 and trusted:
166184
yield VisitedAction(
167185
org=o, repo=r, commit_hash=c, sub_path=s, depth=depth,

0 commit comments

Comments
 (0)