BUILD-12475 Document persist-credentials: false for actions requiring contents: write - #341
Conversation
Every composite action requiring contents: write (config-maven, build-maven, config-poetry, build-poetry, config-gradle, build-gradle, config-npm, build-npm, build-yarn, config-pip, config-uv) checks out the repo before running PR-authored build/test code. actions/checkout defaults to persist-credentials: true, writing that now-elevated token into .git/config where PR-authored code could use it to push or manipulate build-number refs - these actions themselves take their token from github.token in their own step env, not the git credential helper, so this doesn't affect their behavior. Confirmed working (all CI green) on SonarSource/sonar-dummy-maven-enterprise#143, which applies this to a real caller. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Code Review
|
| Auto-apply | Compact | Unblock |
|
|
|
Was this helpful? React with 👍 / 👎 | Gitar
There was a problem hiding this comment.
Pull request overview
Updates the repository documentation to harden GitHub Actions workflow examples that run PR-authored code after checkout while requiring contents: write, by preventing actions/checkout from persisting the elevated token into .git/config.
Changes:
- Add
with: persist-credentials: falsetoactions/checkoutin 11 README workflow examples that requestcontents: write. - Leave the
check-scaexample unchanged (as it does not requirecontents: write).
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
| - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | ||
| with: | ||
| persist-credentials: false |
There was a problem hiding this comment.
⚠️ Bug: persist-credentials: false breaks git fetch inside build-* actions
The build-maven, build-gradle, build-npm, build-poetry and build-yarn composite actions run git fetch --unshallow / git fetch origin "$GITHUB_BASE_REF" against origin to give SonarQube full history — these use the credential that actions/checkout writes into .git/config, not github.token from step env (no http.extraheader/GH_TOKEN is configured for git anywhere in the repo). With persist-credentials: false in a private repo the fetch is unauthenticated: build-gradle runs git fetch origin "$GITHUB_BASE_REF" unguarded on every PR (build-gradle/build.sh:74-77) and will fail the job, while the maven/npm/poetry/yarn variants swallow the failure with || true on the shallow path, so history is silently not unshallowed and new-code/blame analysis degrades with a green build — which is why the end-to-end test looked clean. Either keep credentials on the checkout for the build-* examples, or make the build actions authenticate git themselves (e.g. git -c http.extraheader="AUTHORIZATION: basic $(printf 'x-access-token:%s' "$GITHUB_TOKEN" | base64)" fetch ...) before documenting this pattern for them.
Revert persist-credentials: false in the six build- examples (build-maven, build-poetry, build-gradle, build-npm, build-yarn) until the actions authenticate their own git fetch; keep it only in the config- examples, which perform no git remote operations.:**
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
# Full history for SonarQube; credentials stay persisted because the
# build-* actions fetch from origin themselves.
fetch-depth: 0
- uses: SonarSource/ci-github-actions/build-gradle@v1
Was this helpful? React with 👍 / 👎
| contents: write | ||
| steps: | ||
| - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | ||
| with: | ||
| persist-credentials: false |
There was a problem hiding this comment.
💡 Quality: New persist-credentials pattern not propagated or explained
The migration templates in .cursor/cirrus-github-migration.md (lines 313-320 and 1789-1795) grant contents: write and check out with the default persist-credentials: true, so every workflow generated from them reproduces exactly the token-persistence exposure this PR sets out to close; nothing in the diff updates them or states they are intentionally excluded. Additionally, the README change is snippet-only: the per-action "Required GitHub Permissions" sections that call out contents: write never mention persist-credentials: false, so a reader who copies only the permissions block (or is told to add contents: write, as at README:88-92) gets the elevated token without the mitigation. Add the with: persist-credentials: false to the migration templates and one sentence of rationale next to the contents: write requirement.
Apply the same pattern to both build-job templates in .cursor/cirrus-github-migration.md and document the rationale once in the README requirements prose.:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
# contents: write is elevated for this job; don't leave that token in
# .git/config where PR-authored build code could reuse it.
persist-credentials: false
Was this helpful? React with 👍 / 👎
|
We decided not to use |



Every composite action requiring
contents: write(config-maven,build-maven,config-poetry,build-poetry,config-gradle,build-gradle,config-npm,build-npm,build-yarn,config-pip,config-uv) checks out the repo before running PR-authored build/test code (mvn verify,./gradlew build, etc.).actions/checkoutdefaults topersist-credentials: true, writing the job's now-elevatedcontents: writetoken into.git/config. A caller's PR-authored code running after checkout could use that persisted token to push tomasteror manipulaterefs/build-number/*, since these composite actions themselves read their token fromgithub.tokenin their own step env — not from the git credential helper — sopersist-credentials: falsedoesn't affect them.Adds
persist-credentials: falseto theactions/checkoutstep in each of the 11 usage examples above (check-sca's example is untouched — it doesn't requirecontents: write).Confirmed working end-to-end: flagged by gitar-bot on sonar-dummy-maven-enterprise#143, applied there, all CI green (Linux/Windows build+verify, pre-commit).
Tracked in BUILD-12473.