diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 00000000..cae805da --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,89 @@ + + +# GitHub Actions Workflows + +All third-party GitHub Actions used in these workflow files are pinned to full +40-character commit SHAs (with version comments) to protect against supply chain +attacks and comply with security policies (e.g., +[Zizmor](https://docs.zizmor.sh/audits/#unpinned-uses)). + +## Updating Action Versions + +Future maintainers can update pinned actions using automated tools or manually. + +### Option 1: Using Ratchet (Recommended) + +[Ratchet](https://github.com/sethvargo/ratchet) is specifically designed to +manage and bump pinned GitHub Actions: + +```bash +# Upgrade all pinned actions to their latest releases (e.g. v1 -> v3) +ratchet upgrade .github/workflows/*.yml + +# Update pinned actions to the latest commit within their current tag constraint +ratchet update .github/workflows/*.yml + +# Unpin all actions back to named tags +ratchet unpin .github/workflows/*.yml + +# Pin named tags to their commit SHAs +ratchet pin .github/workflows/*.yml +``` + +### Option 2: Using Zizmor (Pinning & Remediation) + +`zizmor --fix=all` resolves named tags (e.g. `@v4`) to their immutable commit +SHAs. It does not automatically bump major versions (e.g. `v4` → `v5`), but it +will remediate unpinned tags and known-vulnerable actions. + +To upgrade versions using Zizmor: + +1. Change the action tag in the workflow file to the desired new release tag + (e.g. `@v5`). +2. Run `zizmor --fix=all` with an authenticated GitHub token to resolve the SHA + and add the version comment: + +```bash +zizmor --fix=all --gh-token=$(gh auth token) .github/workflows/ +``` + +The zizmor documentation suggests setting up either Dependabot or Renovate to +automate this process. (https://docs.zizmor.sh/audits/#remediation_35). + +### Option 3: Manual Updating + +To manually find the commit SHA corresponding to a specific release tag, use +`git ls-remote`: + +```bash +git ls-remote https://github.com/actions/checkout.git refs/tags/v4.2.2 +``` + +Then update the workflow step format: + +```yaml +- uses: actions/checkout@ # v4.2.2 +``` + +## Security Guidelines + +* **Permissions:** Maintain least-privilege access by declaring explicit + `permissions:` blocks (e.g., `permissions: { contents: read }`) at the top + or job level. +* **Credential Persistence:** Ensure `actions/checkout` steps include `with: + persist-credentials: false` unless git push credentials are explicitly + needed. +* **Suppressions:** Any false-positive suppressions must be documented inline + above the offending line using `# zizmor: ignore[] - {reason}`. diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index feaa6f96..1e108a60 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -16,20 +16,24 @@ name: Unittests on: push: - branches: [ main ] + branches: [main] pull_request: - branches: [ main ] + branches: [main] workflow_dispatch: +permissions: + contents: read + jobs: check-lockfile: name: "Check: pylock.toml Sync" runs-on: ubuntu-latest timeout-minutes: 5 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: fetch-depth: 0 + persist-credentials: false - name: Check if pyproject.toml was modified id: check_pyproject env: @@ -49,7 +53,7 @@ jobs: echo "changed=false" >> "$GITHUB_OUTPUT" echo "pyproject.toml was not modified. Skipping lockfile sync check." fi - - uses: astral-sh/setup-uv@v5 + - uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5 if: steps.check_pyproject.outputs.changed == 'true' with: enable-cache: true @@ -76,21 +80,23 @@ jobs: cancel-in-progress: true steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false - # Install deps - - uses: actions/setup-python@v5 - with: - python-version: "3.12" + # Install deps + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.12" - - uses: astral-sh/setup-uv@v5 - with: - enable-cache: true + - uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5 + with: + enable-cache: true - - name: Install dependencies - run: | - uv pip install --system -r pylock.toml - uv pip install --system -e . + - name: Install dependencies + run: | + uv pip install --system -r pylock.toml + uv pip install --system -e . - - name: Run core tests - run: pytest -vv -n auto --import-mode=importlib + - name: Run core tests + run: pytest -vv -n auto --import-mode=importlib diff --git a/.github/workflows/update_lockfile.yml b/.github/workflows/update_lockfile.yml index a70c90f1..85d70d79 100644 --- a/.github/workflows/update_lockfile.yml +++ b/.github/workflows/update_lockfile.yml @@ -27,15 +27,17 @@ jobs: pull-requests: write steps: - name: Checkout repository - uses: "actions/checkout@v4" + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false - name: Set up Python - uses: "actions/setup-python@v5" + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.12" - name: Install uv - uses: "astral-sh/setup-uv@v5" + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5 with: enable-cache: true @@ -45,7 +47,7 @@ jobs: go run github.com/google/addlicense@v1.1.1 -c "Google LLC" -y "2026" -l apache pylock.toml - name: Create Pull Request - uses: "peter-evans/create-pull-request@v7" + uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7 with: token: ${{ secrets.GITHUB_TOKEN }} commit-message: "Update dependencies in pylock.toml" diff --git a/.github/workflows/welcome.yml b/.github/workflows/welcome.yml index 6842ebcc..da670e38 100644 --- a/.github/workflows/welcome.yml +++ b/.github/workflows/welcome.yml @@ -15,6 +15,7 @@ name: Welcome First-Time Contributors on: + # zizmor: ignore[dangerous-triggers] - Only posts welcome comment; does not checkout untrusted code. pull_request_target: types: [opened] @@ -25,7 +26,7 @@ jobs: welcome: runs-on: ubuntu-latest steps: - - uses: actions/first-interaction@v1 + - uses: actions/first-interaction@3c71ce730280171fd1cfb57c00c774f8998586f7 # v1 with: repo-token: ${{ secrets.GITHUB_TOKEN }} pr-message: |