Cross Repository Access
Cross Repository Access
Description
When a workflow checks out or clones a repository other than the one that triggered it, any secrets granted to the workflow can cross trust boundaries. Attackers can substitute malicious dependencies, exfiltrate data to forked repos, or silently tamper with code if the external repo is compromised. GitHub recommends using organization allowlists and scoped tokens for cross-repo interactions. 1
Vulnerable Instance
actions/checkoutfetchesowner/other-repousing the defaultGITHUB_TOKEN.- Workflow writes artifacts or pushes commits back to that repository.
- There is no allowlist or validation of the requested repository name.
name: Cross Repo Sync
on:
workflow_dispatch:
inputs:
target_repo:
required: true
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Clone target repository
run: git clone https://github.com/${{ inputs.target_repo }} target
- name: Push changes
run: |
cd target
git commit --allow-empty -m "sync"
git pushA malicious user can supply inputs.target_repo pointing to an attacker-controlled repo, causing secrets or code to be exposed.
Mitigation Strategies
- Allowlist target repositories
Check the requested repo against a regex orcasestatement before cloning. - Use fine-grained PATs
Replace the defaultGITHUB_TOKENwith repo- or org-scoped PATs that limit write operations. - Pin revisions and verify sources
When consuming code, pin to specific SHAs and configure Dependabot/CodeQL scanning. - Log and audit access
Emit telemetry when cross-repo operations run and review logs for unexpected targets. - Prefer GitHub Actions Marketplace
Use prebuilt actions from trusted publishers instead of cloning arbitrary repos.
Secure Version
name: Approved Cross Repo Sync
on:
workflow_dispatch:
inputs:
target_repo:
- required: true
+ type: choice
+ options:
+ - my-org/docs
+ - my-org/app
+ required: true
jobs:
sync:
runs-on: ubuntu-latest
+ permissions:
+ contents: read
steps:
- uses: actions/checkout@v4
- name: Clone approved repo
+ env:
+ TARGET_REPO: ${{ inputs.target_repo }}
run: |
- git clone https://github.com/${{ inputs.target_repo }} target
- - name: Push changes
- run: |
- cd target
- git commit --allow-empty -m "sync"
- git push
+ case "$TARGET_REPO" in
+ my-org/docs|my-org/app) ;;
+ *) echo "Repo not allowlisted"; exit 1 ;;
+ esac
+ git clone https://github.com/$TARGET_REPO target
+ - name: Sync read-only data
+ run: rsync -a src/ target/
Impact
| Dimension | Severity | Notes |
|---|---|---|
| Likelihood | Cross-repo clones are common in monorepos and mirrored workflows. | |
| Risk | Exposes secrets to untrusted repos or allows supply-chain tampering. | |
| Blast radius | Any repository or service that the workflow token can reach becomes vulnerable. |
References
- GitHub Docs, “Granting access to workflows,” https://docs.github.com/actions/using-jobs/assigning-permissions-to-jobs 1
- GitHub Docs, “Creating a fine-grained personal access token,” https://docs.github.com/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token
GitHub Docs, “Granting access to workflows,” https://docs.github.com/actions/using-jobs/assigning-permissions-to-jobs ↩︎ ↩︎
Last updated on