The auto-generated runner identity
Every workflow run gets an automatically issued GITHUB_TOKEN. It's an installation token for the runner, scoped to the current repo. Use it to call the GitHub API without provisioning a personal access token.
Available as ${{ secrets.GITHUB_TOKEN }} or ${{ github.token }}. Lives only for the duration of the run, then expires.
Default permissions are too generous
Until 2023, GITHUB_TOKEN defaulted to write on most things (contents, issues, pull-requests). Now the org default can be either 'permissive' (legacy) or 'restricted' (read all). Always check and prefer restricted.
Scope per workflow with permissions::
contents: read— checkout, no push.contents: write— push commits, tags, releases.pull-requests: write— comment on PRs, create PRs.issues: write— comment on issues.id-token: write— request OIDC tokens (covered in next lesson).packages: write— push to GHCR.security-events: write— upload SARIF for code scanning.