Environment Bypass Risk
Environment Bypass Risk
Description
Workflows triggered by pull_request_target, workflow_run, or other elevated events can call protected environments without the usual approval gates. A malicious contributor can craft a PR that triggers the privileged workflow and bypasses environment reviewers or required branches, releasing unreviewed code. GitHub cautions that pull_request_target should never deploy directly to production because it runs with the base repository’s token. 1
Vulnerable Instance
- Workflow uses
pull_request_target. - Job targets a protected environment (deployments, secrets) without checking the source branch.
- No manual approval before environment deployment.
name: Deploy on PR Target
on:
pull_request_target:
branches: [main]
jobs:
deploy:
environment: production
permissions:
contents: write
deployments: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- run: ./scripts/deploy.shA forked PR can inject arbitrary code into deploy.sh; the workflow runs with maintainer permissions and bypasses environment approvals.
Mitigation Strategies
- Avoid privileged deployments on
pull_request_target
Usepull_requestfor testing only; gate deployments onworkflow_dispatch/push. - Require environment reviewers
Configure environments with required reviewers and wait timers so automation cannot bypass them. - Validate triggering metadata
Checkgithub.event.pull_request.head_repo.full_nameand restrict to trusted repos/branches. - Split validation from deployment
Have PR workflows create artifacts; only trustedpushorworkflow_dispatchjobs deploy them. - Scope permissions
Setpermissions: read-allby default and elevate only after approval.
Secure Version
name: PR Validation
on:
- pull_request_target:
+ pull_request:
branches: [main]
jobs:
- deploy:
- environment: production
- permissions:
- contents: write
- deployments: write
+ build:
runs-on: ubuntu-latest
+ permissions:
+ contents: read
steps:
- uses: actions/checkout@v4
- with:
- ref: ${{ github.event.pull_request.head.sha }}
- - run: ./scripts/deploy.sh
+ - run: npm test
+
+ name: Deploy (Trusted)
+ on:
+ push:
+ branches: [main]
+ jobs:
+ deploy:
+ environment:
+ name: production
+ url: https://prod.example.com
+ permissions:
+ contents: read
+ deployments: write
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Require manual approval
+ uses: chrnorm/deployment-gate@v1
+ - run: ./scripts/deploy.sh
Impact
| Dimension | Severity | Notes |
|---|---|---|
| Likelihood | Many teams use pull_request_target or chained workflows for convenience. | |
| Risk | Attackers can push unreviewed code to protected environments or access secrets. | |
| Blast radius | Compromised workflow affects all environments linked via workflow_run or deployments. |
References
- GitHub Docs, “Using environments for deployment,” https://docs.github.com/actions/deployment/targeting-different-environments/using-environments-for-deployment 1
- GitHub Docs, “pull_request_target event,” https://docs.github.com/actions/using-workflows/events-that-trigger-workflows#pull_request_target
GitHub Docs, “Using environments for deployment,” https://docs.github.com/actions/deployment/targeting-different-environments/using-environments-for-deployment ↩︎ ↩︎
Last updated on