https://github.com/praetorian-inc/gato
Gato (GitHub Attack Toolkit) from Praetorian is a Python CLI for enumerating and attacking GitHub organizations' CI/CD pipelines: it identifies poisoned pipeline execution risks, abuses self-hosted runners via workflow and run-log analysis, exfiltrates Actions secrets, and automates fork-PR/workflow-based command execution. Version 1.7 added an Actions Artifacts Secrets Scanner that downloads and recursively scans workflow artifacts with NoseyParker, which Praetorian used to find critical secrets leaks in prominent open-source projects. The project is now archived/superseded by Praetorian's multi-platform tool Trajan, which merges Gato (GitHub) and Glato (GitLab) attack capabilities.
What it is
Gato (GitHub Attack Toolkit) is a Python CLI from Praetorian for enumerating and attacking CI/CD pipeline weaknesses across a GitHub organization's repos, operating against a GitHub classic PAT or App installation token.
How it works
Gato is organized into three subcommands: gato search, gato enum, and gato attack. Enumeration draws on GitHub Code Search, SourceGraph search, and GitHub Action run-log parsing to find self-hosted runners and poisoned-pipeline-execution candidates. The Actions Artifacts Secrets Scanner (added in v1.7) downloads workflow artifacts, recursively extracts them, and scans the contents with NoseyParker (which must be separately installed and on $PATH); results exclude common false-positive rules by default. Attack modules automate fork-PR and workflow-based command execution and workflow secrets exfiltration.
Example invocation for the artifact scanner against a list of orgs, with self-hosted runner enumeration skipped and all secret findings included:
gato e --enum_wf_artifacts --include_all_artifact_secrets --skip_sh_runner_enum -O testorgs.txt -oJ testorgoutput.jsonPreconditions / Affected
- Requires OS X or Linux, Python 3.7+, git 2.27+ on PATH; the fork-PR attack module additionally requires
sedon PATH. - Requires a GitHub classic PAT or App installation token (App tokens need at least
Actions:readandContents:readfor enumeration). - NoseyParker must be installed separately for the artifact secrets scanner to function.
- To bound runtime, the artifact scanner by default downloads only one artifact per name, caps at 50 artifacts per repo, skips more than 10 files over 536 MB, and never downloads files over 2.68 GB — tuned so it can scan the top 200 GitHub orgs in 48 hours. These limits are hardcoded in
scan_wf_artifacts()ingato/enumerate/repository.pyand must be edited there to change.
What to do
- Install via
pip install .inside a virtualenv after cloning; adevbranch exists with newer features (covered by the same integration test suite) for those willing to tolerate more bugs. - Set the token via
export GH_TOKEN=<token>or enter it when prompted. - Run
gato -h,gato search -h,gato enum -h,gato attack -hto see module-specific flags. - Consult the project wiki for OpSec considerations before running attack/enumeration modules against real targets.
Caveats
The repo is archived with no further updates, bug fixes, or security patches — Praetorian directs users to migrate to Trajan (github.com/praetorian-inc/trajan), which merges Gato and Glato. The page itself warns that public-artifact secret scans can surface many false positives, which is why default rule exclusions exist (--include_all_artifact_secrets overrides them). Disclosure details for the real-world secrets Praetorian found via the scanner were withheld pending vendor disclosure, so no specifics are available on the page.
Technologies named here
- GitHub Actions
- Gato
- Trajan
- GitHub
- Glato
- Nosey Parker
- Python
- git
Techniques named here
- Poisoned Pipeline Execution
- Self-hosted runner attack enumeration
- Actions Artifacts Secrets Scanning
- Classic PAT privilege enumeration
- Code search based enumeration
- Bulk repo sparse clone
Related in DevSecOps
JFrog: The Governance Gap Between Your Policy and Your Pipeline

Dev Machine Guard Now Supports Windows - StepSecurity

Socket: TanStack npm Packages Compromised
