From 43d47848ea84907a0d8f3733e297ff231b987ba0 Mon Sep 17 00:00:00 2001 From: Michele Mancioppi Date: Thu, 16 Jul 2026 09:39:50 +0200 Subject: [PATCH 1/2] ci(nix): auto-heal vendorHash on Dependabot PRs Dependency bumps change go.mod/go.sum, which invalidates the buildGoModule vendorHash in nix/package.nix and turns the Nix build red on the PR. The existing `nix-vendor-hash.yml` workflow fixes this on `pull_request`, but GitHub withholds Actions secrets from Dependabot- triggered `pull_request` runs, so the PAT-based checkout fails with "Input required and not supplied: token" (see PR #188). Add a companion workflow on `pull_request_target`, which does grant Actions secrets to Dependabot-triggered runs. Guard by `actor == dependabot[bot]` and same-repo head, and drop Dependabot from the existing workflow's `if:` so the two do not double-fire. Security tradeoff: the job still checks out and runs `nix build` on the PR branch while a write-scoped PAT is in the environment. Scope is confined to Dependabot's own bumps; the remaining trust surface is a compromised upstream dependency exfiltrating the PAT during the build. --- .../workflows/nix-vendor-hash-dependabot.yml | 65 +++++++++++++++++++ .github/workflows/nix-vendor-hash.yml | 17 +++-- 2 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/nix-vendor-hash-dependabot.yml diff --git a/.github/workflows/nix-vendor-hash-dependabot.yml b/.github/workflows/nix-vendor-hash-dependabot.yml new file mode 100644 index 0000000..5dbe186 --- /dev/null +++ b/.github/workflows/nix-vendor-hash-dependabot.yml @@ -0,0 +1,65 @@ +name: Nix vendorHash (Dependabot) + +# Dependency bumps change go.mod / go.sum, which invalidates the buildGoModule +# vendorHash in nix/package.nix and turns the Nix build red on the PR. This +# workflow heals Dependabot PRs by recomputing the hash and pushing the fix +# back to the PR branch (see PR #188 for the failure mode this addresses). +# +# The sibling `nix-vendor-hash.yml` workflow handles the same fix for human +# PRs on `pull_request`. It cannot handle Dependabot PRs because GitHub +# withholds Actions secrets from `pull_request` runs triggered by Dependabot, +# so `REPOSITORY_FULL_ACCESS_GITHUB_TOKEN` resolves empty and `actions/checkout` +# fails with "Input required and not supplied: token". +# +# `pull_request_target` runs the workflow file from the base branch and does +# grant Actions secrets to Dependabot-triggered runs, so it is the supported +# way to push back to a Dependabot PR branch without also registering the PAT +# as a Dependabot secret. +# +# Security note: this checks out the PR branch and runs `nix build` on it +# while a write-scoped PAT is available. The `actor` guard confines the job +# to Dependabot's own bumps; the remaining trust surface is a compromised +# upstream dependency exfiltrating the PAT during the build. +on: + pull_request_target: + paths: + - "go.mod" + - "go.sum" + - "nix/package.nix" + +permissions: + contents: read + +jobs: + update-vendor-hash: + # Dependabot branches live in this repo (never on a fork), so we can push + # to `head.ref`. The actor guard keeps the workflow from firing on any + # other author's PRs — those are already covered by `nix-vendor-hash.yml`. + if: >- + github.actor == 'dependabot[bot]' && + github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + steps: + - name: Checkout PR branch + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + ref: ${{ github.event.pull_request.head.ref }} + token: ${{ secrets.REPOSITORY_FULL_ACCESS_GITHUB_TOKEN }} + + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@ef8a148080ab6020fd15196c2084a2eea5ff2d25 # v22 + + - name: Recompute vendorHash + run: ./nix/update-vendor-hash.sh + + - name: Commit and push if changed + run: | + if git diff --quiet -- nix/package.nix; then + echo "vendorHash already correct; nothing to do." + exit 0 + fi + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add nix/package.nix + git commit -m "chore(nix): update vendorHash for dependency change" + git push origin "HEAD:${{ github.event.pull_request.head.ref }}" diff --git a/.github/workflows/nix-vendor-hash.yml b/.github/workflows/nix-vendor-hash.yml index 361edaf..6fbe060 100644 --- a/.github/workflows/nix-vendor-hash.yml +++ b/.github/workflows/nix-vendor-hash.yml @@ -10,9 +10,10 @@ name: Nix vendorHash # rather than the default GITHUB_TOKEN also makes the follow-up commit # re-trigger the Nix build workflow. # -# For this to work on Dependabot PRs, that token must ALSO be registered as a -# Dependabot secret (Settings -> Secrets and variables -> Dependabot), because -# GitHub withholds Actions secrets from Dependabot-triggered pull_request runs. +# Dependabot PRs are handled by the sibling `nix-vendor-hash-dependabot.yml` +# workflow, which uses `pull_request_target` so Dependabot-triggered runs can +# access the PAT (GitHub withholds Actions secrets from Dependabot-triggered +# `pull_request` runs otherwise). on: pull_request: paths: @@ -27,9 +28,13 @@ permissions: jobs: update-vendor-hash: - # Only same-repo branches (Dependabot branches live in this repo); we can't - # push to a fork's branch. - if: github.event_name == 'workflow_dispatch' || github.event.pull_request.head.repo.full_name == github.repository + # Only same-repo branches (we can't push to a fork's branch). Dependabot + # PRs are handled by `nix-vendor-hash-dependabot.yml` — this `pull_request` + # workflow can't fetch the PAT under Dependabot's secret restrictions. + if: >- + github.event_name == 'workflow_dispatch' || + (github.event.pull_request.head.repo.full_name == github.repository && + github.actor != 'dependabot[bot]') runs-on: ubuntu-latest steps: - name: Checkout PR branch From 0577645ea6ba39c160f09c4951c6776533eebea7 Mon Sep 17 00:00:00 2001 From: Michele Mancioppi Date: Thu, 16 Jul 2026 09:45:38 +0200 Subject: [PATCH 2/2] ci(nix): consolidate vendorHash workflow onto pull_request_target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge the Dependabot-only sibling back into `nix-vendor-hash.yml`. A single `pull_request_target` workflow handles both Dependabot and human dependency PRs uniformly: `pull_request_target` grants Actions secrets to Dependabot runs (which `pull_request` denies), and same-repo human branches are pushable the same way. Tradeoff: a change to this workflow on a PR branch is not exercised by that PR — `pull_request_target` evaluates the workflow file from the base branch. Manual runs via `workflow_dispatch` cover pre-merge testing. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../workflows/nix-vendor-hash-dependabot.yml | 65 ------------------- .github/workflows/nix-vendor-hash.yml | 21 +++--- 2 files changed, 11 insertions(+), 75 deletions(-) delete mode 100644 .github/workflows/nix-vendor-hash-dependabot.yml diff --git a/.github/workflows/nix-vendor-hash-dependabot.yml b/.github/workflows/nix-vendor-hash-dependabot.yml deleted file mode 100644 index 5dbe186..0000000 --- a/.github/workflows/nix-vendor-hash-dependabot.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: Nix vendorHash (Dependabot) - -# Dependency bumps change go.mod / go.sum, which invalidates the buildGoModule -# vendorHash in nix/package.nix and turns the Nix build red on the PR. This -# workflow heals Dependabot PRs by recomputing the hash and pushing the fix -# back to the PR branch (see PR #188 for the failure mode this addresses). -# -# The sibling `nix-vendor-hash.yml` workflow handles the same fix for human -# PRs on `pull_request`. It cannot handle Dependabot PRs because GitHub -# withholds Actions secrets from `pull_request` runs triggered by Dependabot, -# so `REPOSITORY_FULL_ACCESS_GITHUB_TOKEN` resolves empty and `actions/checkout` -# fails with "Input required and not supplied: token". -# -# `pull_request_target` runs the workflow file from the base branch and does -# grant Actions secrets to Dependabot-triggered runs, so it is the supported -# way to push back to a Dependabot PR branch without also registering the PAT -# as a Dependabot secret. -# -# Security note: this checks out the PR branch and runs `nix build` on it -# while a write-scoped PAT is available. The `actor` guard confines the job -# to Dependabot's own bumps; the remaining trust surface is a compromised -# upstream dependency exfiltrating the PAT during the build. -on: - pull_request_target: - paths: - - "go.mod" - - "go.sum" - - "nix/package.nix" - -permissions: - contents: read - -jobs: - update-vendor-hash: - # Dependabot branches live in this repo (never on a fork), so we can push - # to `head.ref`. The actor guard keeps the workflow from firing on any - # other author's PRs — those are already covered by `nix-vendor-hash.yml`. - if: >- - github.actor == 'dependabot[bot]' && - github.event.pull_request.head.repo.full_name == github.repository - runs-on: ubuntu-latest - steps: - - name: Checkout PR branch - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - ref: ${{ github.event.pull_request.head.ref }} - token: ${{ secrets.REPOSITORY_FULL_ACCESS_GITHUB_TOKEN }} - - - name: Install Nix - uses: DeterminateSystems/nix-installer-action@ef8a148080ab6020fd15196c2084a2eea5ff2d25 # v22 - - - name: Recompute vendorHash - run: ./nix/update-vendor-hash.sh - - - name: Commit and push if changed - run: | - if git diff --quiet -- nix/package.nix; then - echo "vendorHash already correct; nothing to do." - exit 0 - fi - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add nix/package.nix - git commit -m "chore(nix): update vendorHash for dependency change" - git push origin "HEAD:${{ github.event.pull_request.head.ref }}" diff --git a/.github/workflows/nix-vendor-hash.yml b/.github/workflows/nix-vendor-hash.yml index 6fbe060..ddd61c1 100644 --- a/.github/workflows/nix-vendor-hash.yml +++ b/.github/workflows/nix-vendor-hash.yml @@ -10,17 +10,19 @@ name: Nix vendorHash # rather than the default GITHUB_TOKEN also makes the follow-up commit # re-trigger the Nix build workflow. # -# Dependabot PRs are handled by the sibling `nix-vendor-hash-dependabot.yml` -# workflow, which uses `pull_request_target` so Dependabot-triggered runs can -# access the PAT (GitHub withholds Actions secrets from Dependabot-triggered -# `pull_request` runs otherwise). +# Why `pull_request_target` rather than `pull_request`: GitHub withholds Actions +# secrets from `pull_request` runs triggered by Dependabot, so the PAT resolves +# empty and `actions/checkout` fails with "Input required and not supplied: +# token" (see PR #188). `pull_request_target` grants Actions secrets to +# Dependabot runs and evaluates the workflow file from the base branch, so a PR +# cannot alter what runs here. The tradeoff is that a change to this file on a +# PR branch cannot be tested by that PR — it only takes effect after merge. on: - pull_request: + pull_request_target: paths: - "go.mod" - "go.sum" - "nix/package.nix" - - ".github/workflows/nix-vendor-hash.yml" workflow_dispatch: permissions: @@ -29,12 +31,11 @@ permissions: jobs: update-vendor-hash: # Only same-repo branches (we can't push to a fork's branch). Dependabot - # PRs are handled by `nix-vendor-hash-dependabot.yml` — this `pull_request` - # workflow can't fetch the PAT under Dependabot's secret restrictions. + # branches always live in this repo, so this covers both Dependabot and + # human dependency PRs. if: >- github.event_name == 'workflow_dispatch' || - (github.event.pull_request.head.repo.full_name == github.repository && - github.actor != 'dependabot[bot]') + github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - name: Checkout PR branch