Fix Codex security review authorization (#6913)

The Codex security review workflow now authorizes automatic reviews from
the live pull request instead of the webhook snapshot. This prevents a
stale author association from sending an internal PR down the
external-contributor invalidation path.

Internal PRs with no previous review now exit without attempting a
comment or label mutation. The jobs that update PR comments and labels
use `pull-requests: write`, and the review job runs only after the
trusted prepare step emits `authorized=true`.

Regression tests cover stale author associations in both directions, the
no-op invalidation path, and the mutation-job permission contract.

Checked with `just ci`, `just security-review-check`, and `actionlint
.github/workflows/codex-security-review.yml`.

The failing `Mark Previous Review Stale` check on this PR runs the
pre-fix `pull_request_target` workflow from `main`. GitHub will not
execute this branch’s trusted workflow until it is merged; the new
workflow contract and state-machine tests exercise the fix before then.

Signed-off-by: Jordan Mecom <jm@squareup.com>
This commit is contained in:
Jordan Mecom
2026-08-27 11:06:04 -07:00
committed by GitHub
parent 0ccf934b88
commit 745ff6066c
3 changed files with 127 additions and 21 deletions

View File

@@ -17,14 +17,14 @@ jobs:
# This workflow posts an advisory review; its skipped jobs are not a merge
# gate and must not be configured as required status checks.
# MEMBER and OWNER are GitHub's associations for members of the `block`
# organization. Outside contributors require this exact command from one
# organization. The trusted prepare step checks the live PR instead of the
# event snapshot. Outside contributors require this exact command from one
# of those members: @buzz-security-review <full-head-sha>
if: >-
github.repository == 'block/buzz' && (
(
github.event_name == 'pull_request_target' &&
github.event.pull_request.draft == false &&
contains(fromJSON('["MEMBER", "OWNER"]'), github.event.pull_request.author_association)
github.event.pull_request.draft == false
) || (
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
@@ -38,6 +38,7 @@ jobs:
contents: read
pull-requests: read
outputs:
authorized: ${{ steps.pr.outputs.authorized }}
pr_number: ${{ steps.pr.outputs.pr_number }}
trigger_actor: ${{ steps.pr.outputs.trigger_actor }}
base_sha: ${{ steps.pr.outputs.base_sha }}
@@ -111,8 +112,7 @@ jobs:
cancel-in-progress: true
permissions:
contents: read
issues: write
pull-requests: read
pull-requests: write
steps:
- name: Checkout trusted workflow support
if: matrix.pr_number != 0
@@ -192,8 +192,7 @@ jobs:
cancel-in-progress: true
permissions:
contents: read
issues: write
pull-requests: read
pull-requests: write
steps:
- name: Checkout trusted workflow support
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -212,6 +211,7 @@ jobs:
security-review:
name: Run Codex Security Review
needs: prepare-review
if: needs.prepare-review.outputs.authorized == 'true'
runs-on: ubuntu-latest
environment: codex-review
timeout-minutes: 30
@@ -453,8 +453,7 @@ jobs:
cancel-in-progress: true
permissions:
contents: read
issues: write
pull-requests: read
pull-requests: write
env:
CODEX_MODEL: gpt-5.6-sol
REVIEW_JSON: ${{ needs.security-review.outputs.review_json }}