Excessive Write Permissions
Excessive Write Permissions
Description
GitHub Actions defaults the GITHUB_TOKEN to contents: read / packages: write, but many workflows override permissions: write-all even when they only run tests or lint. If an attacker compromises that workflow (e.g., via dependency injection), they gain repository write access, allowing them to push malicious commits. GitHub recommends the principle of least privilege: grant only the scopes required per job. 1
Vulnerable Instance
- Workflow sets
permissions: write-all. - Jobs run read-only operations like linting or tests.
- Tokens unnecessarily grant push permissions.
name: CI
on: pull_request
permissions: write-all
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run lintIf a malicious dependency escapes the lint job, it can use the token to push commits or create releases.
Mitigation Strategies
- Set minimal global permissions
Start workflows withpermissions: read-allor specify exact read scopes. - Grant write per job
Only jobs that publish artifacts or tag releases should request write scopes. - Audit third-party actions
Ensure actions you use don’t require elevated permissions; update or replace if they do. - Split workflows
Keep read-only CI separate from deployment workflows requiring write access. - Monitor token use
Add logging aroundgit push/ghcommands to detect unexpected writes.
Secure Version
name: CI
on: pull_request
-permissions: write-all
+permissions:
+ contents: read
+ pull-requests: write
jobs:
lint:
runs-on: ubuntu-latest
+ permissions:
+ contents: read
steps:
- uses: actions/checkout@v4
- run: npm run lint
+ deploy:
+ needs: lint
+ if: github.ref == 'refs/heads/main'
+ permissions:
+ contents: write
+ steps:
+ - run: ./scripts/deploy.sh
Impact
| Dimension | Severity | Notes |
|---|---|---|
| Likelihood | Many workflows inherit write-all from templates or tutorials. | |
| Risk | Excess permissions let attackers overwrite code, create releases, or leak secrets. | |
| Blast radius | A single compromised job threatens the entire repository and dependent deployments. |
References
- GitHub Docs, “Assigning permissions to jobs,” https://docs.github.com/actions/using-jobs/assigning-permissions-to-jobs 1
- GitHub Docs, “Security hardening for GitHub Actions,” https://docs.github.com/actions/security-guides/security-hardening-for-github-actions
GitHub Docs, “Assigning permissions to jobs,” https://docs.github.com/actions/using-jobs/assigning-permissions-to-jobs ↩︎ ↩︎
Last updated on