From 5ee1997cef89bee2bda971a3d45b9d6f445866bb Mon Sep 17 00:00:00 2001 From: Cail Daley Date: Wed, 27 May 2026 12:49:16 +0200 Subject: [PATCH 1/2] =?UTF-8?q?chore:=20add=20dependabot.yml=20=E2=80=94?= =?UTF-8?q?=20cooldown=20+=20grouped=20monthly=20bumps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds an explicit version-updates policy on top of the security-updates channel that fires automatically since uv.lock landed (#719). Posture is supply-chain conservative: - 14-day cooldown on minor/patch, 30-day on majors (Dependabot won't PR a version until it's been live for that long). Buys a detection window against maintainer-compromise attacks (Shai-Hulud, axios, PyTorch Lightning, …) where malicious versions typically get yanked within hours-to-days. - Monthly schedule + grouped patch/minor — one batched PR, atomic to revert, large enough to actually be reviewed instead of waved through. - Major bumps stay individual (potentially breaking, deserve individual review). - No auto-merge. - github-actions ecosystem also enabled (companion to SHA-pinning the workflows). Cooldown does NOT apply to security updates — those still fire on the CVE-publication timeline, which is the right tradeoff. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/dependabot.yml | 62 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..526a09aa --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,62 @@ +# Dependabot config — supply-chain conservative posture. +# +# Why this exists: +# - We now ship a `uv.lock`, so Dependabot's security-updates channel fires +# automatically on GHSAs touching transitive deps. This file adds +# *version-updates* policy on top: routine bumps that don't fall out +# of a security advisory. +# - 2025-2026 has seen a wave of maintainer-compromise attacks across npm +# and PyPI (Shai-Hulud / Mini Shai-Hulud, axios, PyTorch Lightning, +# tj-actions/changed-files, …). The published-to-Dependabot-PR-lag is +# often minutes. Cooldown buys a detection window for free. +# +# Policy: +# - 14-day cooldown on minor/patch (30 days on majors). Anything malicious +# is usually caught and yanked within a few days; the cooldown lets that +# happen before it reaches us. +# - Monthly schedule + grouped patch/minor PRs — one batched PR per month, +# atomic to revert, large enough to actually be reviewed. +# - Major bumps stay as individual PRs (potentially breaking; each +# deserves its own review). +# - No auto-merge anywhere. Lockfile diffs are uninspectable; we eyeball +# the version metadata and source links before merging. +# +# Note: cooldown does NOT apply to security-updates (the GHSA-driven PRs). +# Those still fire on the CVE-publication timeline, which is the right +# tradeoff for shapepipe — fix CVEs fast, but don't auto-merge them either. + +version: 2 + +updates: + # Python dependencies tracked via uv.lock + - package-ecosystem: "uv" + directory: "/" + schedule: + interval: "monthly" + day: "monday" + cooldown: + default-days: 14 + semver-major-days: 30 + groups: + lockfile-minor-patch: + patterns: ["*"] + update-types: ["minor", "patch"] + open-pull-requests-limit: 3 + labels: + - "dependencies" + + # GitHub Actions versions (SHA-pinned in workflows; Dependabot proposes + # SHA bumps with the new tag annotated in the PR body). + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + cooldown: + default-days: 14 + groups: + actions: + patterns: ["*"] + open-pull-requests-limit: 2 + labels: + - "dependencies" + - "github-actions" From 8ca7b56a74c2880e900548376af9976423973e02 Mon Sep 17 00:00:00 2001 From: Cail Daley Date: Wed, 27 May 2026 12:49:26 +0200 Subject: [PATCH 2/2] chore: SHA-pin all GitHub Actions across workflows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mutable action references (@v4, @v3, …) are the same failure mode that took out tj-actions/changed-files (23k+ repos compromised in Q1 2026) and trivy-action. An attacker who compromises an action's maintainer account can silently re-point a tag at a malicious SHA, and every workflow that references that tag pulls the new code on the next run. Pinning each action by full commit SHA — with the human-readable tag preserved as a trailing comment — closes that vector. Dependabot's github-actions ecosystem (enabled in the companion commit) proposes SHA bumps with the new tag annotated in the PR body, so updates remain reviewable. All four workflows pinned; SHAs resolved against current refs as of this commit, no behavioral change intended. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/cd.yml | 6 +++--- .github/workflows/ci-release.yml | 4 ++-- .github/workflows/deploy-image.yml | 18 +++++++++--------- .github/workflows/doc-tests.yml | 6 +++--- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index c9dcc597..366a3a9b 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -13,10 +13,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0 - name: Set up conda - uses: conda-incubator/setup-miniconda@v2 + uses: conda-incubator/setup-miniconda@9f54435e0e72c53962ee863144e47a4b094bfd35 # v2.3.0 with: auto-update-conda: true python-version: 3.9 @@ -38,7 +38,7 @@ jobs: sphinx-build -E docs/source docs/_build - name: Deploy API documentation - uses: peaceiris/actions-gh-pages@v3.5.9 + uses: peaceiris/actions-gh-pages@cf301857435c1f95963b21d58f452a7617770d60 # v3.5.9 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: docs/_build diff --git a/.github/workflows/ci-release.yml b/.github/workflows/ci-release.yml index 82445dfd..115952e4 100644 --- a/.github/workflows/ci-release.yml +++ b/.github/workflows/ci-release.yml @@ -19,7 +19,7 @@ jobs: python-version: [3.11] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Install Linux dependencies if: runner.os == 'Linux' @@ -35,7 +35,7 @@ jobs: brew reinstall gcc - name: Set up conda - uses: conda-incubator/setup-miniconda@v3 + uses: conda-incubator/setup-miniconda@fc2d68f6413eb2d87b895e92f8584b5b94a10167 # v3.3.0 with: auto-update-conda: true python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/deploy-image.yml b/.github/workflows/deploy-image.yml index 0119fd71..f12638f9 100644 --- a/.github/workflows/deploy-image.yml +++ b/.github/workflows/deploy-image.yml @@ -11,17 +11,17 @@ jobs: packages: write steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Log in to the Container registry - uses: docker/login-action@v3 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 with: driver-opts: network=host @@ -29,13 +29,13 @@ jobs: # `:develop`); `runtime` carries a `-runtime` suffix. - name: Tags — dev (default) id: meta-dev - uses: docker/metadata-action@v5 + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - name: Tags — runtime id: meta-runtime - uses: docker/metadata-action@v5 + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} flavor: | @@ -43,7 +43,7 @@ jobs: # Build runtime first (smaller, used to smoke-test pipeline binaries) - name: Build runtime (load) - uses: docker/build-push-action@v6 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . target: runtime @@ -70,7 +70,7 @@ jobs: # Build dev (reuses cached `base` layer) - name: Build dev (load) - uses: docker/build-push-action@v6 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . target: dev @@ -90,7 +90,7 @@ jobs: # Push both targets - name: Push runtime - uses: docker/build-push-action@v6 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . target: runtime @@ -100,7 +100,7 @@ jobs: cache-from: type=gha - name: Push dev - uses: docker/build-push-action@v6 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . target: dev diff --git a/.github/workflows/doc-tests.yml b/.github/workflows/doc-tests.yml index 6333dc5f..2f1dbc3d 100644 --- a/.github/workflows/doc-tests.yml +++ b/.github/workflows/doc-tests.yml @@ -8,10 +8,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0 - name: Set up conda - uses: conda-incubator/setup-miniconda@v2 + uses: conda-incubator/setup-miniconda@9f54435e0e72c53962ee863144e47a4b094bfd35 # v2.3.0 with: auto-update-conda: true python-version: 3.8 @@ -33,7 +33,7 @@ jobs: sphinx-build -E docs/source docs/_build - name: Archive API build - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@82c141cc518b40d92cc801eee768e7aafc9c2fa2 # v2.3.1 with: name: api-docs retention-days: 14