Skip to content
Merged
56 changes: 51 additions & 5 deletions .github/workflows/codeql-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,12 @@ jobs:
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
LANGUAGE: ${{ matrix.language }}
RUN_ATTEMPT: ${{ github.run_attempt }}
REQUIRED_RUN_ID: ${{ github.run_id }}
run: |
set -euo pipefail
live_pr="$(gh api "repos/${TARGET_REPOSITORY}/pulls/${PR_NUMBER}")"
live_head="$(printf '%s' "$live_pr" | jq -r '.head.sha // empty')"
live_base="$(printf '%s' "$live_pr" | jq -r '.base.sha // empty')"
live_state="$(printf '%s' "$live_pr" | jq -r 'if (.state | type) == "string" then .state else empty end')"
if [ -z "$live_head" ] || [ -z "$live_state" ]; then
echo "::error::Could not validate live pull request state before CodeQL dispatch."
Expand All @@ -188,6 +190,14 @@ jobs:
echo "Pull request head moved on the live open PR; a fresh dispatch will fire for the current head."
exit 0
fi
if ! [[ "$live_base" =~ ^[0-9a-fA-F]{40}$ ]]; then
echo "::error::Could not validate live pull request base SHA before CodeQL verdict read."
exit 1
fi
if ! [[ "$REQUIRED_RUN_ID" =~ ^[1-9][0-9]*$ ]]; then
echo "::error::CodeQL shard requires a canonical current run id."
exit 1
fi

statuses="$(gh api "repos/${TARGET_REPOSITORY}/commits/${PR_HEAD_SHA}/statuses")"
verdict_state="$(printf '%s' "$statuses" | jq -r --arg ctx "codeql-dispatch/${LANGUAGE}" '
Expand All @@ -208,6 +218,36 @@ jobs:
exit 0
;;
esac

expected_title="CodeQL Scan Dispatch ${TARGET_REPOSITORY}#${PR_NUMBER}@${PR_HEAD_SHA}/${live_base}/${REQUIRED_RUN_ID}"
expected_job="CodeQL dispatch scan (${LANGUAGE})"
runs_json="$(gh api --paginate --slurp "repos/ContextualWisdomLab/.github/actions/workflows/codeql-scan-dispatch.yml/runs")"
run_id="$(printf '%s' "$runs_json" | jq -r --arg title "$expected_title" --arg path ".github/workflows/codeql-scan-dispatch.yml" '
[
.[] | .workflow_runs[]
| select(.path == $path)
| select(.event == "repository_dispatch")
| select(.status == "completed")
| select(.display_title == $title or .name == $title)
]
| first
| .id // empty
')"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: this run lookup is not an authenticated receipt. Bind exact base SHA, required run/jobs, protected source/actors, scan conclusion and one unexpired SARIF artifact before consuming its job as a terminal verdict.

if [[ "$run_id" =~ ^[1-9][0-9]*$ ]]; then
jobs_json="$(gh api --paginate --slurp "repos/ContextualWisdomLab/.github/actions/runs/${run_id}/jobs")"
job_conclusion="$(printf '%s' "$jobs_json" | jq -r --arg name "$expected_job" '
[.[] | .jobs[] | select(.name == $name)]
| if length == 1 then .[0].conclusion else empty end
')"
case "$job_conclusion" in
success|failure)
echo "verdict=${job_conclusion}" >>"$GITHUB_OUTPUT"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: before consuming this conclusion, verify exact protected handler source/actors, successful validate-dispatch, the supplied required job identity, and an unexpired SARIF artifact for the same run/language/attempt. Base/run text in display_title is necessary but not sufficient provenance.

echo "Found completed CodeQL dispatch scan job for ${LANGUAGE}: ${job_conclusion}."
exit 0
;;
esac
fi

if [ "$RUN_ATTEMPT" != "1" ]; then
echo "::error::Exact CodeQL job was rerun without an authenticated terminal verdict."
exit 1
Expand Down Expand Up @@ -251,7 +291,6 @@ jobs:
always()
&& github.event.action != 'closed'
&& github.event.pull_request.state != 'closed'
&& github.run_attempt == 1
&& needs.detect-languages.result == 'success'
&& needs.detect-languages.outputs.code == 'true'
runs-on: ubuntu-24.04
Expand All @@ -277,6 +316,9 @@ jobs:
set -euo pipefail
live_pr="$(gh api "repos/${TARGET_REPOSITORY}/pulls/${PR_NUMBER}")"
live_head="$(printf '%s' "$live_pr" | jq -r '.head.sha // empty')"
live_base="$(printf '%s' "$live_pr" | jq -r '.base.sha // empty')"
live_base_ref="$(printf '%s' "$live_pr" | jq -r '.base.ref // empty')"
live_head_ref="$(printf '%s' "$live_pr" | jq -r '.head.ref // empty')"
live_state="$(printf '%s' "$live_pr" | jq -r 'if (.state | type) == "string" then .state else empty end')"
if [ -z "$live_head" ] || [ -z "$live_state" ]; then
echo "::error::Could not validate live pull request state before CodeQL dispatch."
Expand All @@ -294,6 +336,10 @@ jobs:
echo "::error::CodeQL dispatch requires a canonical current run id."
exit 1
fi
if ! [[ "$live_base" =~ ^[0-9a-fA-F]{40}$ ]] || [ -z "$live_base_ref" ] || [ -z "$live_head_ref" ]; then
echo "::error::Could not validate live pull request base identity before CodeQL dispatch."
exit 1
fi

include_json="$(printf '%s' "$MATRIX" | jq -c '.include // empty' 2>/dev/null || true)"
if [ -z "$include_json" ] ||
Expand Down Expand Up @@ -385,10 +431,10 @@ jobs:
jq -cn \
--arg target_repository "$TARGET_REPOSITORY" \
--arg pr_number "$PR_NUMBER" \
--arg pr_base_ref "$PR_BASE_REF" \
--arg pr_base_sha "$PR_BASE_SHA" \
--arg pr_head_ref "$PR_HEAD_REF" \
--arg pr_head_sha "$PR_HEAD_SHA" \
--arg pr_base_ref "$live_base_ref" \
--arg pr_base_sha "$live_base" \
--arg pr_head_ref "$live_head_ref" \
--arg pr_head_sha "$live_head" \
--argjson matrix "$pending_matrix" \
--arg required_run_id "$REQUIRED_RUN_ID" \
--argjson required_jobs "$required_jobs" \
Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/codeql-scan-dispatch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ run-name: >-
CodeQL Scan Dispatch ${{ github.event.client_payload.target_repository ||
github.repository }}#${{
github.event.client_payload.pr_number || 'event' }}@${{
github.event.client_payload.pr_head_sha || github.sha }}
github.event.client_payload.pr_head_sha || github.sha }}/${{
github.event.client_payload.pr_base_sha || 'none' }}/${{
github.event.client_payload.required_run_id || github.run_id }}

on:
repository_dispatch:
Expand Down Expand Up @@ -503,6 +505,11 @@ jobs:
exit 0
fi

if [ "$GATE_OUTCOME" = "success" ]; then
echo "::notice::Could not publish the CodeQL dispatch status after all configured credentials failed. The completed dispatch scan job remains the evidence for this head."
exit 0
fi

echo "::error::Could not publish the CodeQL dispatch status after all configured credentials failed; the exact required job will remain failed and will not be woken with stale or missing evidence."
exit 1

Expand Down
Loading
Loading