# How actions/checkout Blocks Unsafe Forked PR Checkouts by Default

> Learn how actions/checkout blocks unsafe forked PR checkouts by default. Discover the safety guard that prevents pwn request attacks when running workflows with privileged tokens.

- Repository: [GitHub Actions/checkout](https://github.com/actions/checkout)
- Tags: how-to-guide
- Published: 2026-08-30

---

**The actions/checkout action prevents "pwn request" attacks by default through a safety guard that detects and blocks attempts to check out code from forked pull requests when workflows run with privileged tokens.**

Forked pull request workflows present a critical security risk where malicious code executes with the base repository's trusted `GITHUB_TOKEN` and secrets. The `actions/checkout` repository mitigates this threat through built-in safeguards that analyze checkout parameters before executing dangerous operations.

## The "Pwn Request" Vulnerability

The "pwn request" attack occurs when a workflow triggered by `pull_request_target` or `workflow_run` events runs with the base repository's privileged credentials but processes code from a forked pull request. By default, `actions/checkout` implements a security boundary that prevents this exploit without requiring manual configuration from repository maintainers.

## Input Processing and Guard Invocation

The protection mechanism begins in [`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts), where the `getInputs` function orchestrates the checkout configuration. After resolving the repository, reference, and commit values, the action invokes the safety guard unless performing a default self-checkout:

```typescript
unsafePrCheckoutHelper.assertSafePrCheckout({
  qualifiedRepository,
  ref: result.ref,
  commit: result.commit,
  allowUnsafePrCheckout: result.allowUnsafePrCheckout
})

```

This invocation occurs at lines 94-100 in [`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts). The guard is skipped only when the workflow performs a default checkout of its own repository without an explicit `ref` input, preserving normal operations while maintaining security boundaries.

## Fork Detection and Blocking Logic

The core protection resides in [`src/unsafe-pr-checkout-helper.ts`](https://github.com/actions/checkout/blob/main/src/unsafe-pr-checkout-helper.ts) within the `assertSafePrCheckout` function (lines 13-81). This helper executes a multi-layered verification process specifically for events capable of running under trusted tokens:

- **Event Validation**: The guard activates exclusively for `pull_request_target` and `workflow_run` events
- **Repository Identification**: It extracts the head repository ID and full name from the workflow context payload
- **Fork Detection**: The helper compares the head repository ID against the base repository ID; differing values indicate a forked pull request

When a fork is detected, the guard blocks the checkout if any of these conditions match the unsafe repository:

- The qualified repository name equals the fork's head repository full name
- The input `ref` matches the pull request pattern `refs/pull/<num>/<head|merge>`
- The supplied commit SHA matches one of the fork's head commit SHAs

If triggered, the helper throws an error that aborts the workflow and directs users to security guidance at `https://gh.io/securely-using-pull_request_target`.

## Configuration and Opt-In Bypass

Maintainers can explicitly disable this protection for specific use cases by setting the `allow-unsafe-pr-checkout` input parameter to `true`. The following configuration demonstrates both safe default usage and the blocked pattern:

```yaml

# Safe default usage - checks out the workflow's own repository

- uses: actions/checkout@v4

# Blocked unsafe pattern - fork checkout without opt-in

- uses: actions/checkout@v4
  with:
    repository: attacker/forked-repo
    ref: refs/pull/123/head
    # allow-unsafe-pr-checkout: true  # Required to bypass the guard

```

## Summary

- **Guard Location**: The `getInputs` function in [`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts) invokes `assertSafePrCheckout` to intercept dangerous operations before execution.
- **Detection Method**: The helper in [`src/unsafe-pr-checkout-helper.ts`](https://github.com/actions/checkout/blob/main/src/unsafe-pr-checkout-helper.ts) identifies forks by comparing repository IDs and validates against PR ref patterns and commit SHAs.
- **Scope**: Protection applies only to privileged events (`pull_request_target`, `workflow_run`) that present actual security risks.
- **Bypass Mechanism**: Repository owners must explicitly set `allow-unsafe-pr-checkout: true` to check out forked PR code in sensitive workflow contexts.

## Frequently Asked Questions

### What triggers the unsafe PR checkout block?

The block triggers when a workflow running under `pull_request_target` or `workflow_run` attempts to check out code where the repository ID differs from the base repository, or when the ref matches `refs/pull/<num>/<head|merge>` patterns that indicate forked PR code.

### How can I bypass the protection for legitimate use cases?

Add `allow-unsafe-pr-checkout: true` to the action inputs. According to the source code in [`src/unsafe-pr-checkout-helper.ts`](https://github.com/actions/checkout/blob/main/src/unsafe-pr-checkout-helper.ts), this boolean flag instructs `assertSafePrCheckout` to skip validation, though this is strongly discouraged without additional security measures.

### Does the guard affect normal pull_request events?

No. The `assertSafePrCheckout` function specifically checks for `pull_request_target` and `workflow_run` events before activating. Standard `pull_request` events do not receive the base repository's privileged `GITHUB_TOKEN`, so they do not present the same "pwn request" attack vector.

### Where is the blocking logic implemented in the source code?

The blocking logic resides in [`src/unsafe-pr-checkout-helper.ts`](https://github.com/actions/checkout/blob/main/src/unsafe-pr-checkout-helper.ts) within the `assertSafePrCheckout` function (lines 13-81). The invocation trigger exists in [`src/input-helper.ts`](https://github.com/actions/checkout/blob/main/src/input-helper.ts) (lines 94-100), while [`src/workflow-context-helper.ts`](https://github.com/actions/checkout/blob/main/src/workflow-context-helper.ts) provides supporting context utilities used during the security validation process.