-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Description
Describe the problem
Two CI/CD hygiene improvements that follow the principle of least privilege:
1. Persisted git credentials (persist-credentials: true default)
All actions/checkout usages retain the default persist-credentials: true, which writes the GITHUB_TOKEN into .git/config as a base64-encoded HTTP extraheader. This token remains readable by any process for the entire workflow run. The most sensitive instances are:
- Release workflow (
release.yml): Token hascontents: write,id-token: write, andpull-requests: writepermissions, plus npm publishing access - Autofix workflow (
autofix-lint.yml): Token hascontents: writeand is exposed topnpm install,pnpm format, and code generation steps
After checkout, any subsequent step can extract the token:
grep -A1 'extraheader' .git/config
# AUTHORIZATION: basic <base64-encoded-token>2. Over-broad secret inheritance in platform tests
The platform-tests-all.yml workflow passes all repository-level secrets to the Vercel tests workflow via secrets: inherit, when only three specific secrets are needed (VERCEL_TOKEN, VERCEL_PROJECT_ID_BASIC, VERCEL_ORG_ID). Any repository-level secrets added in the future will automatically become accessible without explicit review.
# Current
jobs:
vercel:
uses: ./.github/workflows/platform-tests-vercel.yml
secrets: inherit # passes ALL repository secretsDescribe the proposed solution
For persisted credentials, add persist-credentials: false to all actions/checkout usages:
- uses: actions/checkout@v6
with:
persist-credentials: falseFor workflows that need to push commits (like autofix-lint.yml), configure git authentication explicitly only for the push step and unset it immediately after:
- name: Push changes
run: |
git config --local http.https://github.com/.extraheader \
"AUTHORIZATION: basic $(echo -n x-access-token:${{ github.token }} | base64)"
git push origin HEAD
git config --local --unset http.https://github.com/.extraheaderFor secret inheritance, replace secrets: inherit with explicit secret passing:
jobs:
vercel:
uses: ./.github/workflows/platform-tests-vercel.yml
with:
sha: ${{ inputs.sha }}
secrets:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_PROJECT_ID_BASIC: ${{ secrets.VERCEL_PROJECT_ID_BASIC }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}Alternatives considered
- Relying on GitHub's token expiration (tokens expire after the workflow run) — but within a single run, the token is available to all steps regardless of whether they need it.
- Using environment-scoped secrets exclusively — this helps for the platform tests case but doesn't address the persisted credentials issue.
Importance
would make my life easier
Additional Information
Affected workflows:
ci.yml— multiple checkout instances (contents: read, lower risk)autofix-lint.yml— checkout withcontents: writerelease.yml— checkout withcontents: write,id-token: write,pull-requests: writeplatform-tests-vercel.yml— checkout withcontents: readaudit.yml— checkout withcontents: readplatform-tests-all.yml—secrets: inheritto called workflow
These changes complement SHA-pinning of third-party actions as general CI/CD hardening best practices.