/dependency-audit Workflow
Role
This skill is a pipeline coordinator. It orchestrates a sequential supply chain security workflow by delegating scanner invocation and synthesis to appropriate tools. It does NOT perform LLM-based CVE lookup — it coordinates real CLI scanners that use live vulnerability databases, then synthesizes their output. The LLM's training data has a knowledge cutoff and cannot reliably detect post-cutoff CVEs.
Inputs
- Package manifest path or scope: $ARGUMENTS (optional — auto-detected if omitted)
- Supported:
package.json,requirements.txt,pyproject.toml,Pipfile,go.mod,Cargo.toml,pom.xml,Gemfile
Step 0 — Pre-flight: detect manifest and scanner availability
Tool: Bash (direct — coordinator does this), Glob
Detect manifest type by searching for known manifest files:
Tool: Glob
Search patterns (in order):
**/package.json→ ecosystem: Node.js, scanner:npm audit**/requirements.txtor**/pyproject.tomlor**/Pipfile→ ecosystem: Python, scanners:pip-auditorsafety**/go.mod→ ecosystem: Go, scanner:govulncheck**/Cargo.toml→ ecosystem: Rust, scanner:cargo audit**/pom.xml→ ecosystem: Java, scanner:mvn dependency:analyze**/Gemfile→ ecosystem: Ruby, scanner:bundle audit
If $ARGUMENTS specifies a manifest path, use that directly. Otherwise, use the first manifest found.
Check scanner availability via which:
Tool: Bash
TIMESTAMP=$(date -u +"%Y%m%dT%H%M%SZ")
echo "Run timestamp: $TIMESTAMP"
# Detect ecosystem and check scanners
ECOSYSTEM=""
MANIFEST=""
SCANNER=""
SCANNER_CMD=""
# Check for manifests and their scanners
if [ -f "package.json" ] || [ -f "$(find . -name 'package.json' -not -path '*/node_modules/*' -maxdepth 3 | head -1)" ]; then
MANIFEST=$(find . -name 'package.json' -not -path '*/node_modules/*' -maxdepth 3 | head -1)
ECOSYSTEM="Node.js"
if which npm >/dev/null 2>&1; then SCANNER="npm"; SCANNER_CMD="npm audit --json"; fi
fi
if [ -z "$ECOSYSTEM" ] && ([ -f "requirements.txt" ] || [ -f "pyproject.toml" ] || [ -f "Pipfile" ]); then
MANIFEST=$(ls requirements.txt pyproject.toml Pipfile 2>/dev/null | head -1)
ECOSYSTEM="Python"
if which pip-audit >/dev/null 2>&1; then SCANNER="pip-audit"; SCANNER_CMD="pip-audit --format json";
elif which safety >/dev/null 2>&1; then SCANNER="safety"; SCANNER_CMD="safety check --json"; fi
fi
if [ -z "$ECOSYSTEM" ] && [ -f "go.mod" ]; then
MANIFEST="go.mod"
ECOSYSTEM="Go"
if which govulncheck >/dev/null 2>&1; then SCANNER="govulncheck"; SCANNER_CMD="govulncheck ./..."; fi
fi
if [ -z "$ECOSYSTEM" ] && [ -f "Cargo.toml" ]; then
MANIFEST="Cargo.toml"
ECOSYSTEM="Rust"
if which cargo >/dev/null 2>&1; then SCANNER="cargo audit"; SCANNER_CMD="cargo audit --json"; fi
fi
if [ -z "$ECOSYSTEM" ] && [ -f "pom.xml" ]; then
MANIFEST="pom.xml"
ECOSYSTEM="Java"
if which mvn >/dev/null 2>&1; then SCANNER="mvn"; SCANNER_CMD="mvn dependency:analyze -q"; fi
fi
if [ -z "$ECOSYSTEM" ] && [ -f "Gemfile" ]; then
MANIFEST="Gemfile"
ECOSYSTEM="Ruby"
if which bundle >/dev/null 2>&1 && bundle exec gem list 2>/dev/null | grep -q bundler-audit; then
SCANNER="bundle-audit"; SCANNER_CMD="bundle audit check --update";
fi
fi
echo "ECOSYSTEM=$ECOSYSTEM"
echo "MANIFEST=$MANIFEST"
echo "SCANNER=$SCANNER"
echo "SCANNER_CMD=$SCANNER_CMD"
echo "TIMESTAMP=$TIMESTAMP"
Pre-flight outcomes:
- If no manifest found: Stop workflow. Output: "No supported package manifest found. Supported: package.json, requirements.txt, pyproject.toml, Pipfile, go.mod, Cargo.toml, pom.xml, Gemfile"
- If manifest found but no scanner available: Log
SCANNER=""— workflow continues. Steps 1–3 will be skipped for CVE scanning; Steps 4–5 (license + supply chain) still run. Verdict will beINCOMPLETE. - If manifest and scanner found: Full workflow runs.
Step 1 — Read and parse manifest
Tool: Read (direct — coordinator does this)
Read the manifest file identified in Step 0. Extract:
- All direct dependencies (name + version or version constraint)
- All dev/test dependencies (if present and relevant)
- Lock file location (e.g.,
package-lock.json,Pipfile.lock,go.sum,Cargo.lock,Gemfile.lock) for precise version data
If a lock file exists alongside the manifest, note it — the scanner will use it for exact vulnerability matching.
Output summary of dependency count to stdout (e.g., "Found 42 direct dependencies, 87 total including transitive").
Step 2 — Invoke scanner
Tool: Bash (direct — coordinator does this)
If no scanner is available (SCANNER="" from Step 0):
Output:
SCANNER STATUS: INCOMPLETE — no vulnerability scanner available for [ecosystem]
To enable full vulnerability scanning, install the appropriate scanner:
Node.js: npm (included with Node.js)
Python: pip install pip-audit (or: pip install safety)
Go: go install golang.org/x/vuln/cmd/govulncheck@latest
Rust: cargo install cargo-audit
Java: Apache Maven required (https://maven.apache.org)
Ruby: gem install bundler-audit
Continuing with license compliance and supply chain risk assessment only.
Steps 4–5 will still run. CVE vulnerability data will NOT be reported.
Set SCANNER_OUTPUT="(no scanner available)" and skip to Step 3 synthesis with empty CVE data.
If scanner is available:
Run the scanner. Note: non-zero exit codes from vulnerability scanners indicate findings, not errors.
# Run scanner — non-zero exit = findings found, not a command error
SCANNER_OUTPUT_FILE="./plans/dependency-audit-${TIMESTAMP}.scanner-raw.json"
case "$SCANNER" in
npm)
npm audit --json 2>/dev/null > "$SCANNER_OUTPUT_FILE" || true
;;
pip-audit)
pip-audit --format json 2>/dev/null > "$SCANNER_OUTPUT_FILE" || true
;;
safety)
safety check --json 2>/dev/null > "$SCANNER_OUTPUT_FILE" || true
;;
govulncheck)
govulncheck -json ./... 2>/dev/null > "$SCANNER_OUTPUT_FILE" || true
;;
"cargo audit")
cargo audit --json 2>/dev/null > "$SCANNER_OUTPUT_FILE" || true
;;
mvn)
mvn dependency:analyze -q 2>&1 > "$SCANNER_OUTPUT_FILE" || true
;;
bundle-audit)
bundle audit check --update 2>&1 > "$SCANNER_OUTPUT_FILE" || true
;;
esac
echo "Scanner output saved to: $SCANNER_OUTPUT_FILE"
cat "$SCANNER_OUTPUT_FILE"
Step 3 — LLM synthesis of scanner output
Tool: Task, subagent_type=general-purpose, model=claude-sonnet-4-6
Prompt: "You are a security analyst synthesizing vulnerability scanner output for a dependency audit report.
Read the scanner output file at ./plans/dependency-audit-[TIMESTAMP].scanner-raw.json.
Also read the manifest file at [MANIFEST].
Your task:
-
Parse the scanner output and extract all vulnerability findings.
-
For each finding, identify:
- Package name and affected version
- CVE/vulnerability ID (e.g., CVE-2024-XXXXX, GHSA-XXXXX)
- Severity (Critical / High / Medium / Low — use scanner-reported severity)
- Description (one sentence)
- Whether a fixed version is available
- Whether the vulnerable package is a direct dependency or transitive
-
Categorize findings by severity:
- Critical: RCE, authentication bypass, data exfiltration — must fix before shipping
- High: Significant security impact — should fix soon
- Medium: Limited impact or requires unusual conditions — review and plan fix
- Low: Minimal impact — track but lower priority
-
Note any findings where the scanner could not complete (e.g., network errors, auth required).
Output: Write your synthesis to ./plans/dependency-audit-[TIMESTAMP].cve-synthesis.md with:
## CVE Findings
**Scanner:** [scanner name and version if available]
**Ecosystem:** [ecosystem]
**Scan date:** [timestamp]
**Total vulnerabilities:** [count by severity: X Critical, X High, X Medium, X Low]
### Critical Findings
[table: Package | CVE ID | Description | Fixed Version | Dire