From 91cde860bc3f28ef421a6f9b2d13df471bd82491 Mon Sep 17 00:00:00 2001 From: Ririsoft Date: Mon, 28 Sep 2026 17:58:30 +0200 Subject: [PATCH] harden CI/CD supply chain and use crates.io trusted publishing - pin all GitHub Actions to commit SHAs (upgraded to latest releases) - least-privilege workflow permissions, persist-credentials: false - publish via crates.io trusted publishing from the protected release environment - run publish dry-run before creating the GitHub release - install cargo-llvm-cov with --locked and a pinned version - add actionlint and zizmor workflow linting to CI - enable Dependabot security updates only, with a 7-day cooldown --- .github/dependabot.yml | 19 ++++++++++++++ .github/workflows/release.yml | 49 ++++++++++++++++++++++++++++------- .github/workflows/rust.yml | 41 +++++++++++++++++++++++++---- CHANGELOG.md | 4 +++ 4 files changed, 98 insertions(+), 15 deletions(-) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..6c3c365 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,19 @@ +# Security updates only: `open-pull-requests-limit: 0` disables version +# update pull requests while still allowing Dependabot security updates. +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 0 + cooldown: + default-days: 7 + + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 0 + cooldown: + default-days: 7 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7a31844..01566f5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,17 +3,37 @@ on: push: tags: [ "v[0-9]+.*" ] -permissions: - contents: write +permissions: {} jobs: + verify: + if: github.repository_owner == 'ririsoft' + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # master + with: + toolchain: stable + + - name: Verify package can be published + run: cargo publish --dry-run + create-release: if: github.repository_owner == 'ririsoft' + needs: + - verify runs-on: ubuntu-latest + permissions: + contents: write steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - - uses: taiki-e/create-gh-release-action@v1 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: taiki-e/create-gh-release-action@eba8ea96c86cca8a37f1b56e94b4d13301fba651 # v1.11.0 with: changelog: CHANGELOG.md title: $version @@ -24,14 +44,23 @@ jobs: needs: - create-release runs-on: ubuntu-latest + environment: release + permissions: + contents: read + id-token: write steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # master + with: + toolchain: stable - - name: Verify package can be published - run: cargo publish --dry-run + - name: Authenticate to crates.io with trusted publishing + id: auth + uses: rust-lang/crates-io-auth-action@c6f97d42243bad5fab37ca0427f495c86d5b1a18 # v1.0.5 - name: Publish package to crates.io env: - CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }} run: cargo publish diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 49af70f..c74c7d3 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -9,6 +9,9 @@ on: branches: - master +permissions: + contents: read + jobs: rust-ci: runs-on: ${{ matrix.os }} @@ -19,16 +22,19 @@ jobs: steps: - name: Checkout sources - uses: actions/checkout@v4 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Install rust toolchain - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # master with: toolchain: stable components: rustfmt, clippy, llvm-tools-preview + # This workflow publishes no artifacts and release.yml uses no cache. - name: Setup rust smart caching - uses: Swatinem/rust-cache@v2 + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 # zizmor: ignore[cache-poisoning] with: cache-on-failure: "true" @@ -45,8 +51,33 @@ jobs: run: cargo test - name: Setup cargo-llvm-cov - run: cargo install cargo-llvm-cov + run: cargo install cargo-llvm-cov --locked --version 0.9.1 - name: Run code coverage test run: | - cargo llvm-cov test --fail-under-lines 90 \ No newline at end of file + cargo llvm-cov test --fail-under-lines 90 + + workflow-lint: + runs-on: ubuntu-latest + env: + ACTIONLINT_VERSION: 1.7.12 + steps: + - name: Checkout sources + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Run actionlint + run: | + base="https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}" + archive="actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" + curl -fsSLO "${base}/${archive}" + curl -fsSLO "${base}/actionlint_${ACTIONLINT_VERSION}_checksums.txt" + grep " ${archive}\$" "actionlint_${ACTIONLINT_VERSION}_checksums.txt" | sha256sum -c - + tar -xzf "${archive}" actionlint + ./actionlint -color + + - name: Run zizmor + uses: zizmorcore/zizmor-action@cc914d7f3750a2d13d75c7f184a1060aa0e9d482 # v0.6.4 + with: + advanced-security: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 2891b68..afb49d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed ### Security +- Hardened CI/CD supply chain: GitHub Actions pinned to commit SHAs, least-privilege + workflow permissions, crates.io trusted publishing (OIDC) from a protected `release` + environment, Dependabot security updates, and actionlint/zizmor workflow linting. + ## [2.2.0] - 2026-09-28 ### Fixed