Job runs with overly broad (write-all) permissions
Control: Job must not run with write-all permissions · Config key: workflowMustNotGrantPermissionsWriteAll
📋 What is this?
A workflow or job in committed YAML declares the literal permissions: write-all shortcut, which grants GITHUB_TOKEN every scope GitHub supports at once. Workflow-level write-all is propagated to every job without its own block. Plumber does not flag scope maps (contents: write, …), read-all, missing permissions: blocks (ISSUE-801), or ${{ }} expressions.
⚠️ Impact
Over-broad GITHUB_TOKEN scopes magnify the impact of any other vulnerability. A template-injection in a write-all job lets the attacker push to the repo, create releases, modify branch protection, etc.
🔧 How to fix
List only the scopes the job actually needs. Most jobs only need contents: read; release jobs need contents: write; CodeQL needs security-events: write.
# .github/workflows/release.yml — ❌ Write-alljobs: release: runs-on: ubuntu-latest permissions: write-all steps: - run: ./release.sh# .github/workflows/release.yml — ✅ Scopedjobs: release: runs-on: ubuntu-latest permissions: contents: write # to create the release packages: write # to push to ghcr.io steps: - run: ./release.sh💡 Tips
- Scope is static
permissions:keys in.github/workflows/only. Broad but explicit maps are intentionally out of scope for this control. - Pair with ISSUE-801 to catch jobs that omit a
permissions:block and inherit the repository default. - Permissions inside callee reusable workflows are not scanned unless those files are in the analyzed repository.
- Toggle via
github.controls.workflowMustNotGrantPermissionsWriteAll.enabled.
⚙️ Configuration
This control is configured in .plumber.yaml under the github section:
github:
controls:
workflowMustNotGrantPermissionsWriteAll:
enabled: trueSee the CLI documentation for the full configuration reference.