From af98f982042740c5c2ce9482e6931d48f405d0c7 Mon Sep 17 00:00:00 2001 From: Nils Lehnen <30603423+iderex@users.noreply.github.com> Date: Tue, 15 Sep 2026 19:17:21 +0200 Subject: [PATCH] Upload the zizmor findings of a Dependabot head, whose token can write them [#318] The workflow auditor's upload step skipped a pull request Dependabot opened, by author name, and the comment beside it said such a run holds a token that cannot write security events. #312 took that same exclusion out of the other two uploads on this board on the reading of #256's run log; this file was not in that count, and the run log refutes it here too. The proposal Dependabot opened as #317 ran this workflow with the write it was said not to have, and the upload was the one step skipped: gh run view 34809323213 --repo Flowfin/core --log | grep -oE 'SecurityEvents: (write|read)|Contents: read|Metadata: read' | sort -u Contents: read Metadata: read SecurityEvents: write gh api repos/Flowfin/core/actions/runs/34809323213/jobs --jq '.jobs[] | .steps[] | select(.name=="Upload SARIF") | .conclusion' skipped So the condition now excludes a fork's pull request and nothing else, and the paragraph beside it carries the reading rather than the sentence it refutes. What the fork half rests on is not measured here and stays a claim. What it prevents is a surface that reports less than it examined: the auditor judged #317's head and passed it, and nothing it examined reached the code-scanning tab, so the only check-run name absent on that head against a person's head is the code-scanning application's zizmor context. It was found while comparing those two heads for #108. Whether the upload succeeds on a Dependabot head is not measured here; the next proposal Dependabot opens is where it is read. A failed upload on such a head is bounded by continue-on-error on the step, which this change leaves alone, because in this file the upload runs before the gating step. Closes #318 Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com> --- .github/workflows/zizmor.yml | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index 264234a..c92b6f1 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -82,12 +82,32 @@ jobs: - name: Upload SARIF # Only upload where the GITHUB_TOKEN can write security events: pushes to main - # and same-repo human PRs. Fork and Dependabot pull requests run with a - # read-only token, so the upload is skipped there - the gate step below still - # runs and blocks on findings. continue-on-error keeps the security gate - # independent of the upload: a transient code-scanning upload failure must not - # skip the "Fail on actionable findings" step below. - if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.user.login != 'dependabot[bot]') + # and pull requests from a branch on this repository. A fork's pull request + # runs with a read-only token, so the upload is skipped there - the gate step + # below still runs and blocks on findings. continue-on-error keeps the security + # gate independent of the upload: a transient code-scanning upload failure + # must not skip the "Fail on actionable findings" step below. + # + # THIS PARAGRAPH NAMED A DEPENDABOT PULL REQUEST BESIDE THE FORK AND THE RUN + # LOG REFUTES IT (#318). #312 took the same exclusion out of the other two + # uploads on this board on the reading of #256's run, and this file kept it. + # The proposal Dependabot opened as #317 ran this workflow with the write it + # was said not to have, and this step was the one step skipped: + # + # gh run view 34809323213 --repo Flowfin/core --log | grep -oE 'SecurityEvents: (write|read)|Contents: read|Metadata: read' | sort -u + # Contents: read + # Metadata: read + # SecurityEvents: write + # + # gh api repos/Flowfin/core/actions/runs/34809323213/jobs --jq '.jobs[] | .steps[] | select(.name=="Upload SARIF") | .conclusion' + # skipped + # + # So the condition below excludes the fork and nothing else. What the fork + # half rests on is not measured here and stays a claim. A failed upload on a + # head this condition now reaches is bounded by continue-on-error above, not + # by ordering: this step runs BEFORE the gating step, which is the difference + # .github/workflows/shell-analysis.yml names at its own upload. + if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event.pull_request.head.repo.full_name == github.repository continue-on-error: true uses: github/codeql-action/upload-sarif@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 with: