| name | supply-chain-hardened-ci-cd |
| description | Hardened GitHub Actions release workflow patterns for supply-chain security. Use when reviewing or writing GitHub Actions release workflows (.github/workflows/*.yml). Contains SHA-pinning, OIDC trusted publishing, two-job build/publish split, --ignore-scripts, Pwn Request prevention, deny-by-default permissions, and egress hardening patterns. Triggered by March 2026 TeamPCP campaign that specifically hijacked release tags. |
Supply Chain Hardened CI/CD
GitHub Actions Audit Checklist
Run on every .github/workflows/*.yml file reviewed. Flag each failure with its specific line.
Key Hardening Patterns
SHA-pinning
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
Verify the SHA belongs to the expected tag: git -C <cloned-actions-repo> tag --points-at <sha>
OIDC Trusted Publishing (no long-lived tokens)
permissions:
id-token: write
contents: read
- uses: pypa/gh-action-pypi-publish@release/v1
Two-job split (build / publish)
jobs:
build:
permissions:
contents: read
steps:
- run: python -m build
- uses: actions/upload-artifact@...
publish:
needs: build
environment: pypi-release
permissions:
id-token: write
steps:
- uses: actions/download-artifact@...
- uses: pypa/gh-action-pypi-publish@...
Registry credentials (OIDC or token) appear only in the publish job. The build job has no network write access.
Deny-by-default permissions
permissions: {}
jobs:
test:
permissions:
contents: read
Pwn Request prevention
Never combine pull_request_target with checkout of the PR head:
on: pull_request_target
steps:
- uses: actions/checkout@...
with:
ref: ${{ github.event.pull_request.head.sha }}
Use pull_request (no secrets) or audit all code paths before accessing secrets in pull_request_target.
Findings Format
For each finding: file path, line number, violation type (e.g., "mutable tag reference", "Pwn Request pattern"), and remediation (the exact SHA-pinned replacement or restructured job split).