With the plain pull_request trigger that most templates use, a fork pull request runs your workflow with read only permissions and no repository secrets. For a first time contributor to a public repository, GitHub may also hold the run until a maintainer with write access approves it.
What GitHub documents
For a pull request from a fork to the base repository, GitHub sends the pull request events to the base repository and no pull request events occur on the fork. The events reference also says that Dependabot pull requests are treated as though they come from a fork and are subject to the same restrictions.
GitHub's compromised runners page spells out the effect: workflows triggered from a fork with the pull_request event have read only permissions and have no access to secrets. It then contrasts this with other triggers, such as issue_comment, issues, push and pull_request from a branch inside the repository, where an attacker could try to steal secrets or use the write permission of the token.
The approval step
When a first time contributor opens a pull request to a public repository, a maintainer with write access may need to approve running workflows. GitHub's approval page tells maintainers to inspect the proposed changes first, and to be especially alert to changes in the .github/workflows directory. Runs that wait for approval longer than 30 days expire and are marked failed.
You can configure approval requirements at the repository, organization or enterprise level.
A walk through
| Step | What happens |
|---|---|
| 1 | A contributor forks your repository and edits code |
| 2 | They open a pull request to your default branch |
| 3 | Your template workflow, triggered by pull_request, is queued |
| 4 | If they are a first time contributor, GitHub may wait for approval |
| 5 | A maintainer reads the diff, especially workflow file changes |
| 6 | The run starts with read only access and no secrets |
Why a pull request can still hurt
Read only and no secrets limit the damage but do not make the code harmless. Code in the pull request runs on a runner. It can consume runner minutes and cache space, and on a self hosted runner it runs inside your network. Keep fork pull requests on hosted runners and keep an eye on workflow changes inside the pull request itself.
What to put in your template
- Use
pull_requestfor build and test steps that run contributor code. - Keep anything that needs secrets, such as comments or labels with write access, in a separate privileged workflow, and do not check out the contributor's code there. See scanning fork pull requests without secrets, a two workflow pattern.
- Add CODEOWNERS on workflow files so changes to CI itself always reach a reviewer.
- Review the approval queue regularly. Our checklist on approving workflow runs from first time forks helps.
Quick check
Can a fork pull request read my repository secrets?
Not with the plain pull_request trigger. GitHub documents read only permissions and no secrets for that case. Other triggers behave differently, so check your template.
Why does my fork pull request show Awaiting approval?
For public repositories, workflow runs from first time contributors may need approval from a maintainer with write access.
Sources
- Events that trigger workflows, GitHub Docs
- Approving workflow runs from forks, GitHub Docs
- Compromised runners, GitHub Docs
Last reviewed: 19 October 2026.