Secure CI/CD for untrusted contributions and fork pull requests
Implementation Effort: Medium – Locking down fork pull request permissions, secrets, and workflow injection paths is a multi-step configuration effort across pipeline owners. User Impact: Low – Restricting fork pull request execution is a pipeline configuration change for repository administrators; end users are not affected. Lifecycle Stage: Build
Overview
Secure your CI/CD pipelines against untrusted contributions by restricting what workflows can run, what secrets are accessible, and what permissions are granted when external or fork-based pull requests trigger pipeline execution. Fork pull requests are one of the most exploited CI/CD attack vectors because they allow an external contributor to submit code that runs inside the target repository's pipeline infrastructure.
On GitHub, workflows triggered by pull_request events from forks run with read-only permissions and no access to repository secrets by default. For workflows that must build fork contributions, use the pull_request event, run on ephemeral runners, and never expose secrets.
Workflows using pull_request_target run in the context of the base repository and can access repository secrets. Restrict pull_request_target workflows to metadata or policy actions that do not check out, build, or execute untrusted code. Enable approval requirements for first-time and new contributors, and use the stricter "Require approval for all outside collaborators" setting where warranted.
Guard against workflow injection attacks where fork PR titles, branch names, or commit messages contain malicious payloads interpolated into workflow commands via ${{ github.event.* }} expressions. Do not use direct interpolation in run: steps. Instead, assign untrusted values to environment variables and reference them in the shell. Also protect GITHUB_OUTPUT and GITHUB_ENV files — untrusted input written to these files can inject environment variables or step outputs that affect downstream workflow steps.
Isolate caches and artifacts between trusted and untrusted workflows. Scope cache keys to the event or ref, and do not allow artifacts produced by fork validation runs to be consumed by trusted release workflows without separate verification.
In Azure Pipelines for GitHub repositories, control fork behavior at the pipeline level. Enable Build pull requests from forks of this repository only for pipelines that must validate external contributions. Keep Make secrets available to builds of forks and Make fork builds have the same permissions as regular builds disabled.
At the organization or project level, enable Limit job authorization scope to current project for non-release pipelines so build identities remain project-scoped. For Azure Repos validation, keep secrets and protected resources unavailable to untrusted pull request validation and rely on branch policies plus protected-resource checks.
Restricting permissions, secrets, and workflow execution for fork and untrusted pull requests applies the Assume breach principle — treating every external contribution as potentially hostile — and enforces Use least privilege access so untrusted code runs with the minimum permissions and no access to secrets.