By default, actions/checkout writes the GitHub token to the local .git/config file, where it remains accessible to every subsequent step in the job. Any script, dependency, or action that runs later can read this token and use it to make authenticated API calls or push to the repository.
A compromised dependency or malicious post-install script reads the token from .git/config:
cat .git/config | grep "url.*x-access-token"
The token typically has contents: write permission, allowing the attacker to push code, create releases, or modify branch protection settings.
Add persist-credentials: false to every checkout step:
# Before (token persists in .git/config)
- uses: actions/checkout@v4
# After (token is not stored)
- uses: actions/checkout@v4
with:
persist-credentials: false
If a later step needs to push, configure credentials explicitly and immediately before the push, rather than relying on the persisted checkout token.
The persisted token expands the attack surface of your entire CI job. Every step after checkout -- including third-party actions and dependency install scripts -- has implicit access to repository write credentials.