pull_request_target runs in the context of the base repository with access to secrets, and checking out the pull request code under it executes a stranger’s code with those secrets.
# dangerous
on: pull_request_target
jobs:
test:
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }} # ← their code
- run: npm ci && npm test # ← with secrets
# safe use: label the PR, comment on it, read metadata.
# never check out and never execute the head ref.
The event exists so a workflow can act on a pull request from a fork — adding a label, posting a comment — which requires a token the fork does not get. Combining that with a checkout of the fork’s code is the vulnerability, and it is easy to arrive at because the workflow needs both to do something apparently reasonable like commenting test results. The correct shape is two workflows: pull_request runs the tests without secrets and uploads an artifact, and workflow_run reads it and comments.