GITHUB_TOKEN is an automatically created secret for authenticating a GitHub Actions workflow against GitHub resources. It is available through github.token or secrets.GITHUB_TOKEN, and actions can access it even when it is not passed as an input or environment variable. section 3.8
Treat the token as a scoped workflow credential, not a universal secret. Set only the permissions required at workflow or job level: once any scope is specified, unspecified scopes become none. Review granted permissions in the job log under Set up Job > GITHUB_TOKEN Permissions. section 3.8 section 10.3.1
Label pull requests with minimal access
A pull-request labeling job can grant contents: read to read its configuration and pull-requests: write to apply labels. Keeping these permissions explicit prevents unrelated repository capabilities from being available to the job. section 3.8
on: pull_request_target
permissions:
contents: read
pull-requests: write
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v4
This workflow listing places contents: read and pull-requests: write beside a pull_request_target trigger, showing a narrowly scoped labeling job. section 3.8
Actions performed with GITHUB_TOKEN are recorded as github-actions bot activity and do not trigger additional workflow runs, preventing recursive workflow loops. Token access is restricted for workflows triggered by pull requests from forks; their maximum permissions are read-only. section 3.8
Listing 10.5 Elevating privileges for a specific scope
name: Comment on the PR
permissions:
read: all
on:
workflow_run:
workflows: ["Receive PR"]
types:
- completed
jobs:
upload:
runs-on: ubuntu-latest
if: >
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'success'
permissions:
pull-requests: write
steps:
- name: Download Artifact
- uses: actions/download-artifact@v3
with:
name: pr
- name: unzip artifact
run: unzip pr.zip
- name: Comment on PR
uses: actions/github-script@v3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
var fs = require('fs');
var issue_number = Number(fs.readFileSync('./pr/NR'));
await github.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue_number,
body: 'Everything is OK. Thank you for the PR!'
});
This listing starts with read: all and adds pull-requests: write only to the job that posts a pull-request comment with secrets.GITHUB_TOKEN. section 10.3.1
Use read-only defaults and elevate a specific scope only where needed. This is especially important for self-hosted runners and untrusted pull requests: GitHub limits GITHUB_TOKEN on pull_request triggers, while runner isolation, approval, and protection rules reduce broader job risks. section 6.2 section 10.3.1
