Skip to content

Add Plumber security scan and harden workflow actions - #76

Merged
davidB merged 5 commits into
cdevents:mainfrom
thomasboni:ci/add-plumber-security-scan
Jul 28, 2026
Merged

Add Plumber security scan and harden workflow actions#76
davidB merged 5 commits into
cdevents:mainfrom
thomasboni:ci/add-plumber-security-scan

Conversation

@thomasboni

Copy link
Copy Markdown
Contributor

What this does

This PR adds a workflow (.github/workflows/plumber.yml) that runs Plumber on every push and pull request to main. Plumber scans the repository's GitHub Actions workflows for CI/CD security issues and reports them to the Security tab.

Running the scan surfaced a set of pre-existing findings, so the PR also hardens the current workflows. Three commits cover the scan and the hardening:

  1. ci: add plumber security scan workflow : the new workflow, with its own actions already pinned by SHA.
  2. ci: pin third-party actions to commit sha: pin every third-party action in the ci, linter and release-plz workflows to a full commit SHA, keeping the version as a trailing comment (Dependabot can bump them).
  3. ci: add plumber config trusting existing action sources: add .plumber.yaml that keeps every control enabled and allowlists the third-party actions this project already uses (mise, sccache, commitlint, release-plz, rust-toolchain).

Local scan result

With these changes the local run reports:

  • Status: PASSED (score B, 77.5/100, required >= C)
  • Passed Controls (20), Failed Controls (1)
  • The gate is set to fail only below score C, so the check passes today.

One finding is left as a follow-up on purpose:

  • ISSUE-714: dtolnay/rust-toolchain runs the rustup installer from a moving ref. Pinning the action by SHA does not remove this, because the fetch happens inside the action itself. Fixing it means installing the toolchain from a pinned, checksum-verified source, which would change how releases install Rust. Left out of scope here. Let me know what you think about this and if you want to talk about how to fix it.

⚠️ About score-push: this PR publishes your plumber result

The last two commits enable score-push and add a Plumber Score badge to the README. When the workflow runs on main, it publishes this repository's result to the hosted service at score.getplumber.io over OIDC (no secret required).

This makes the repository name and its A to E score publicly visible, and the README badge reflects that score (the badge will remain unknown or empty until the first push to main on the upstream cdevents/sdk-rust).

If you would rather not publish it: just tell me and I will remove the 2 last commits from the PR. The scan and the hardening keep working either way.

@thomasboni
thomasboni force-pushed the ci/add-plumber-security-scan branch from c59d7dc to 65f8ff7 Compare July 28, 2026 13:57

@davidB davidB left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iirc, dependabot (our dependencies updater), is able to handle the commit SHA for the action version.

@davidB

davidB commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

