actions: new coronarium actions audit for SHA-pin static analysis#47
Merged
Conversation
Closes harden-runner gap #10. Walks one or more workflow YAMLs and flags every `uses:` ref that isn't pinned to a 40-char commit SHA — the supply-chain analogue of an unpinned dependency. Severity ladder: - Error: third-party with mutable tag/branch (`foo/bar@v1`, `foo/bar@main`) — exits 1. - Warn: first-party (`actions/*`, `github/*`) mutable ref, or a docker image without `@sha256:` digest. `--strict` escalates. - Ok: 40-char SHA pin, local action (`./...`), docker `@sha256:` digest reference. Walks both `jobs.<id>.steps[].uses` and `jobs.<id>.uses` (reusable workflow callers). Composite-action `action.yml` (no top-level `jobs:` block) is treated as out-of-scope and returns no findings. Text + JSON output. Smoke-tested against this repo's own workflows and surfaces real issues (dtolnay/rust-toolchain@stable, several docker/* actions). Tag→SHA auto-resolution via the GitHub API is intentionally deferred — keeping the tool offline. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]> Signed-off-by: bokuweb <[email protected]>
coronarium report
events by kind
denied samples (first 10)
📊 Open the full HTML report locallyrm -rf /tmp/coronarium-25630917601 && gh run download 25630917601 -R bokuweb/sakimori -n coronarium-report -D /tmp/coronarium-25630917601 && (open /tmp/coronarium-25630917601/coronarium-report.html 2>/dev/null || xdg-open /tmp/coronarium-25630917601/coronarium-report.html 2>/dev/null || echo "open file:///tmp/coronarium-25630917601/coronarium-report.html")Requires the |
5 tasks
bokuweb
added a commit
that referenced
this pull request
May 11, 2026
…> points at (#57) Closes the deferred follow-up from #47 (`actions audit`). `sakimori actions audit` was offline-only: it flagged `foo/bar@v1` as a mutable ref but left the user to manually look up what to pin to. New `--resolve` flag (off by default) hits the GitHub REST API and surfaces the resolved SHA on each finding so the user can copy-paste the fix straight from the report. Architecture: - `actions::Resolver` trait keeps the offline path the default and lets tests substitute a deterministic fake. - `actions::GithubResolver` is the concrete impl (`GET /repos/{owner}/{repo}/commits/{ref}` via ureq, reads `GITHUB_TOKEN` to raise the rate limit to 5000/hour). - `actions::resolve_all(&mut findings, &dyn Resolver)` walks findings, caches per `(owner, repo, ref)` so a workflow that uses `actions/checkout@v4` ten times only hits the API once, and populates `Finding::resolved_sha` (or `Finding::resolve_error` when the lookup fails — one rate-limited action shouldn't kill the whole audit). Output: - **text**: indented `→ resolved: <sha>` line under the finding; `→ resolve failed: <reason>` on lookup error. - **JSON**: new `resolved_sha` / `resolve_error` fields on `Finding` (both `skip_serializing_if = "Option::is_none"` so off-by-default consumers see no schema change). 5 new unit tests in `actions::tests` — caching, error isolation, owner/repo extraction edge cases, percent-encoding for `feature/x` style refs. Signed-off-by: bokuweb <[email protected]> Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
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
Closes harden-runner parity gap #10 from the roadmap.
New subcommand
coronarium actions audit <workflow.yml...>walksevery
uses:injobs.<id>.steps[]andjobs.<id>.uses(reusableworkflow callers) and flags references that aren't pinned to a
40-char commit SHA. Pure offline static analysis — no GitHub API
calls.
Severity ladder:
foo/bar@v1,foo/bar@main)actions/*,github/*) mutable tag, or docker image without@sha256:digest./...), docker@sha256:reference--strictescalates Warn → Error. Text + JSON output. Exits non-zerowhen at least one error remains.
Smoke-tested against this repo's own workflows — it correctly
surfaces 17 errors (mostly
dtolnay/rust-toolchain@stable|nightlyand the
docker/*family on@v3/@v6) plus a long warn list ofactions/checkout@v4etc.Composite-action
action.ymlfiles (no top-leveljobs:block) areintentionally treated as out-of-scope — they return an empty
findings list rather than parse errors.
Tag→SHA auto-resolution via the GitHub API is deferred; it would
turn the tool into a network one and require auth.
Test plan
cargo fmt --all -- --checkcargo clippy --workspace --all-targets -- -D warningscargo test --workspace— 13 new unit tests incoronarium-core::actions(107 total in core, all green).github/workflows/*.ymlproduced expected findings + exit code 1🤖 Generated with Claude Code