supply-chain-auditor
Supply Chain Security Auditor
Phase 1: Repo Detection
Detect repository characteristics using Glob and Grep. Record which categories apply — skip inapplicable checks silently.
| Signal file(s) | Category flag |
|---|---|
package.json |
js |
pnpm-lock.yaml OR pnpm-workspace.yaml |
js-pnpm |
yarn.lock |
js-yarn |
package-lock.json |
js-npm |
bun.lock OR bun.lockb |
js-bun |
pyproject.toml OR requirements.txt OR setup.py |
python |
uv.lock OR [tool.uv] in pyproject.toml |
python-uv |
Cargo.toml |
rust |
go.mod |
go |
.github/workflows/*.yml or .github/workflows/*.yaml |
github-actions |
.github/dependabot.yml |
dependabot |
renovate.json OR renovate.json5 OR .renovaterc OR .renovaterc.json OR renovate key in package.json |
renovate |
.github/PULL_REQUEST_TEMPLATE.md OR .github/PULL_REQUEST_TEMPLATE/ |
has-pr-template |
Dockerfile OR docker-compose.yml OR docker-compose.yaml |
docker |
Fallback: If dependabot not detected, run gh pr list --author 'app/dependabot' --state all --limit 1 — if results, set dependabot-pr-only. Same for renovate with --author 'app/renovate' → renovate-pr-only.
Phase 2: Audit Checks
Severity levels: CRITICAL (actively exploitable) · HIGH (one step from exploitation) · MEDIUM (defense-in-depth gap) · LOW (best practice missing) · PASS (no issue)
Category 1: CI Issues — code fixes applied in PR
Findings in this category MUST be fixed with actual code changes committed in the PR branch.
1.1: GitHub Actions SHA Pinning
Applies to: github-actions
Search .github/workflows/*.yml, .github/workflows/*.yaml, and .github/actions/*/action.yml for uses: directives.
- PASS: 40-char hex SHA (e.g.,
actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4) - PASS: Local actions (
./.github/actions/...) - CRITICAL: Tag or branch reference (e.g.,
actions/checkout@v4,some-org/action@main)
The actions/ org actions must still be pinned — no namespace is inherently safe.
1.2: Dangerous Workflow Triggers
Applies to: github-actions
pull_request_target— CRITICAL if workflow checks out PR head (ref: ${{ github.event.pull_request.head.sha }}orref: ${{ github.head_ref }}), HIGH otherwise.issue_comment— HIGH if noauthor_associationpermission check found.workflow_run— MEDIUM if it processes artifacts without validation.workflow_dispatchwith${{ github.event.inputs.* }}interpolated inrun:steps — MEDIUM (command injection).
1.3: Docker Image Pinning
Applies to: docker
Check Dockerfile and docker-compose.yml/docker-compose.yaml:
FROM image:latest— HIGHFROM image:tagwithout@sha256:digest — MEDIUMFROM image@sha256:...— PASS
1.4: CI Lock File Usage
Applies to: github-actions AND (js OR python OR rust)
Scan all .github/workflows/*.yml and .github/workflows/*.yaml run: steps for dependency install commands that bypass lockfiles:
npm installornpm iwithout usingcisub-command — HIGH. Fix: replace withnpm ci.yarn install(Yarn v1 / Classic) without--frozen-lockfile— HIGH. Fix: add--frozen-lockfile. Note: Yarn v2+ (Berry) defaults to immutable installs in CI viaenableImmutableInstalls, soyarn installwithout--immutableis PASS when using Yarn v2+.pnpm installwithout--frozen-lockfile— PASS. pnpm defaults to--frozen-lockfilewhen theCIenvironment variable is set (as in GitHub Actions). Adding the flag explicitly is acceptable for clarity but not required.bun installorbun iwithout usingcisub-command — HIGH. Fix: replace withbun ci.uv syncwithout--frozen— MEDIUM. Fix: add--frozen.cargo installwithout--locked— MEDIUM. Fix: add--locked.
1.5: Unpinned Dependencies in CI Commands
Applies to: github-actions
Scan run: steps in workflow files for commands that pull and execute unpinned packages at CI time:
npx <package>@latestornpx <package>without version pin — HIGH. Fix: pin exact version (e.g.,npx package@1.2.3). Recommend adding the tool as adevDependencyand running via lockfile instead, since pinning the tool version does not pin its transitive dependencies.bunx <package>@latestorbunx <package>without version pin — HIGH. Fix: pin exact version (e.g.,bunx package@1.2.3). Recommend adding the tool as adevDependencyand running via lockfile instead, since pinning the tool version does not pin its transitive dependencies.pip install <package>without==version pin in arun:step — HIGH. Fix: pin with==(e.g.,pip install package==1.2.3). Recommend adding torequirements.txtwith hashes (--require-hashes) or usinguvwith a lockfile, since pinning does not pin transitive dependencies.npm install -g <package>without version pin — HIGH. Fix: pin exact version (e.g.,npm install -g package@1.2.3).go install <package>@latest— HIGH. Fix: pin to an exact version (e.g.,go install package@v1.2.3). Treat barego install <package>(no@versionsuffix) as a finding only when it runs outside the repo module context; in module-aware mode a barego installresolves from the current module'sgo.mod/go.sumand is not unpinned. Note:go installalways builds from source with the module'sgo.sum, so transitive dependencies are already verified.curl ... | shorwget ... | sh(piped installs) — CRITICAL. Fix: replace with a package manager, or at minimum download to a file, verify a checksum, then execute.
Category 2: Automatic Dependency Updates — recommendations only
Findings in this category MUST NOT be fixed with code changes. Include them as actionable recommendations in the PR description.
2.1: Dependabot Cooldown (docs)
Applies to: dependabot OR dependabot-pr-only
If dependabot-pr-only: HIGH — no config file found, recommend creating .github/dependabot.yml with cooldown setting.
If dependabot: check each updates entry for cooldown.default-days. HIGH if missing, MEDIUM if < 3 days.
2.2: Renovate Minimum Release Age
Applies to: renovate OR renovate-pr-only
If renovate-pr-only: HIGH — no config file found, recommend creating renovate.json with minimumReleaseAge and helpers:pinGitHubActionDigests preset.
If renovate: check config files for:
minimumReleaseAge(top-level or inpackageRules) — HIGH if missing, MEDIUM if < 3 days.helpers:pinGitHubActionDigestsinextends— MEDIUM if missing (whengithub-actionsalso detected).
Category 3: Dev Dependency Install — recommendations only
Findings in this category MUST NOT be fixed with code changes. Include them as actionable recommendations in the PR description.
3.1: Dependency Version Pinning
Applies to: all repo types with dependencies
Exception — downgrade to PASS when both: (1) a lockfile is committed, AND (2) a minimum release age / cooldown is configured (Dependabot cooldown, Renovate minimumReleaseAge, pnpm minimumReleaseAge, or uv exclude-newer). If only one condition is met, flag as normal.
JS — check all package.json files (root + workspace packages). Flag ^, ~, >=, >, *, latest in dependencies (HIGH) and devDependencies (MEDIUM). Do NOT flag workspace:*/workspace:^/workspace:~ references.
Python — check pyproject.toml, requirements.txt, setup.py, setup.cfg. Flag anything without == pin. HIGH.
Rust — check Cargo.toml. Flag deps without = prefix or using *. MEDIUM if Cargo.lock committed, HIGH if not.
Go — flag if go.sum not committed. HIGH.
3.2: pnpm Supply Chain Protections
Applies to: js-pnpm
Check pnpm-workspace.yaml:
minimumReleaseAge— recommended3or7days. HIGH if missing.blockExoticSubdeps— MEDIUM if missing.
3.3: uv Supply Chain Protections
Applies to: python-uv
Check pyproject.toml [tool.uv] and uv.toml for exclude-newer (RFC 3339 datetime). MEDIUM if missing. LOW if present but older than 90 days.
Phase 3: Output Format
Produce a markdown report with:
- Header: repo name, date, detected ecosystems
- Summary table: severity counts (CRITICAL/HIGH/MEDIUM/LOW/PASS)
- Category 1 — CI Issues (code fixes applied in this PR): findings grouped by severity, each with: file path (line N), issue description, concrete fix applied
- Category 2 — Automatic Dependency Updates (recommendations): findings grouped by severity, each with: issue description, recommended action for the user to take
- Category 3 — Dev Dependency Install (recommendations): findings grouped by severity, each with: issue description, recommended action for the user to take
- Passed checks list
- Collapsible "Why This Matters" section with real-world supply chain attack examples (include links and CVEs):
- GitHub Actions: Trivy (CVE-2026-33634), KICS (CVE-2026-33634), LiteLLM (CVE-2026-33634), reviewdog (CVE-2025-30154), tj-actions/changed-files (CVE-2025-30066)
- Package registries: Axios npm compromise impacting OpenAI (2026), PyTorch torchtriton (2022), colors.js (CVE-2021-23567, 2022), ua-parser-js (2021), event-stream (2018)
- Prioritized next steps, split into:
- Already fixed — Category 1 items addressed in this PR
- Follow-up actions — Category 2 and 3 items for the user to address
Phase 4: PR Guidance
Duplicate PR Check
Before creating a PR, check for existing supply-chain hardening PRs:
- Run:
gh pr list --search "supply chain" --state open --limit 5 - Run:
gh pr list --search "supply chain" --state merged --limit 5 - If any open PR title contains "supply chain" or "supply-chain" — do not create a new PR. Inform the user and suggest updating the existing PR.
- If a merged PR with a matching title exists from the last 7 days — warn the user and ask for confirmation before proceeding.
PR Creation
Check for a PR template (.github/PULL_REQUEST_TEMPLATE.md or .github/PULL_REQUEST_TEMPLATE/) and follow it if present. Title: security: Harden supply chain <area>.
Code changes (Category 1 only): Create a branch and commit fixes for all Category 1 findings:
- Pin GitHub Actions to SHA digests (1.1)
- Fix dangerous workflow triggers (1.2)
- Pin Docker images to SHA digests (1.3)
- Add
--frozen-lockfile/--locked/ciflags to CI install commands (1.4) - Pin or remove unpinned CI dependency references (1.5)
PR description structure:
## Summary
Brief description of supply chain hardening changes.
## Changes Made (CI Fixes)
- List each code change with file path and what was fixed
## Recommendations — Automatic Dependency Updates
> These items require manual follow-up and are NOT included as code changes in this PR.
- [ ] [2.1] ...
- [ ] [2.2] ...
## Recommendations — Dev Dependency Install Protections
> These items require manual follow-up and are NOT included as code changes in this PR.
- [ ] [3.1] ...
- [ ] [3.2] ...
- [ ] [3.3] ...
Only include recommendation sections that have findings. Use checkboxes so users can track follow-up.
Important Notes
- Never suggest removing lockfiles.
- When suggesting SHA pinning, look up the actual SHA using
gh api repos/{owner}/{repo}/git/ref/tags/{tag}. Do not invent SHAs. - For monorepos, check all
package.jsonfiles, not just root. - Always include exact file paths and line numbers in findings.
- When fixing CI install commands (1.4), preserve existing flags — only append the lockfile flag if missing.
More from erezrokah/skills
you-dont-need-isr
Audit a Next.js project's Incremental Static Regeneration usage and suggest simpler alternatives where ISR is overkill. Use when the user asks to evaluate ISR, check if ISR is necessary, simplify a Next.js caching strategy, or wants to know "do I actually need ISR?". Activate for partial matches like "should I be using ISR?", "ISR or SSG?", "is revalidate worth it?", or "my Next.js caching is confusing".
4vercel-to-cloudflare-migrator
Analyze a Next.js project deployed to Vercel, estimate monthly savings from moving to Cloudflare Workers, and scaffold a migration. Use when the user asks to move from Vercel to Cloudflare, check Cloudflare savings, estimate Vercel bill on Cloudflare, or migrate Next.js off Vercel. Activate for partial matches like "how much would we save on Cloudflare?" or "get me off Vercel".
1