I added getplumber/plumber into our whitelist of allowed action (on github's settings).
You will have to sign-off (click on DCO to have the instruction).

What do you prefer, "Squash and merge" or "rebase", when I'll merge the PR?

Add an independent workflow that runs Plumber to scan the GitHub Actions
workflows for CI/CD security issues on every push and pull request to main.
The report is uploaded to the Security tab as SARIF.

The check fails only when the Plumber Score drops below C. Publishing the
score to the hosted badge service is left disabled.

Signed-off-by: Thomas Boni <thomas@getplumber.io>
Pin the third-party actions used by the ci, linter and release-plz workflows
to full commit SHAs, keeping the version as a trailing comment for Dependabot.
A moving tag can otherwise change the code that runs in CI without any local
change.

Once pinned by SHA, dtolnay/rust-toolchain can no longer read the toolchain
from the ref, so it is set explicitly through the toolchain input.

Signed-off-by: Thomas Boni <thomas@getplumber.io>
Add .plumber.yaml based on Plumber's github defaults, with every control kept
enabled so none is silently turned off. The trustedGithubActions list is
extended with the third-party actions this project already relies on (mise,
sccache, commitlint, release-plz and rust-toolchain) so they pass the
authorized-sources control.

Code owner approval is not part of this project's branch protection policy,
so branchMustBeProtected.codeOwnerApprovalRequired is set to false.

Signed-off-by: Thomas Boni <thomas@getplumber.io>
Turn on score-push and grant id-token: write so the workflow publishes this
repository's Plumber Score to the hosted score service on pushes to main. This
keeps the README badge current. It makes the repository name and score public
and does not publish on pull requests.

Signed-off-by: Thomas Boni <thomas@getplumber.io>
Show the repository's Plumber Score in the README badge row. The badge is
served by the hosted score service and updates after the plumber workflow
publishes the score on pushes to main.

Signed-off-by: Thomas Boni <thomas@getplumber.io>
@thomasboni
thomasboni force-pushed the ci/add-plumber-security-scan branch from 65f8ff7 to da2662b Compare July 28, 2026 14:35
@thomasboni

Copy link
Copy Markdown
Contributor Author

Thanks for the review @davidB! The DCO is now ok.

I generally rebase. All the commits here are independent, but if you prefer to keep a light commit history, I can squash all of them in one commit before.

@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

Comment thread .github/workflows/release-plz.yml Dismissed
Comment thread .github/workflows/release-plz.yml Dismissed
@davidB

davidB commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

ok, I'll rebase when ready to merge.

@thomasboni

thomasboni commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

@davidB just so you know, the 2 GHAS alerts above come from the Plumber report.

The Plumber check itself passes (min score is C, the repo scores B, see report), but Plumber also pushes its findings to code scanning, and this repo requires all alerts to be resolved before merging.

Both alerts are about ISSUE-714 on the dtolnay/rust-toolchain steps in release-plz.yml: the action downloads the latest rustup-init at run time, so SHA-pinning the action doesn't cover that code.

About the actual risk: the code fetched by the action comes from static.rust-lang.org, official Rust infrastructure that any Rust build trusts anyway. The preinstalled rustup on the runners comes from the same place. The difference is that it was baked into the runner image ahead of time instead of downloaded live during the release job, so there is no moving dependency left in the two jobs holding the crates.io token.

I see 2 options:

  1. Remove the two dtolnay/rust-toolchain steps and rely on the rustup + stable toolchain preinstalled on GitHub runners. It's a small deletion, and it removes a run-time download from the two jobs that hold the crates.io token. But I don't know if you are using other part of what dtolnay/rust-toolchain provide. I can push this to the PR if you like.
  2. Dismiss both alerts as accepted risk: the downloaded code comes from rust-lang.org infrastructure, which any Rust build has to trust anyway. With maintainer right, you can do it directly from the GHAS comment on in security tab.

Let me know what you prefer.

@davidB

davidB commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

rust installed on runner has no garanty to be the latest or a specific version. Using dtolnay/rust-toolchain is pretty common in the rust ecosystem. As alternative I can use the mise action like in ci.yml that also install rust + other tools. in release-plz I just try to install the minimal toolset.

So We can switch to mise action or dismiss the alert.
As it's a library (no binary distributed), we can dismiss the alert.

@thomasboni

Copy link
Copy Markdown
Contributor Author

@davidB agreed, keeping dtolnay/rust-toolchain seems fine to me: the action itself is now pinned by SHA, and the mutable part it downloads (rustup-init) comes from official Rust infrastructure (static.rust-lang.org), which has a high safety level.

Switching to mise would also clear the alerts, but it pulls more tooling into the release jobs, so dismissing is simpler here.

I can't dismiss the alerts myself, it requires maintainer rights: you can do it directly from the GHAS annotations on this PR or from the Security tab. After that the PR should be mergeable.

@davidB
davidB merged commit d309039 into cdevents:main Jul 28, 2026
4 checks passed
@davidB

davidB commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

@thomasboni Merci

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.

3 participants