hardening: lock GITHUB_TOKEN to contents: read across all CI jobs - #337
Open
Keengfk wants to merge 1 commit into
Open
hardening: lock GITHUB_TOKEN to contents: read across all CI jobs#337Keengfk wants to merge 1 commit into
Keengfk wants to merge 1 commit into
Conversation
Add an explicit top-level permissions block to ci.yml and document the
per-job audit that justifies the chosen scopes.
Problem: no permissions: block meant every job ran with the GitHub
default, which includes contents: write on push events. A compromised
third-party action (Swatinem/rust-cache, dtolnay/rust-toolchain) or a
malicious PR step would have had repository write access — more than
any job here actually needs.
Changes:
.github/workflows/ci.yml
- Add top-level permissions: contents: read
- Inline per-job audit comment on all 6 jobs (fmt, contract,
wasm-size, proptest, audit, mutants)
- Block header documents: why only read, trigger coverage
(push vs pull_request), and guidance for future jobs that
need elevated scope
CONTRIBUTING.md
- New 'GITHUB_TOKEN permission model' section in the Maintainer
Guide: per-job audit table, rationale, and example of how to
add a narrowly-scoped job-level override for any future job
that needs to write (e.g. posting a PR comment)
No build logic changed. All existing CI jobs run identically with the
narrowed token — none of them call any GitHub API beyond checkout.
|
@Keengfk Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Without an explicit permissions: block, every job in ci.yml ran with GitHub's
default token scopes — which include contents: write on push events from the
same repository. None of the six jobs here (formatting, tests, wasm-size check,
proptest, dependency audit, mutation testing) need write access to anything. A
compromised third-party action (Swatinem/rust-cache, dtolnay/rust-toolchain) or
a malicious step in a PR-triggered run would have had unnecessary repository
write privilege available to abuse.
What changed
.github/workflows/ci.yml
Added a top-level permissions: contents: read block immediately after the on:
trigger. The block header explains:
file writes and don't require a GitHub API permission
contents: write; for fork pull_request events GitHub already enforces
read-only, so this covers both trigger types consistently
job that genuinely needs more (e.g. pull-requests: write to post a PR comment)
— without widening the workflow-level block
Each of the six jobs also got an inline # Needs: comment documenting its
specific requirements so the rationale is visible at the job level, not just at
the top of the file.
CONTRIBUTING.md
Added a "GITHUB_TOKEN permission model" section to the Maintainer Guide with:
needs elevated scope
No logic changed
All six CI jobs run identically with the narrowed token. None of them call any
GitHub API beyond checkout (actions/checkout uses contents: read to clone the
repository). The change is purely additive — one YAML key and documentation.
Audit summary
┌───────────┬──────────────────────────────────────────────┬────────────────┐
│ Job │ Operations │ Scope needed │
├───────────┼──────────────────────────────────────────────┼────────────────┤
│ fmt │ checkout, cargo fmt --check │ contents: read │
├───────────┼──────────────────────────────────────────────┼────────────────┤
│ contract │ checkout, clippy, test │ contents: read │
├───────────┼──────────────────────────────────────────────┼────────────────┤
│ wasm-size │ checkout, build, write to │ contents: read │
│ │ $GITHUB_STEP_SUMMARY (local file) │ │
├───────────┼──────────────────────────────────────────────┼────────────────┤
│ proptest │ checkout, cargo test │ contents: read │
├───────────┼──────────────────────────────────────────────┼────────────────┤
│ audit │ checkout, cargo audit (RustSec over HTTPS) │ contents: read │
├───────────┼──────────────────────────────────────────────┼────────────────┤
│ mutants │ checkout, cargo mutants (runner-local temp │ contents: read │
│ │ copy) │ │
└───────────┴──────────────────────────────────────────────┴────────────────┘
closes #278