Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions memories/claude-bot-workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -939,3 +939,82 @@ mattering.
org-level Claude secrets, provisioned in three batches between 2026-05-09 and
2026-07-14.
Attribution proved unrecoverable by any of the three surfaces above.)

## `pull_request_target` is rejected by the App-token exchange

Anthropic's `github-app-token-exchange` endpoint rejects OIDC tokens minted for
`pull_request_target` events, with
`App token exchange failed: 401 Unauthorized - Invalid OIDC token`.
The job dies in about 25 seconds, before the model is reached.

The trap is that the action's **own** side supports the event.
claude-code-action#347, "Can't use action in workflow triggered by
`pull_request_target`", is closed as completed, and `docs/security.md` carries a
section on using the action with that trigger --- so the workflow reads as both
correct and documented.
Only the server side refuses it.
(Issue #713's body credits the support to "PR #759".
That number is an unrelated open bug report in the same repo, so cite #347
instead of repeating it.)
Tracked as
[anthropics/claude-code-action#713](https://github.com/anthropics/claude-code-action/issues/713),
open since 2025-12-02, whose stated workaround is to use `pull_request`.

So `pull_request_target` is not an available fix for fork PRs, whatever else
recommends it.
Nor would it be sufficient if the exchange worked: the action still refuses to run
for a contributor without write access unless `allowed_non_write_users` is set,
which `docs/security.md` documents as a significant security risk.
Read a proposal to switch a review workflow to this trigger as a regression, and
leave a comment in the workflow naming the upstream issue so it does not get
re-applied.

Three messages arrive at that same exchange step, and only the first two are
401s.
The message is what separates them:

- `Invalid OIDC token` --- the trigger event, this entry.
- `User does not have write access on this repository` --- the triggering actor is
not a collaborator, e.g. the Copilot coding agent
(`UCD-SERG/ucd-serg.github.io#84`).
- `Workflow validation failed ... identical content to the version on the
repository's default branch` --- not a failure at all.
The action **skips** and exits 0, so a green check on a PR that edits the review
workflow is not a review.
See the self-mod skip bullet above for gha's own guard against this.

This is a fourth distinct cause in the short-duration band that
[`fully-clean`](../shared/workflow/fully-clean.md) already records three for,
under "That duration signature does not run backwards".
Three of the four run 25 seconds or less, and none of them is about credentials,
which is that section's point: a short run corroborates a credential hypothesis
you already hold on other grounds, and never produces one.

Three of the four are on `UCD-SERG/ucd-serg.github.io` and one is on
`d-morrison/qwt`, so the band is the thing they share rather than the repo.
Saying otherwise would be the grouping-by-symptom overreach that same section
warns about, in the entry invoking its authority.

(`UCD-SERG/ucd-serg.github.io`, 2026-07-31: PR #83 switched the review workflow to
`pull_request_target`, and all five subsequent runs failed this way while the two
`pull_request` runs immediately before it succeeded.
Reverted in #89, tracked as #88.
The revert PR's own two runs are the cleanest demonstration available, because the
trigger is the only variable between them.
Run 30680266779 (`pull_request_target`) was rejected at the token with
`401 Invalid OIDC token`.
Run 30680266785 (`pull_request`) had its token *accepted* and got as far as
workflow validation, where it skipped and exited 0 --- so its check reads
`success` while the action never reviewed anything.
Same repo, same secret, 15 seconds apart.

That second run is also a worked example of the skip bullet above, and of how it
misleads a careful reader.
Round 2 of this PR's own review read that `success` conclusion and reported the
sentence describing it as a fabricated claim, on the reasoning that a run which
succeeded cannot have stopped early.
It can, and this one did: the log carries
`Skipping action due to workflow validation` and `Exiting due to workflow
validation skip`.
Read the log rather than the conclusion, on any job whose action can exit 0
without doing its work.)
Loading