ci-cd-security
Scan GitHub Actions workflow files for security vulnerabilities by reading the YAML and reporting findings directly — no external tools, no installation, no shell execution. Use this skill whenever the user shares a `.github/workflows/` file, pastes workflow YAML, asks for a CI/CD security review, mentions `pull_request_target`, `workflow_run`, action pinning, `GITHUB_TOKEN` permissions, pwn requests, template injection, cache poisoning, secret exfiltration, supply chain risk, or any GitHub Acti
Security Assessment
About ci-cd-security
CI/CD Security Scanner turns the model into a GitHub Actions workflow-YAML scanner that reads a workflow file and reports security findings with severity and a concrete rewrite, with no external tools, installation, or shell execution: the analysis is simply the model reading the YAML. It is meant to trigger whenever a user shares a .github/workflows/ file, pastes workflow YAML, asks for a CI/CD security review, or mentions topics such as pull_request_target, workflow_run, action pinning, GITHUB_TOKEN permissions, pwn requests, template injection, cache poisoning, secret exfiltration, or supply-chain risk. Its rules encode the current consensus from Astral, OpenSSF, GitHub Security Lab, Chainguard, and the zizmor audit set, aiming to flag what those tools would flag without running them, and it biases toward triggering rather than answering from memory because CI/CD defaults are wrong almost everywhere.
The mental model places every workflow on a two-by-two of privileged versus unprivileged crossed with trusted versus untrusted code, where compromise happens in exactly one cell: a privileged workflow running untrusted code. Privileged means having secrets, write permissions, or producing a sensitive artifact, while untrusted code is anything a fork PR author can influence, including PR source, title, body, commit messages, branch names, read files, caches, and artifacts from another untrusted workflow; when unsure, a value is treated as untrusted because the cost of a false negative is a supply-chain compromise.
The scan proceeds through ordered passes, each mapping to an attack class. Pass 1 inspects the on block for dangerous triggers (pull_request_target and workflow_run as P0, comment and issue events as P1, broad push wildcards as P2). Pass 2 checks permissions blocks, flagging a missing top-level block or write-all and recommending least privilege. Pass 3 reviews action pinning, treating tag pins as P1, branch pins as P0, and SHA pins without a version comment as a style finding, with the fix being a full 40-character commit SHA plus a version comment. Pass 4 hunts shell or template injection from untrusted substitutions in run blocks, with direct interpolation as P0 and the fix routing values through environment variables. Pass 5 flags untrusted checkout of a PR head SHA in privileged contexts and risky persist-credentials defaults. Pass 6 flags caching in release or secret-handling workflows due to cache poisoning, and Pass 7 covers artifact-borne injection from untrusted-code workflows. Each finding names the issue, explains why it is dangerous, and proposes the rewrite.
FAQ
Does this skill run any external tools or commands?
No. There are no tools to install and no commands to run; the analysis is the model reading the workflow YAML directly and reporting findings.
What is the core risk it is looking for?
A privileged workflow running untrusted code. Privileged means having secrets, write permissions, or producing a sensitive artifact, and untrusted code is anything a fork PR author can influence.
Which triggers are flagged as most dangerous?
pull_request_target and workflow_run are rated P0, the canonical pwn-request vectors. Comment and issue events such as issue_comment are P1, and push with broad wildcards is P2.
How does it want actions to be pinned?
By full 40-character commit SHA with a version comment. Tag pins are rated P1 and branch pins P0 because both are mutable and can be moved by an attacker who compromises the action repo.
How should untrusted values in run blocks be handled?
Direct interpolation of untrusted github.event or github.head_ref fields into a run script is P0 template injection. The fix is to pass the value through an environment variable and reference it as a shell variable instead.
Install ci-cd-security
Quick Setup:
- Copy the skill folder to
.claude/skills/ - Claude will automatically detect and use the skill
Repository
superagent-ai/skills