Skip to content

ci: harden github actions and add a continuous check - #2836

Open
Totara-thib wants to merge 3 commits into
validatorjs:masterfrom
Totara-thib:ci-hardening
Open

ci: harden github actions and add a continuous check#2836
Totara-thib wants to merge 3 commits into
validatorjs:masterfrom
Totara-thib:ci-hardening

Conversation

@Totara-thib

Copy link
Copy Markdown

Hi, drive-by CI hardening in three commits, one logical change each.

Commit 1 pins every action to its commit sha, versions kept as comments. A tag like @v5 is a movable pointer: whoever controls the action, or anyone who compromises it, can re-point it and your next run executes their code with the job's token. This repo publishes to npm from CI, so the release path deserves frozen inputs. Same pattern as the tj-actions/changed-files incident (CVE-2025-30066). All shas were resolved from the upstream repos and cross checked against their release tags. The pins stay maintainable: a dependabot config with the github-actions ecosystem bumps them automatically, one small block.

Commit 2 adds permissions: contents: read to the CI workflow, the only one without a block. Coverage uploads use your dedicated CODECOV_TOKEN secret and the GitHub token is never used, so the scope is exact. The npm publish and CodeQL workflows already declare scoped permissions and are untouched.

Commit 3 adds Plumber to CI, the tool I used to find the issues in the first place, so none of this quietly drifts back:

  • Scans the workflows on each push to master and on each PR, fails when something regresses: an unpinned action, a job without permissions, a known CVE. The gate passes at 85 points, so one small finding does not block your PRs.
  • The config is a 14 line overlay inheriting the CLI's built-in baseline, with one adjustment: the baseline also expects your release/* branches to be protected, the overlay keeps that requirement on master only, where the npm releases cut from. If you would rather protect the release branches instead, delete the overlay and the default applies.
  • Adds a score badge to the README, reference-style like your existing ones. It works like OpenSSF Scorecard's published results: runs publish the score to score.getplumber.io, the badge shows the state of master, a failed publish never fails your CI, and it reads UNKNOWN in gray until the first run.

One heads up: if the org uses an Actions allowlist in settings, patterns written against tags (like owner/action@v5) stop matching once refs are shas and workflows refuse to start. Entries need to be owner/action@* in that case.

To be fully transparent: I work on Plumber. If you do not want the tool in your CI, no hard feelings, say so and I remove that commit from the PR, the two hardening commits are the part that matters and they stand entirely on their own.

Checklist

  • PR contains only changes related; no stray files, etc.
  • README updated (where applicable)
  • Tests written (where applicable)
  • References provided in PR (where applicable)

Mutable tags are movable pointers: whoever controls an action, or
anyone who compromises it, can re-point the tag and the next run
executes unreviewed code with the job's token. This repo publishes
to npm from CI, so the release path deserves frozen inputs. Same
pattern as the tj-actions/changed-files incident (CVE-2025-30066).

Pinning to the full commit sha freezes what runs; the version each
sha corresponds to stays as a comment. Every sha was resolved from
the upstream repository and cross-checked against its release tag.
No workflow logic changes.
Without a permissions block the test job's GITHUB_TOKEN inherits the
repository default scope. Coverage uploads use the dedicated
CODECOV_TOKEN secret and the GitHub token is never used, so contents
read is exact. The npm publish and CodeQL workflows already declare
scoped permissions and are untouched.
Scans the workflows on each push to master and on pull requests, and
fails when something regresses: an unpinned action, a job without a
permissions block, a known CVE. The gate passes at 85 points so a
single small finding does not block PRs. The config is a small
overlay that inherits the CLI's built-in baseline and narrows the
branch protection requirement to master, where npm releases cut
from. Each run publishes the score to score.getplumber.io, shown as
a badge in the README.
@codecov

codecov Bot commented Aug 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (3576b41) to head (399f202).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff            @@
##            master     #2836   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          114       114           
  Lines         2598      2598           
  Branches       658       658           
=========================================
  Hits          2598      2598           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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