vulnerability-report
SKILL.md
Vulnerability Report Skill
When generating vulnerability reports, scan all project dependencies for known CVEs, categorize findings by severity, and produce three separate reports — one for each severity tier. Each report is a standalone document with full context, remediation steps, and priority guidance.
IMPORTANT: Always save THREE markdown files to the project-decisions/ directory:
YYYY-MM-DD-vulnerabilities-high.md— Critical and High severity (CVSS ≥ 7.0)YYYY-MM-DD-vulnerabilities-medium.md— Medium severity (CVSS 4.0–6.9)YYYY-MM-DD-vulnerabilities-low.md— Low and Informational (CVSS < 4.0)
0. Output Setup
mkdir -p project-decisions
# Files will be saved as:
# project-decisions/YYYY-MM-DD-vulnerabilities-high.md
# project-decisions/YYYY-MM-DD-vulnerabilities-medium.md
# project-decisions/YYYY-MM-DD-vulnerabilities-low.md
1. Dependency Discovery
Detect Package Ecosystem
# Detect all package managers in use
echo "=== Package Ecosystems Detected ==="
# Node.js / JavaScript / TypeScript
ls package.json package-lock.json yarn.lock pnpm-lock.yaml bun.lockb 2>/dev/null && echo "→ Node.js detected"
# Python
ls requirements.txt Pipfile pyproject.toml poetry.lock setup.py setup.cfg 2>/dev/null && echo "→ Python detected"
# Go
ls go.mod go.sum 2>/dev/null && echo "→ Go detected"
# Ruby
ls Gemfile Gemfile.lock 2>/dev/null && echo "→ Ruby detected"
# PHP
ls composer.json composer.lock 2>/dev/null && echo "→ PHP detected"
# Rust
ls Cargo.toml Cargo.lock 2>/dev/null && echo "→ Rust detected"
# Java
ls pom.xml build.gradle build.gradle.kts 2>/dev/null && echo "→ Java detected"
# .NET
ls *.csproj *.sln packages.config 2>/dev/null && echo "→ .NET detected"
# Docker (base image vulnerabilities)
ls Dockerfile Dockerfile.* docker-compose.yml 2>/dev/null && echo "→ Docker detected"
Inventory Dependencies
# Node.js — count direct and transitive
echo "=== Node.js Dependencies ==="
echo "Direct dependencies: $(cat package.json 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get('dependencies',{})))" 2>/dev/null || echo "N/A")"
echo "Dev dependencies: $(cat package.json 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get('devDependencies',{})))" 2>/dev/null || echo "N/A")"
echo "Total installed: $(ls node_modules/ 2>/dev/null | wc -l || echo "N/A")"
# Python
echo "=== Python Dependencies ==="
pip list --format=columns 2>/dev/null | wc -l || echo "N/A"
cat requirements.txt 2>/dev/null | grep -v "^#\|^$" | wc -l || echo "N/A"
# Go
echo "=== Go Dependencies ==="
cat go.sum 2>/dev/null | awk '{print $1}' | sort -u | wc -l || echo "N/A"
# Ruby
echo "=== Ruby Dependencies ==="
cat Gemfile.lock 2>/dev/null | grep " [a-z]" | wc -l || echo "N/A"
# PHP
echo "=== PHP Dependencies ==="
cat composer.lock 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get('packages',[])))" 2>/dev/null || echo "N/A"
2. Vulnerability Scanning
Node.js / npm
# Full npm audit with JSON output
npm audit --json 2>/dev/null > /tmp/npm-audit-output.json
# Parse audit results
cat /tmp/npm-audit-output.json | python3 -c "
import sys, json
try:
data = json.load(sys.stdin)
# npm v7+ format
if 'vulnerabilities' in data:
vulns = data['vulnerabilities']
for name, info in sorted(vulns.items(), key=lambda x: {'critical':0,'high':1,'moderate':2,'low':3,'info':4}.get(x[1].get('severity','info'), 5)):
severity = info.get('severity', 'unknown')
via = info.get('via', [])
fix = info.get('fixAvailable', False)
range_affected = info.get('range', 'unknown')
# Get CVE details from via
cves = []
if isinstance(via, list):
for v in via:
if isinstance(v, dict):
cves.append({
'title': v.get('title', 'N/A'),
'url': v.get('url', ''),
'severity': v.get('severity', severity),
'cwe': v.get('cwe', []),
'cvss': v.get('cvss', {}).get('score', 'N/A'),
'range': v.get('range', range_affected)
})
print(f'PACKAGE: {name}')
print(f' Severity: {severity.upper()}')
print(f' Affected: {range_affected}')
print(f' Fix Available: {fix}')
for cve in cves:
print(f' CVE Title: {cve[\"title\"]}')
print(f' CVSS Score: {cve[\"cvss\"]}')
print(f' URL: {cve[\"url\"]}')
print(f' CWE: {cve[\"cwe\"]}')
print()
# Summary
metadata = data.get('metadata', {}).get('vulnerabilities', {})
print('=== SUMMARY ===')
print(f'Critical: {metadata.get(\"critical\", 0)}')
print(f'High: {metadata.get(\"high\", 0)}')
print(f'Moderate: {metadata.get(\"moderate\", 0)}')
print(f'Low: {metadata.get(\"low\", 0)}')
print(f'Info: {metadata.get(\"info\", 0)}')
print(f'Total: {metadata.get(\"total\", 0)}')
except Exception as e:
print(f'Error parsing: {e}', file=sys.stderr)
" 2>/dev/null
# Also check with npm audit fix --dry-run to see what's auto-fixable
npm audit fix --dry-run 2>/dev/null | tail -20
Node.js / yarn
# Yarn audit
yarn audit --json 2>/dev/null | head -100
Node.js / pnpm
# pnpm audit
pnpm audit --json 2>/dev/null | head -100
Python / pip
# pip-audit (preferred)
pip install pip-audit --break-system-packages 2>/dev/null
pip-audit --format=json 2>/dev/null > /tmp/pip-audit-output.json
cat /tmp/pip-audit-output.json | python3 -c "
import sys, json
try:
data = json.load(sys.stdin)
for vuln in data:
name = vuln.get('name', 'unknown')
version = vuln.get('version', 'unknown')
vulns = vuln.get('vulns', [])
for v in vulns:
print(f'PACKAGE: {name}=={version}')
print(f' ID: {v.get(\"id\", \"N/A\")}')
print(f' Fix Versions: {v.get(\"fix_versions\", [])}')
print(f' Description: {v.get(\"description\", \"N/A\")[:200]}')
print()
except Exception as e:
print(f'Error: {e}', file=sys.stderr)
" 2>/dev/null
# Safety check (alternative)
pip install safety --break-system-packages 2>/dev/null
safety check --json 2>/dev/null | head -100
Go
# govulncheck
go install golang.org/x/vuln/cmd/govulncheck@latest 2>/dev/null
govulncheck ./... 2>/dev/null
Ruby
# bundler-audit
gem install bundler-audit 2>/dev/null
bundle-audit check --update 2>/dev/null
PHP
# Composer audit
composer audit --format=json 2>/dev/null | head -100
Docker Base Images
# Check Dockerfile base images
echo "=== Docker Base Images ==="
grep "^FROM" Dockerfile Dockerfile.* 2>/dev/null
# Check if base images are pinned
grep "^FROM" Dockerfile 2>/dev/null | while read line; do
image=$(echo "$line" | awk '{print $2}')
echo "$image" | grep -q ":" || echo "⚠️ UNPINNED: $image (using :latest implicitly)"
echo "$image" | grep -q ":latest" && echo "⚠️ UNPINNED: $image (using :latest explicitly)"
echo "$image" | grep -qE ":[0-9]" && echo "✅ PINNED: $image"
echo "$image" | grep -qE "@sha256:" && echo "✅ DIGEST PINNED: $image"
done
Lockfile Integrity
# Check lockfiles exist and are committed
echo "=== Lockfile Status ==="
for lockfile in package-lock.json yarn.lock pnpm-lock.yaml Pipfile.lock poetry.lock Gemfile.lock composer.lock Cargo.lock go.sum; do
if [ -f "$lockfile" ]; then
if git ls-files --error-unmatch "$lockfile" >/dev/null 2>&1; then
echo "✅ $lockfile — committed"
else
echo "⚠️ $lockfile — exists but NOT committed to git"
fi
fi
done
# Check for unpinned versions in package.json
echo ""
echo "=== Unpinned Versions ==="
cat package.json 2>/dev/null | python3 -c "
import sys, json
data = json.load(sys.stdin)
for section in ['dependencies', 'devDependencies']:
deps = data.get(section, {})
for name, version in deps.items():
if version.startswith('^') or version.startswith('~') or version == '*' or version == 'latest':
print(f' {section}/{name}: {version}')
" 2>/dev/null
3. Vulnerability Classification
Severity Mapping
Map each finding to a consistent severity:
| Source | Critical | High | Medium | Low |
|---|---|---|---|---|
| npm audit | critical | high | moderate | low |
| pip-audit/safety | CVSS ≥ 9.0 | CVSS 7.0-8.9 | CVSS 4.0-6.9 | CVSS < 4.0 |
| bundler-audit | critical | high | medium | low |
| govulncheck | Map from CVSS | Map from CVSS | Map from CVSS | Map from CVSS |
| Composer | critical | high | medium | low |
| CVSS v3.1 | 9.0-10.0 | 7.0-8.9 | 4.0-6.9 | 0.1-3.9 |
Enrichment Per Vulnerability
For each vulnerability found, gather:
- Package name and installed version
- Vulnerability ID (CVE, GHSA, OSV)
- CVSS score and vector
- CWE classification
- Severity (Critical/High/Medium/Low)
- Description of the vulnerability
- Affected version range
- Fixed version (if available)
- Is it a direct or transitive dependency?
- Is the vulnerable code reachable from our code?
- Exploit availability (PoC exists? actively exploited?)
- Fix available? (auto-fixable with npm audit fix?)
- Remediation steps
Reachability Analysis
# Check if vulnerable package is directly imported (higher risk)
# vs only a transitive dependency (lower risk)
for pkg in [list-of-vulnerable-packages]; do
echo "=== $pkg ==="
# Direct dependency?
cat package.json 2>/dev/null | grep "\"$pkg\"" && echo " → DIRECT dependency"
# Imported in source code?
grep -rn "import.*$pkg\|require.*$pkg\|from '$pkg'\|from \"$pkg\"" --include="*.ts" --include="*.js" --include="*.py" src/ app/ 2>/dev/null && echo " → DIRECTLY USED in source code"
# Only transitive?
npm ls "$pkg" 2>/dev/null | head -5
done
4. Report Generation
Generate THREE separate reports, one for each severity tier:
Report 1: Critical & High Vulnerabilities
File: project-decisions/YYYY-MM-DD-vulnerabilities-high.md
Audience: Security team, engineering leads, management — requires immediate action
# 🔴 Vulnerability Report: Critical & High Severity
**Project:** [Project Name]
**Scan Date:** YYYY-MM-DD
**Scanned By:** [Name / Automated]
**Ecosystems Scanned:** [npm, pip, Go, Ruby, PHP, Docker]
**Action Required:** 🔴 IMMEDIATE — Fix within 48 hours
---
## Executive Summary
| Metric | Value |
|--------|-------|
| **Critical vulnerabilities** | X |
| **High vulnerabilities** | X |
| **Total in this report** | X |
| **Auto-fixable** | X (Y%) |
| **Requires manual fix** | X (Y%) |
| **No fix available** | X (Y%) |
| **Direct dependencies affected** | X |
| **Transitive dependencies affected** | X |
### Risk Assessment
**Overall Risk: [🔴 Critical / 🟠 High]**
[2-3 sentences: what's the worst case if these aren't fixed?
Are any actively exploited? Is sensitive data at risk?]
---
## Quick Fix Commands
Run these immediately to fix auto-fixable vulnerabilities:
```bash
# Node.js — auto-fix what's possible
npm audit fix
# If breaking changes are acceptable
npm audit fix --force
# Python — upgrade to fixed versions
pip install --upgrade [package1] [package2] --break-system-packages
# Ruby
bundle update [gem1] [gem2]
# PHP
composer update [package1] [package2]
```
**After running fixes, re-scan:**
```bash
npm audit
pip-audit
```
---
## Detailed Findings
### VULN-001: [Package Name] — [Vulnerability Title]
| Field | Value |
|-------|-------|
| **Package** | `[package-name]` |
| **Installed Version** | `X.Y.Z` |
| **Severity** | 🔴 Critical |
| **CVSS Score** | X.X |
| **CVSS Vector** | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| **CVE** | [CVE-YYYY-XXXXX](https://nvd.nist.gov/vuln/detail/CVE-YYYY-XXXXX) |
| **CWE** | [CWE-XXX](https://cwe.mitre.org/data/definitions/XXX.html) — [Name] |
| **GHSA** | [GHSA-xxxx-xxxx-xxxx](https://github.com/advisories/GHSA-xxxx-xxxx-xxxx) |
| **Dependency Type** | Direct / Transitive |
| **Reachable** | Yes — imported in `src/services/auth.ts` / No — transitive only |
| **Exploit Available** | Yes — PoC published / No known exploit |
| **Actively Exploited** | Yes — in the wild / No |
| **Affected Versions** | `>= X.Y.Z, < A.B.C` |
| **Fixed Version** | `A.B.C` |
| **Fix Available** | ✅ Yes — upgrade to `A.B.C` / ❌ No fix yet |
| **Auto-Fixable** | ✅ `npm audit fix` / ❌ Manual intervention required |
**Description:**
[What the vulnerability allows an attacker to do.
How it could be exploited in the context of THIS project.]
**Impact on This Project:**
[Specific to YOUR codebase — is the vulnerable function actually called?
Is the attack vector reachable? What data is at risk?]
**Dependency Chain:**
your-project └── [direct-dependency]@X.Y.Z └── [vulnerable-package]@A.B.C ← VULNERABLE
Weekly Installs
4
Repository
aakash-dhar/cla…e-skillsFirst Seen
6 days ago
Security Audits
Installed on
opencode4
gemini-cli4
antigravity4
claude-code4
github-copilot4
codex4