Skip to content

ci: Pin workflow actions and scope token permissions - #578

Merged
ebma merged 15 commits into
mainfrom
ci/harden-workflows
Oct 25, 2026
Merged

ebma merged 15 commits into
mainfrom
ci/harden-workflows

Conversation

@ebma

@ebma ebma commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Follows #577, which is merged.

What

  • Every third-party action is pinned to a full commit SHA, with its version noted alongside. Dependabot also covers the shared composite action.
  • Workflows default to a read-only token; write access is granted per job where it is needed.
  • Release workflow:
    • separate build (read-only) and publish jobs
    • the srtool action and image pinned by digest
    • no persisted checkout credentials
    • inputs and outputs passed through the environment
    • a strict tag format
    • publishing never changes a release that already has assets
  • version-up and release-node pass inputs and secrets through the environment; command substitutions are quoted.
  • Clippy and test steps call cargo directly.

Testing

  • actionlint reports no errors (one style suggestion in the release workflow).
  • YAML, job outputs and artifact hand-over between the build and publish jobs checked.
  • The publish job runs end to end only on a real tag; the dry run described in ci: Build runtime releases with the metadata hash #577 covers the build job.

Base automatically changed from fix/release-metadata-hash to main October 24, 2026 07:55
ebma added 13 commits October 25, 2026 10:52
The release built with chevdor/srtool-actions@v0.9.2 and the srtool image
tag 1.81.0, both of which can be moved to other content. Pin the action to
its v0.9.2 commit and the image to 1.81.0-0.17.0 by digest (the image the
current releases were built with; the action pulls <image>:<tag>, so the
tag input carries the digest), and name the pinned image in the release
notes so the build can be reproduced with it.
The release ran in one job with a contents: write token, which the checkout
also stored in the workspace that the srtool container mounts. Build in a
job with the read-only default and without persisted credentials, and pass
the wasm, report and release notes as an artifact to a publish job that
alone holds contents: write and runs only when a release tag is known.

Event values, workflow inputs and the srtool outputs reach the shell steps
through env instead of being expanded into the scripts.
Give every workflow a contents: read default and grant more only to the
job that needs it (the version-bump job pushes a branch and opens a pull
request, so it gets contents and pull-requests write).

Pin every third-party action, including those of the shared composite
action, to a full commit SHA with its version as a comment, so a moved
tag or branch cannot change what runs. Each pin is the commit its tag or
branch resolves to now, except foundry-toolchain: v1 moved to v1.9.2 only
hours ago, so it stays on v1.9.1 until that release has been reviewed.
Before the release action runs, the publish job looks up the release for
the tag and fails if it already has assets, so a later build of the same
tag (with other build options or another image) cannot replace the
published wasm, srtool report or notes. The release action also runs with
overwrite_files: false, so it never deletes an attached asset, even one
that another run added after the check. Publishing to such a release again
requires removing its assets by hand.
A dispatched tag is free text that ends up in step outputs and log lines.
The release workflow now fails before writing any output when the tag
contains another character. Every existing release tag uses only these.
…action

With directory "/", the github-actions updater reads only the workflows
and a root action.yml, so also list .github/actions/shared.
The run scripts of version-up.yml and release-node.yml now read workflow
inputs, step outputs and secrets from step env instead of having them
expanded into the script text, and quote them where they are used.

The version-up conditions compare the inputs with test expressions, so a
bump without a specific version gets the "Bump <package> crate version/s
to <kind>" pull request title.
The publish job's check now reads the release through the same by-tag
lookup the release action uses, and fails the step on any error other
than a missing release.
A second publish run for the same tag waits until the first has
finished, so its check sees the assets the first run attached.
@ebma
ebma force-pushed the ci/harden-workflows branch from 2bc3419 to c6ccbc6 Compare October 25, 2026 09:52
@ebma
ebma merged commit e171c16 into main Oct 25, 2026
7 checks passed
@ebma
ebma deleted the ci/harden-workflows branch October 25, 2026 18:14
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