Github actions
Skill mickzijdel/dev-hooks/plugins/dev-hooks/skills/github-actions
Write, review, and harden GitHub Actions workflows against supply-chain attacks, and bump a whole fleet of repos' action pins to the latest versions. Use when writing or editing a workflow YAML (.github/workflows/*.yml, ci.yml), when asked to review a CI workflow or audit GitHub Actions security, when the ci-action-ref-reminder hook fires, or when the user wants to "bump my actions", "update the fleet", "pin actions to SHAs", run zizmor, or close supply-chain / pull_request_target / script-injection / GITHUB_TOKEN-permissions gaps. Pairs with references/security-checklist.md (the full checklist) and dev-env-setup's CI templates.From its SKILL.md
npx -y skills add mickzijdel/dev-hooks --skill github-actionsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
6.8 KB, ~1.6k tokens by cl100k_base, as published. Nobody here has run it
github-actions
The canonical home for everything GitHub Actions in your repos: the security checklist to apply when writing or reviewing a workflow, and the fleet-wide procedure for bumping action pins to their latest versions. The full checklist lives in references/security-checklist.md; read it whenever you touch a workflow. This skill is the security layer over [[dev-env-setup]], which owns the CI templates (already hardened to this standard).
The five that matter most
If you do nothing else when writing or reviewing a workflow, get these right:
- Pin every
uses:to a full commit SHA, not a tag or branch —owner/repo@<40-hex-sha> # vX.Y.Z. Tags are mutable; a compromised maintainer can repoint@v3to malicious code and every downstream run picks it up silently (tj-actions, Trivy). - Default
GITHUB_TOKENto read-only. Addpermissions: { contents: read }at the workflow level; grant more only on the specific job that needs it, at the job level. - Never
pull_request_target(orworkflow_run) in public repos. They run with secret access on fork-PR-controlled input. Use plainpull_request, or gate on the upstream event. - Never interpolate
${{ github.* }}intorun:. Branch names, PR titles, issue bodies are attacker-controlled. Assign to anenv:var first, then reference$VARin the shell (Ultralytics, Nx/s1ngularity). Same rule for LLM output and anything written to$GITHUB_ENV/$GITHUB_PATH. - Use OIDC for cloud credentials (AWS/Azure/GCP) instead of long-lived static secrets — short-lived, job-scoped, nothing to steal.
Writing or reviewing one repo's workflow
- Read references/security-checklist.md and walk the
workflow against it. The most common real finding is unpinned actions and a missing
permissions:block. - Pin/verify the refs. Resolve each action's latest release SHA and pin it with a version
comment:
a=actions/checkout tag=$(gh release view --repo "$a" --json tagName -q .tagName) # e.g. v7.0.0 sha=$(gh api "repos/$a/commits/$tag" --jq .sha) # dereferences annotated tags echo "uses: $a@$sha # $tag"pinactautomates this across a whole file (pinact runto pin tags→SHA with comments,pinact run -uto update to latest). Install it withmise use -g pinactormise exec -- pinactif a repo pins it. - Verify the pins resolve and the comments are honest before finishing:
Ifbash "$CLAUDE_PLUGIN_ROOT/skills/dev-env-setup/scripts/check_action_refs.sh" .github/workflows # SHA-pinned refs with a `# vX.Y.Z` comment are checked: the tag is resolved on the remote # and its SHA must match the pin. A mismatch (lying comment / wrong SHA) FAILs.gh/pinactis unavailable or unauthenticated, say so and ask the user — never guess a SHA. - Run actionlint + zizmor — correctness then security (the two analyzers the standard wires
in). actionlint catches schema/expression/
needs:errors; zizmor catches credential persistence, template injection, over-broad permissions:
Both are mise-pinned in every dev-env repo (actionlint -shellcheck= # correctness; -shellcheck= skips the run: shellcheck pass zizmor --no-progress .github/workflows/ # security; exit 0 = clean, non-zero = real findings zizmor --no-progress --fix=all .github/workflows/<file>.yml # apply mechanical fixes, then reviewmise.toml); install ad hoc withmise use -g zizmor actionlintelsewhere. Suppress a deliberate zizmor exception inline with# zizmor: ignore[<audit>], never by lowering the persona. (Dogfooded: the dev-env-setup CI templates ship oneactions-lintjob that runs both.)
Fleet-wide bump
Turn the per-repo recipe into one cross-repo pass (this is the "bump my fleet's actions" request). Mirror the cadence in the [[dev-env-bump-backfill-fleet]] memory: do the whole fleet in one session — branch, bump, verify, commit, push — so the repos stay in lockstep.
- Enumerate the fleet. Start from the dev-env fleet (repos carrying
DEV_ENV_VERSIONinmise.toml; the [[dev-env-bump-backfill-fleet]] memory lists the current set), and cross-check with live discovery:
Keep only repos that actually havegh repo list "$(gh api user -q .login)" --source --no-archived --limit 200 --json nameWithOwner -q '.[].nameWithOwner'.github/workflows/. Show the user the target set and confirm it before changing anything — don't sweep in repos they don't want touched. - Per repo (work in a temp clone or worktree, never on a dirty main):
Also add agit switch -c chore/bump-actions pinact run -u # pin + update every uses: to the latest SHA + comment bash "$CHECKER" .github/workflows # verify refs resolve and comments match git diff # eyeball before committingpermissions: { contents: read }block to any workflow missing one, and apply any other checklist gaps you spot. - Commit + push/PR with a consistent message per repo (e.g.
chore(ci): pin actions to SHAs and bump to latest). Open a PR unless the user wants direct pushes. Do all repos in the same session, then report a one-line summary per repo.
Guardrails: gh/pinact missing or unauthenticated → stop and surface it. A repo whose CI
is intentionally bespoke → flag it, don't force the standard. Never push to a repo's default
branch directly.
How this skill is reached
- Editing a workflow → the
ci-action-ref-reminderhook fires and points here. - Setting up / upgrading the dev env → dev-env-setup's CI templates ship pre-hardened to
this standard (SHA pins +
permissions:) and link back here; the dev-env v16 bump is where this became the default. - "Review this CI workflow" / "audit my GitHub Actions" → this skill's description triggers directly.
What ships with it: 1 file
10.0 KB alongside SKILL.md
references/
- security-checklist.md10.0 KB