Repository navigation
feat(action): squabble consumer action — pinned sha256 + attestation - #128
Merged
Merged
Conversation
Add .github/actions/squabble, a composite action that installs the squabble v0.1.0 release binary for other workflows and optionally runs it. install.sh downloads the asset into a fresh directory and refuses it unless (1) its sha256 equals the pinned digest and (2) gh attestation verify --format json accepts it for this repo's release.yml at refs/tags/v0.1.0, source commit b854d17, SLSA provenance v1, no self-hosted runner, and the JSON names the asset with that digest. Only then is it made executable, version-checked and put on PATH. run.sh passes args one per line, literally, and records exit-code. tests/squabble_action_test.sh (27 cases) checks action.yml runs exactly the tested scripts and env (4 planted mutants refused), the JSON check offline, run.sh against a stand-in binary, digest and attestation against the real asset and a one-byte tampered copy, and install.sh end to end with a shimmed tampered download (refused, PATH untouched). The new squabble-action.yml workflow runs the suite and then the two scripts as the composite does. It has no uses: at all: actions.lock does not support local-path actions (gh actions-lock --no-fix refuses `uses: ./`), so GitHub's evaluation of action.yml itself is first exercised by a caller pinning a merged main SHA. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bTuGfwCcvjrmNFejydTML
Contributor
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configuration
⛔ Files ignored due to path filters (1)
📒 Files selected for processing (7)
✨ Finishing Touches📝 Generate docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Adds
.github/actions/squabble, a composite action other workflows can use to install the squabble v0.1.0 release binary and, optionally, run it. It refuses any download whose sha256 is not the pinned digest, or whose build attestation does not trace to this repo'srelease.ymlatv0.1.0and its source commit. Nothing is executed until both checks pass.This is the prerequisite for running
squabble verify-satisfiedfrom CI (the central board and thesemantic-audit-checkplaceholders). Those still wait on the read-only GitHub App, becauseverify-satisfiedneeds Administration: read, whichgithub.tokencannot hold.Changes
.github/actions/squabble/install.sh: download into a fresh dir → sha256 must equal6cbeb457…026c→gh attestation verify --format jsonwith--repo,--signer-workflow …/release.yml,--source-ref refs/tags/v0.1.0,--source-digest b854d17a…,--predicate-type https://slsa.dev/provenance/v1,--deny-self-hosted-runners. The JSON is then read back: it must be a non-empty array in which every result names the asset with the pinned digest. Only then:chmod,--versionmust besquabble 0.1.0, PATH andpathoutput. JSON is used because the plain-text output has been seen empty with exit 0 off a TTY..github/actions/squabble/run.sh:argsone per line, literal (no globbing or splitting), blank lines dropped. Exit code captured with|| rc=$?and written asexit-code..github/actions/squabble/action.yml: KYAML (D280). Install always usesgithub.token; run mode uses thetokeninput, so an App token can be passed forverify-satisfied.tests/squabble_action_test.sh: 27 cases across five sections; see Testing..github/workflows/squabble-action.yml: block YAML, because this repo's linter greps^permissions:and its governance pin predates13b872c1. It has nouses:at all (git checkout in a run step, likelock-sync-gate.yml)..github/workflows/actions.lock:'.github/workflows/squabble-action.yml': []..github/actions/squabble/README.adoc,CHANGELOG.adoc.📌 New pins
2edc515d3e23e69d017910d8e9146f5fd0e1ecc0squabble-x86_64-linux-muslsha256:6cbeb4577d83ccf2dea3405a3afb0d34b7fee422af73f2113d413ea7edba026c(matches the release's ownSHA256SUMS)b854d17abc0dce296719a349ebe856ff945cf03e(v0.1.0^{commit})hyperpolymath/cicd-squabbler/.github/workflows/release.yml, source refrefs/tags/v0.1.0'.github/workflows/squabble-action.yml': []. No actionuses:SHAs are added or changed anywhere.RSR Quality Checklist
Required
just testor equivalent):just testnot run, because this PR changes no Rust code. The new suitetests/squabble_action_test.shran 27/27, and the repo's workflow and lock gates pass (see Testing).kyaml-format.sh --check action.ymlrc=0; the shell follows the repo's existing style.shellcheck -xrc=0 on all three scripts;actionlintrc=0 on the new workflow. Repo-wide actionlint findings are all in pre-existing workflows.unsafeblocks without// SAFETY:comments: not applicable, no Rust touched..envfiles included.As Applicable
STATEdescriptile: not applicable; no descriptile is edited (A2ML is retired estate-wide and is not written to).ECOSYSTEMdescriptile: not applicable, for the same reason.METAdescriptile: not applicable, for the same reason..github/actions/squabble/README.adoccovers usage, what is checked, the pins, how to bump, and what is not yet tested.TOPOLOGY.mdupdated: not applicable, no architecture change.CHANGELOGupdated: Unreleased → Added.gh,jqandyq, which are preinstalled onubuntu-latest.Testing
Run locally on head
2edc515:bash tests/squabble_action_test.sh→27 passed, 0 failed, 27 of 27 planned cases ran. The five sections:install.shand thenrun.sh(only whenargsis set), with exactly the tested env and nouses:. Four planted mutants are each refused, naming the mismatch: another script, an extrauses:step,github.tokenswapped into run mode, the run step'sif:removed. A further case checks that both scripts are executable.*,$HOMEand backticks passed literally, empty args, non-zero exit passed through and recorded, missing binary → rc 1 with nothing recorded.gh release downloadshimmed to serve the tampered copy, it is refused and writes nothing toGITHUB_PATHorGITHUB_OUTPUT. The real download installs and records both.verify_digestmismatch →return 0turns only "tampered copy: sha256" red. The end-to-end tampered install is still refused by the attestation.length > 0turns only "empty array" red.scripts/check-lock-sync.shrc=0;gh actions-lock --no-fix(v0.1.6) rc=0.tests/workflows/validate_workflows_test.shpassed with 0 errors. Its 4 warnings are the pre-existing missingnpm-bun-blocker.ymlandts-blocker.yml.scripts/check-root-shape.shrc=0.workflow-linter.ymlSPDX and^permissions:checks pass; the new workflow adds 0 lines to its unpinned-uses:list.standards/.githooks/docstring-scan.sh --worktree --check: 24/24 functions documented.scripts/validate-template.shfails onmainalready, for files this PR does not touch:npm-bun-blocker.yml,ts-blocker.ymlandCONTRIBUTING.adoc.CI on this head (
2edc515)Squabble Consumer Action(run 37924918914): green onubuntu-latest. The suite ran 27 of 27 planned cases. The real install was verified by sha256 and attestation (installed squabble 0.1.0 … attestation verified), andsquabbleresolved on PATH in a later step. Run mode returnedexit-code0for--version, and2with outcomefailurefor--no-such-flag.scan / gitleaks: success. It is the only required context. Effective rules onmainaredeletion,non_fast_forwardandrequired_status_checks.lint-workflows(Workflow Security Linter, step "Check SHA-Pinned Actions"): red, and pre-existing. It is red onmainatb854d17too, failing on the same list of 31 tag-pinned refs plus 5actions.locklines.squabble-action.ymladds no line to that list, because it contains nouses:.lint-workflowsis deferred to lint-workflows: Check SHA-Pinned Actions red on main (31 tag-pinned refs + 5 actions.lock false positives) #127 (acceptance: the step is green onmain, the 31 refs are SHA-pinned and lock-covered, and the linter no longer readsactions.lock).mainatb854d17.🟡 CHECK: Standards pipeline:startup_failure, which is pre-existing. 27 of its 30 runs since 2026-09-22 ended this way. A startup failure creates no check-run, so it is absent from this PR's rollup. It is logged for the owner in the findings inbox, not fixed here.Not covered here: GitHub's own evaluation of
action.yml, meaning composite inputs and outputs, the run step'sif:, and whetherexit-codeis readable when the run step fails. This repo has anactions.lock, andgh actions-lock --no-fixrefuses local-path actions ("workflow uses local path actions which are not supported"), so the workflow cannot calluses: ./.github/actions/squabble. Instead it runs the two scripts exactly as the composite's steps do, and section 0 pins action.yml to that wiring. GitHub's evaluation is first exercised by a caller that pinshyperpolymath/cicd-squabbler/.github/actions/squabble@<merged main SHA>, which the lockfile does support. That caller must assertexit-codeon a failing run.Screenshots
Not applicable.
🤖 Generated with Claude Code
https://claude.ai/code/session_015bTuGfwCcvjrmNFejydTML