Skip to content

claude-review workflow fails deterministically on every fork PR (missing allow-unsafe-pr-checkout) #33

Description

@jnasbyupgrade

Problem

The `claude-review` workflow uses `pull_request_target` and, once its internal "wait for other CI" gate reaches `decision=run`, its checkout step fails every time for a fork PR:

```
##[error]Refusing to check out fork pull request code from a 'pull_request_target' workflow.
This workflow runs with the base repository's GITHUB_TOKEN, secrets, default-branch cache
scope, and runner access. Fetching and executing a fork's code in that trusted context
commonly leads to "pwn request" vulnerabilities. To opt in, review the risks at
https://gh.io/securely-using-pull_request_target and set 'allow-unsafe-pr-checkout: true'
on the actions/checkout step.
```

This is GitHub Actions' own safety guard against exactly this combination (`pull_request_target` + checking out untrusted fork code) firing as designed -- the workflow is misconfigured for its actual use case (reviewing fork PRs), not flaky.

Confirmed deterministic, not flaky

Checked two runs directly:

  • PR CLAUDE.md: never apply/remove maintainer-gated labels #29 (this repo), run 30215484347: gate reached `decision=run`, then failed at checkout with the exact error above.
  • pgxntool PR #58, run 30212701067: gate reached `decision=skip` (something else was still pending/failed at the time), so the checkout step never executed -- this is why that PR's `claude-review` check shows green. It's not evidence the checkout works; the workflow just never reached the broken step.

Every fork PR that reaches `decision=run` will hit this same failure.

Impact

Beyond the review itself never running for fork PRs, this compounds with pgxntool's `check-test-pr` job (see Postgres-Extensions/pgxntool -- separate issue to follow), which treats any non-success check run on the paired pgxntool-test PR as a hard failure, with no filtering for automated-review-bot checks vs. real tests. So this failure transitively blocks the actual pgxntool PR's pairing check too.

Options

  1. Add `allow-unsafe-pr-checkout: true` if the review is meant to run on fork PR code and the security tradeoff (base-repo secrets/token exposed to fork code) is accepted.
  2. Switch to plain `pull_request` instead of `pull_request_target` if the review doesn't actually need base-repo secrets/write access (mirrors the reasoning already documented for `ci.yml` choosing `pull_request` over `pull_request_target` for exactly this security reason).
  3. Skip/no-op this workflow entirely for fork PRs if it's not meant to run there.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions