From 3be44ec68d8127a7779b83af1f5e685571a1ea84 Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Wed, 1 Apr 2026 15:58:16 +0900 Subject: [PATCH 1/5] Dependabot attestation check workflow --- .../workflows/dependabot-provenance-check.yml | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 .github/workflows/dependabot-provenance-check.yml diff --git a/.github/workflows/dependabot-provenance-check.yml b/.github/workflows/dependabot-provenance-check.yml new file mode 100644 index 000000000..2ac3288df --- /dev/null +++ b/.github/workflows/dependabot-provenance-check.yml @@ -0,0 +1,87 @@ +name: Dependabot Provenance Check + +on: + pull_request: + types: [opened, synchronize, reopened] + +permissions: + contents: read + pull-requests: write + +jobs: + check-provenance: + if: >- + github.actor == 'dependabot[bot]' && + !contains(github.event.pull_request.labels.*.name, 'provenance-exception') + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Fetch Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v2 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + + - name: Setup Node + if: steps.metadata.outputs.package-ecosystem == 'npm_and_yarn' + uses: actions/setup-node@v4 + with: + node-version: "24.13.0" + + - name: Check npm provenance attestation + if: steps.metadata.outputs.package-ecosystem == 'npm_and_yarn' + id: npm-provenance + run: | + IFS=',' read -ra DEPS <<< "${{ steps.metadata.outputs.dependency-names }}" + NEW_VERSION="${{ steps.metadata.outputs.new-version }}" + + FAILED_DEPS="" + for DEP in "${DEPS[@]}"; do + DEP=$(echo "$DEP" | xargs) + echo "::group::Checking provenance for $DEP@$NEW_VERSION" + + ATTESTATIONS=$(npm view "$DEP@$NEW_VERSION" --json 2>/dev/null | jq -r '.dist.attestations // empty') + + if [ -z "$ATTESTATIONS" ]; then + echo "::error::No provenance attestation found for $DEP@$NEW_VERSION" + FAILED_DEPS="${FAILED_DEPS:+$FAILED_DEPS, }$DEP" + else + echo "Provenance attestation found for $DEP@$NEW_VERSION" + fi + echo "::endgroup::" + done + + if [ -n "$FAILED_DEPS" ]; then + echo "failed=true" >> "$GITHUB_OUTPUT" + echo "failed-deps=$FAILED_DEPS" >> "$GITHUB_OUTPUT" + else + echo "failed=false" >> "$GITHUB_OUTPUT" + fi + + - name: Close PR if provenance check failed + if: steps.npm-provenance.outputs.failed == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + FAILED_DEPS: ${{ steps.npm-provenance.outputs.failed-deps }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + gh pr comment "$PR_NUMBER" --body "## Provenance Attestation Check Failed + + This pull request has been automatically closed because the following dependencies do not have [provenance attestation](https://docs.npmjs.com/generating-provenance-statements): + + **Failed:** $FAILED_DEPS + + ### What is provenance attestation? + + Provenance attestation cryptographically proves that a package was built from a specific source repository using a specific build process. This helps protect against supply chain attacks by verifying the link between published packages and their source code. + + ### What to do + + - Check if a newer version of the dependency publishes provenance + - Contact the package maintainer to request [npm provenance](https://docs.npmjs.com/generating-provenance-statements) support + - If this dependency is trusted and an exception is warranted, a maintainer can reopen this PR and add the \`provenance-exception\` label" + + gh pr close "$PR_NUMBER" From 0ada156b2c664821ff2c3b41d0ffbdc889285e34 Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn <100320+knorrium@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:14:17 +0900 Subject: [PATCH 2/5] Update .github/workflows/dependabot-provenance-check.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/dependabot-provenance-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependabot-provenance-check.yml b/.github/workflows/dependabot-provenance-check.yml index 2ac3288df..70f855632 100644 --- a/.github/workflows/dependabot-provenance-check.yml +++ b/.github/workflows/dependabot-provenance-check.yml @@ -11,7 +11,7 @@ permissions: jobs: check-provenance: if: >- - github.actor == 'dependabot[bot]' && + github.event.pull_request.user.login == 'dependabot[bot]' && !contains(github.event.pull_request.labels.*.name, 'provenance-exception') runs-on: ubuntu-latest From 5d90b2f03873fc647ed72704c003f51198c2e238 Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn <100320+knorrium@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:14:28 +0900 Subject: [PATCH 3/5] Update .github/workflows/dependabot-provenance-check.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/dependabot-provenance-check.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/dependabot-provenance-check.yml b/.github/workflows/dependabot-provenance-check.yml index 70f855632..1d958ce56 100644 --- a/.github/workflows/dependabot-provenance-check.yml +++ b/.github/workflows/dependabot-provenance-check.yml @@ -7,6 +7,7 @@ on: permissions: contents: read pull-requests: write + issues: write jobs: check-provenance: From dc7e2bdd82aa2d09836a3ed294f9cd46ab8cf141 Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn <100320+knorrium@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:14:43 +0900 Subject: [PATCH 4/5] Update .github/workflows/dependabot-provenance-check.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../workflows/dependabot-provenance-check.yml | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dependabot-provenance-check.yml b/.github/workflows/dependabot-provenance-check.yml index 1d958ce56..7c3a6d4be 100644 --- a/.github/workflows/dependabot-provenance-check.yml +++ b/.github/workflows/dependabot-provenance-check.yml @@ -69,20 +69,24 @@ jobs: FAILED_DEPS: ${{ steps.npm-provenance.outputs.failed-deps }} PR_NUMBER: ${{ github.event.pull_request.number }} run: | - gh pr comment "$PR_NUMBER" --body "## Provenance Attestation Check Failed - + COMMENT_BODY_FILE="$(mktemp)" + cat > "$COMMENT_BODY_FILE" < Date: Wed, 1 Apr 2026 16:15:15 +0900 Subject: [PATCH 5/5] Update .github/workflows/dependabot-provenance-check.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/dependabot-provenance-check.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dependabot-provenance-check.yml b/.github/workflows/dependabot-provenance-check.yml index 7c3a6d4be..a3fdb503a 100644 --- a/.github/workflows/dependabot-provenance-check.yml +++ b/.github/workflows/dependabot-provenance-check.yml @@ -37,11 +37,21 @@ jobs: id: npm-provenance run: | IFS=',' read -ra DEPS <<< "${{ steps.metadata.outputs.dependency-names }}" - NEW_VERSION="${{ steps.metadata.outputs.new-version }}" + UPDATED_DEPS_JSON='${{ steps.metadata.outputs.updated-dependencies-json }}' FAILED_DEPS="" for DEP in "${DEPS[@]}"; do DEP=$(echo "$DEP" | xargs) + + NEW_VERSION=$(echo "$UPDATED_DEPS_JSON" | jq -r --arg name "$DEP" ' + .[] | select(.dependency-name == $name) | .new-version + ' | head -n 1) + + if [ -z "$NEW_VERSION" ] || [ "$NEW_VERSION" = "null" ]; then + echo "::error::Could not determine updated version for dependency $DEP from Dependabot metadata" + FAILED_DEPS="${FAILED_DEPS:+$FAILED_DEPS, }$DEP" + continue + fi echo "::group::Checking provenance for $DEP@$NEW_VERSION" ATTESTATIONS=$(npm view "$DEP@$NEW_VERSION" --json 2>/dev/null | jq -r '.dist.attestations // empty')