Skip to content

chore(ci): SHA-pin GitHub Actions in publish job #12

@w-martin

Description

@w-martin

Background

The publish job in .github/workflows/ci.yml has elevated permissions:

permissions:
  id-token: write   # OIDC token for trusted PyPI publishing
  contents: write   # GitHub Release creation

All actions in the workflow are pinned by mutable tag (e.g. actions/checkout@v4) rather than immutable commit SHA. If a tag is force-pushed by a compromised or malicious maintainer, the publish job would run arbitrary code with PyPI publishing and GitHub release creation privileges. This is a supply-chain risk.

GitHub's own security hardening guide recommends SHA-pinning for workflows with sensitive permissions.

Fix

Pin the actions in the publish job (and optionally the whole workflow) to their commit SHAs. Use a tool like pinact or Ratchet to automate this:

# Using pinact
pinact run .github/workflows/ci.yml

Or manually look up each SHA:

gh api repos/actions/checkout/git/ref/refs/tags/v4 --jq '.object.sha'
gh api repos/pypa/gh-action-pypi-publish/git/ref/refs/heads/release/v1 --jq '.object.sha'
# etc.

Example pinned form:

- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4
- uses: pypa/gh-action-pypi-publish@76f52bc884231d6614e0d5b2c4b57374e5f41060  # release/v1

Scope

At minimum pin the actions inside the publish job. Pinning the rest of the workflow (lint-and-test, build_wheels, etc.) is lower priority since those jobs have no write permissions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions