You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A CodeQL dispatch scan that passes its Medium+ SARIF gate is reported to the required check as CodeQL dispatch scan for <lang> did not pass (state=failure), telling the reader to go look at SARIF evidence that is in fact clean. The cause is that the required check derives its verdict from the dispatch job's conclusion, and that conclusion is failure whenever the job's last step — waking the required job — fails, regardless of what the scan found.
This is distinct from the wake race in #2051 / #2056, and worse in kind. The race delays a check. This misreports it: a green scan becomes a red security verdict.
Evidence
.github#2137 head 3d39fe7c. Dispatch run 34734286494, job CodeQL dispatch scan (python) (103663188483). Every step of the actual analysis passed:
1 success Set up job
…
8 success Initialize CodeQL
9 success Perform CodeQL Analysis
10 success Enforce CodeQL Medium+ SARIF gate <-- the security gate PASSED
11 success Preserve CodeQL SARIF evidence
12 success Publish CodeQL dispatch status
13 failure Wake exact CodeQL required job <-- only this
…
27 success Complete job
Job conclusion: failure, from step 13 alone.
The required check then reads that conclusion directly as the verdict (codeql-scan-dispatch.yml, the fallback branch after the codeql-dispatch/<lang> status lookup returns nothing):
job_conclusion="$(printf '%s'"$jobs_json"| jq -r --arg name "$expected_job"' … | if length == 1 then .[0].conclusion else empty end')"case"$job_conclusion"in
…) echo"verdict=${job_conclusion}">>"$GITHUB_OUTPUT"echo"Found completed CodeQL dispatch scan job for ${LANGUAGE}: ${job_conclusion}."
And the required job emits:
DISPATCH_OUTCOME: success
VERDICT_STATE: failure
##[error] CodeQL dispatch scan for python did not pass (state=failure).
See the linked dispatch run for SARIF evidence.
There is no Medium+ SARIF evidence to see. Step 10 passed.
Why it matters
It inverts a security signal. "This PR's Python CodeQL scan did not pass" is the strongest thing this pipeline says about a change, and it is being said about scans that passed. A reviewer acting on it looks for a vulnerability that does not exist; a reviewer who learns the signal is unreliable stops reading it, which is worse.
It is reachable by every PR that loses the shard race.POST /actions/jobs/{id}/rerun re-runs the containing run, so when two language shards target jobs in the same run the second is refused The workflow run containing this job is already running (HTTP 403) — its step 13 fails, its clean scan is recorded as a failed scan.
It survives the re-run. On #2137 the first attempt read VERDICT_STATE: pending ("scan dispatched, will rerun"); the re-run read VERDICT_STATE: failure. The second reading is worse than the first while nothing about the code changed.
Fix direction
The verdict should come from what the scan decided, not from whether the notification afterwards succeeded. Concretely, one of:
Derive the verdict from the gate step, not the job. The dispatch job already has the authoritative answer at step 10; publish that as the codeql-dispatch/<lang> status and let the fallback read step-level outcome rather than .conclusion.
At minimum, make the fallback distinguish them: treat a job whose only failed step is the wake as pending (wake later) rather than failure (scan verdict). This is the smallest change and it removes the false red, though it leaves the race.
(2) subsumes (3) and is the same work #2051/#2056 need to do anyway, so it is probably the right one rather than three separate patches.
Scope note
codeql-scan-dispatch.yml is the surface #2040 is the canonical successor for, and #2051/#2056 are active on the adjacent race. I am not opening a competing PR on that file — filing this so the verdict-derivation half is tracked on its own, since it is a correctness defect in what the pipeline reports rather than a scheduling defect in when it reports it, and it could be fixed even if the race work stalls.
Found while checking whether #2137's red python shard was a finding in its diff. It was not: that scan is clean.
Summary
A CodeQL dispatch scan that passes its Medium+ SARIF gate is reported to the required check as
CodeQL dispatch scan for <lang> did not pass (state=failure), telling the reader to go look at SARIF evidence that is in fact clean. The cause is that the required check derives its verdict from the dispatch job'sconclusion, and that conclusion isfailurewhenever the job's last step — waking the required job — fails, regardless of what the scan found.This is distinct from the wake race in #2051 / #2056, and worse in kind. The race delays a check. This misreports it: a green scan becomes a red security verdict.
Evidence
.github#2137head3d39fe7c. Dispatch run 34734286494, jobCodeQL dispatch scan (python)(103663188483). Every step of the actual analysis passed:Job conclusion:
failure, from step 13 alone.The required check then reads that conclusion directly as the verdict (
codeql-scan-dispatch.yml, the fallback branch after thecodeql-dispatch/<lang>status lookup returns nothing):And the required job emits:
There is no Medium+ SARIF evidence to see. Step 10 passed.
Why it matters
POST /actions/jobs/{id}/rerunre-runs the containing run, so when two language shards target jobs in the same run the second is refusedThe workflow run containing this job is already running (HTTP 403)— its step 13 fails, its clean scan is recorded as a failed scan.#2137the first attempt readVERDICT_STATE: pending("scan dispatched, will rerun"); the re-run readVERDICT_STATE: failure. The second reading is worse than the first while nothing about the code changed.Fix direction
The verdict should come from what the scan decided, not from whether the notification afterwards succeeded. Concretely, one of:
codeql-dispatch/<lang>status and let the fallback read step-level outcome rather than.conclusion.pending(wake later) rather thanfailure(scan verdict). This is the smallest change and it removes the false red, though it leaves the race.(2) subsumes (3) and is the same work #2051/#2056 need to do anyway, so it is probably the right one rather than three separate patches.
Scope note
codeql-scan-dispatch.ymlis the surface #2040 is the canonical successor for, and #2051/#2056 are active on the adjacent race. I am not opening a competing PR on that file — filing this so the verdict-derivation half is tracked on its own, since it is a correctness defect in what the pipeline reports rather than a scheduling defect in when it reports it, and it could be fixed even if the race work stalls.Found while checking whether
#2137's red python shard was a finding in its diff. It was not: that scan is clean.Refs #2040, #2051, #2056, #2137, #1929.