Skip to content

ci: pin third-party actions to commit hashes and limit workflow permissions - #43

Merged
gregsvo merged 1 commit into
mainfrom
chore/harden-workflows
Oct 29, 2026
Merged

gregsvo merged 1 commit into
mainfrom
chore/harden-workflows

Conversation

@gregsvo

@gregsvo gregsvo commented Oct 29, 2026

Copy link
Copy Markdown
Collaborator

Why

Every workflow referenced third-party actions by a movable tag or branch (for example pypa/gh-action-pypi-publish@release/v1 in the job that publishes to PyPI), and two workflows ran with the repository's default read-and-write token. A moved or compromised tag would have run unreviewed code in CI, and in the release pipeline.

What changed

Only .github/workflows/*.yml:

  • Pinned actions: 24 references (9 distinct actions) now use the commit hash their version tag points to today. The version stays as a trailing comment (# v7), and Dependabot's weekly github-actions updates understand this format and update both.
  • Read-only token: tests.yml and security.yml get permissions: contents: read. The other workflows already had explicit permissions.
  • Credentials: all six actions/checkout steps set persist-credentials: false, so the token is not left in the checked-out files. No workflow pushes, tags or commits, and the only one that uses gh (the Discord announcement) does not check out code.

Verification

  • Every pinned hash exists in the repository it names and matches the tag or branch it replaces.
  • actionlint is clean. zizmor (a GitHub Actions security linter) went from 51 findings (24 high) to none at default settings.
  • The CI on this PR runs the pinned actions, so a green run here is the real test.

Not in this PR

Switching the repository's default workflow token to read-only and turning on "require actions to be pinned to a full commit SHA" are repository settings. I'll make those after this merges, since turning the second one on first would fail every workflow.

…ssions

Pin every third-party action to the commit its version tag points at, and keep
the version as a trailing comment so Dependabot continues to update both. A
moved or compromised tag can no longer change what runs in the release
pipeline.

Give tests.yml and security.yml a read-only token; they inherited the
repository default, which is read and write. Stop actions/checkout from
leaving the token in the checked-out files.

Checked with actionlint and zizmor, which went from 51 findings (24 high) to
none at default settings.
@gregsvo
gregsvo merged commit 1d91047 into main Oct 29, 2026
14 checks passed
@gregsvo
gregsvo deleted the chore/harden-workflows branch October 29, 2026 23: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