liveBook · Manning

Principle of least privilege

As explained in GitHub Actions in Action: Continuous integration and delivery for DevOps

The principle of least privilege is a security practice of granting only the minimum permissions required for an actor or process to perform its task.

The principle of least privilege limits users, actions, and processes to the minimum access required for their tasks. In GitHub Actions, this applies especially to secrets and the automatically provided GITHUB_TOKEN, whose exposure can enable lateral movement. section 10.3 section 10.3.1

Apply least privilege to workflow credentials and execution paths:

  • Give each secret only the required operation and scope; for example, allow a cloud-upload token to write without permitting reads or deletes. section 10.3.1
  • Use distinct tokens for distinct scenarios instead of one universal credential. section 10.3.1
  • Set workflow-level permissions to read-only, then add narrowly scoped permissions at the job level when a task requires them. section 10.3.1
  • Treat pull requests from forks and other workflow triggers differently because GITHUB_TOKEN permissions vary by trigger. section 10.3.1
  • Separate low-privilege execution from high-privilege operations, and run the latter only for trusted sources rather than incoming pull-request code. section 10.5
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!'
            });

The configuration grants read access by default, then elevates only the pull-requests scope for a job that comments on a successful pull request workflow. section 10.3.1

Scoped pull-request commenting

A workflow triggered after a successful pull-request run can download an artifact and post a comment. Its workflow permissions remain read-only, while the commenting job receives pull-requests: write. section 10.3.1

How GitHub Actions in Action: Continuous integration and delivery for DevOps covers it

How deep it goes
Explains scoped secrets, trigger-dependent tokens, workflow and job permissions, and privilege-separated execution.
Examples
Uses cloud-upload credentials and a pull-request comment workflow with narrowly elevated job permissions.
What it assumes
Assumes familiarity with GitHub Actions workflows, secrets, triggers, and repository tokens while defining least privilege directly.
What you can do after
Operate/configure GitHub Actions workflows with explicit read-only defaults and narrowly scoped job-level elevations.
How it connects
Connects secrets, GITHUB_TOKEN, workflow triggers, pull requests, private runners, expression injection, and security scanning.

Also explained in

Compare how 17 books explain principle of least privilege →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of GitHub Actions in Action: Continuous integration and delivery for DevOps. The section links point to the parts of the book it draws on.