Documentation
¶
Overview ¶
wfaudit reports GitHub Actions workflows that let somebody else's pull request reach this repository's secrets or write token.
wfaudit DIR... # each DIR a checkout, or a directory of checkouts wfaudit -api DIR... # also ask GitHub what a job with no permissions gets wfaudit -fail DIR... # exit 1 if anything at MEDIUM or above is found
Four rules, after GitHub Security Lab's "Keeping your GitHub Actions and workflows secure" series and the audits of the same names in zizmor:
- dangerous-trigger: pull_request_target or workflow_run, which run with the base repository's secrets and a write token for pull requests from forks. HIGH when the workflow also checks out the pull request's code (the "pwn request"), MEDIUM otherwise.
- excessive-permissions: write-all anywhere (HIGH), or write granted at the workflow level, where every job inherits it (MEDIUM).
- artipacked: actions/checkout keeps its token in .git/config unless persist-credentials is false, and a job that then uploads the whole workspace as an artifact publishes that token (HIGH).
- secrets-under-privileged-trigger: a secret read in a workflow with a privileged trigger (MEDIUM).
Template injection -- an untrusted ${{ github.event... }} expanded inside run: -- is NOT checked here: actionlint already reports it, and two tools checking one thing disagree the day one of them is fixed.
Written 2026-10-10, after an audit of go-widgets' 33 workflows had been attempted with grep in zsh: an unquoted $W was not word-split, grep read all 33 paths as one file name, and every section of the report listed every workflow. A tool that parses YAML cannot fail that way, and its tests say what each rule must and must not match.
It reads working trees; it makes no API call unless -api is given, and then one per repository.