Install command
Provided
Scans for security vulnerabilities when package.json or requirements.txt files are modified.
Open the source and read safety notes before installing.
Source-backed facts for citing this resource, derived directly from the registry — also available as plain text for AI assistants.
Decision playbook
Signals are present but mixed. Use the checklist below to confirm the source and operational safety for your environment.
0
78
—
No baseline selected
No major trust-signal divergence detected in the current selection.
Confirm ownership and provenance before trusting install instructions.
Source link availableRequired
Open the canonical repository and verify ownership.
Source provenance statusRequired
Marked as source-backed.
Metadata reviewed
Registry metadata indicates a reviewed listing.
Validate risk disclosures before installation or API wiring.
Safety notes presentRequired
Review the listed safety guidance before running commands.
Privacy notes presentRequired
Review data handling notes before connecting accounts or secrets.
Trust level risk gateRequired
Trust level does not block evaluation.
Check package metadata and artifact integrity signals.
Install payload available
Install or copy payload is available for review.
Package verification flag
No package verification flag provided.
Checksum metadata
No checksum provided for downloaded artifact.
Use compare context to validate trade-offs before adoption.
Compare tray has multiple entries
Add at least one more entry to compare trust differences.
Baseline comparison available
No baseline peer selected yet.
Diverging trust signals identified
No major trust-signal divergence found.
Setup at a glance
Copy-ready — paste the snippet to get started.
Install command
Provided
Config snippet
Provided
Copy snippet
Provided
Prerequisites
None
Platforms
1 listed
Difficulty
0/100
Adoption plan
Current risk score 16/100. Use staged verification before broader rollout.
Validate source and review signals before any execution.
Confirm source provenanceRequired
Source URL/provenance metadata is present.
Confirm metadata review state
Listing has review metadata.
Verify install payload
Install/config payload exists and can be inspected.
Confirm safety, privacy, and package integrity signals.
Review safety notesRequired
Safety notes are present.
Review privacy notesRequired
Privacy notes are present.
Verify package integrity metadata
No package verification/checksum metadata.
Adopt in controlled steps based on the selected plan.
Run in isolated sandbox firstRequired
Use a constrained sandbox and observe behavior across multiple tasks.
Roll out graduallyRequired
Roll out to a small cohort before wider usage.
Set monitoring and fallback
Define rollback path and monitor errors after adoption.
Evidence readiness
Required evidence gates are covered (5/6 signals complete).
Source repository/provenance is listed.
Required in this preset
Review metadata is present.
Required in this preset
Safety notes are present.
Required in this preset
Privacy notes are present.
Optional in this preset
Package integrity metadata is missing.
Optional in this preset
Install payload is available.
Required in this preset
Required evidence gates are covered for this preset.
Decision timeline
5/6 steps complete with no blocking gaps for this preset.
triage
Source/provenance metadata is available.
triage
Review metadata is available.
verify
Safety notes are available.
verify
Privacy notes are available.
verify
Package integrity metadata is missing.
rollout
Install payload is available.
No required blockers for this timeline preset.
Safety & privacy surface
1 safety and 1 privacy notes across 2 risk areas. Review closely: credentials & tokens, permissions & scopes.
#!/usr/bin/env bash
# Read the tool input from stdin
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
# Check if this is a dependency or package file
if [[ "$FILE_PATH" == *package.json ]] || [[ "$FILE_PATH" == *requirements.txt ]] || [[ "$FILE_PATH" == *Pipfile ]] || [[ "$FILE_PATH" == *Gemfile ]] || [[ "$FILE_PATH" == *go.mod ]] || [[ "$FILE_PATH" == *yarn.lock ]] || [[ "$FILE_PATH" == *package-lock.json ]] || [[ "$FILE_PATH" == *composer.json ]]; then
echo "🔒 Package Vulnerability Scanner for: $(basename "$FILE_PATH")" >&2
# Initialize security counters
TOTAL_VULNERABILITIES=0
HIGH_SEVERITY=0
MEDIUM_SEVERITY=0
LOW_SEVERITY=0
CRITICAL_SEVERITY=0
FIXABLE_VULNERABILITIES=0
ERRORS=0
WARNINGS=0
# Function to report security findings
report_security() {
local level="$1"
local message="$2"
case "$level" in
"CRITICAL")
echo "🚨 CRITICAL: $message" >&2
ERRORS=$((ERRORS + 1))
;;
"ERROR")
echo "❌ ERROR: $message" >&2
ERRORS=$((ERRORS + 1))
;;
"WARNING")
echo "⚠️ WARNING: $message" >&2
WARNINGS=$((WARNINGS + 1))
;;
"INFO")
echo "ℹ️ INFO: $message" >&2
;;
"PASS")
echo "✅ PASS: $message" >&2
;;
esac
}
# Detect package manager and language
PACKAGE_MANAGER=""
LANGUAGE=""
SCAN_COMMAND=""
FILE_NAME=$(basename "$FILE_PATH")
FILE_DIR=$(dirname "$FILE_PATH")
echo "📊 Analyzing package file: $FILE_NAME" >&2
# Determine package manager and language
case "$FILE_NAME" in
"package.json")
PACKAGE_MANAGER="npm"
LANGUAGE="Node.js"
;;
"yarn.lock")
PACKAGE_MANAGER="yarn"
LANGUAGE="Node.js"
;;
"package-lock.json")
PACKAGE_MANAGER="npm"
LANGUAGE="Node.js"
;;
"requirements.txt")
PACKAGE_MANAGER="pip"
LANGUAGE="Python"
;;
"Pipfile")
PACKAGE_MANAGER="pipenv"
LANGUAGE="Python"
;;
"Gemfile")
PACKAGE_MANAGER="bundler"
LANGUAGE="Ruby"
;;
"go.mod")
PACKAGE_MANAGER="go"
LANGUAGE="Go"
;;
"composer.json")
PACKAGE_MANAGER="composer"
LANGUAGE="PHP"
;;
*)
report_security "WARNING" "Unknown package file type: $FILE_NAME"
exit 0
;;
esac
echo " 🔧 Package Manager: $PACKAGE_MANAGER" >&2
echo " 📝 Language: $LANGUAGE" >&2
# 1. Node.js Security Scanning
if [[ "$PACKAGE_MANAGER" == "npm" ]] || [[ "$PACKAGE_MANAGER" == "yarn" ]]; then
echo "📦 Node.js security scanning..." >&2
# Check if npm is available
if command -v npm &> /dev/null; then
echo " 🔍 Running npm audit..." >&2
NPM_AUDIT_OUTPUT="/tmp/npm_audit_$$"
# Run npm audit with JSON output
if npm audit --json > "$NPM_AUDIT_OUTPUT" 2>&1; then
# Parse npm audit results
if command -v jq &> /dev/null; then
AUDIT_SUMMARY=$(jq -r '.metadata.vulnerabilities' "$NPM_AUDIT_OUTPUT" 2>/dev/null || echo '{}')
if [ "$AUDIT_SUMMARY" != "{}" ] && [ "$AUDIT_SUMMARY" != "null" ]; then
# Extract vulnerability counts
CRITICAL_COUNT=$(echo "$AUDIT_SUMMARY" | jq -r '.critical // 0')
HIGH_COUNT=$(echo "$AUDIT_SUMMARY" | jq -r '.high // 0')
MODERATE_COUNT=$(echo "$AUDIT_SUMMARY" | jq -r '.moderate // 0')
LOW_COUNT=$(echo "$AUDIT_SUMMARY" | jq -r '.low // 0')
TOTAL_VULNERABILITIES=$((CRITICAL_COUNT + HIGH_COUNT + MODERATE_COUNT + LOW_COUNT))
CRITICAL_SEVERITY=$CRITICAL_COUNT
HIGH_SEVERITY=$HIGH_COUNT
MEDIUM_SEVERITY=$MODERATE_COUNT
LOW_SEVERITY=$LOW_COUNT
echo " 📊 Vulnerability summary:" >&2
echo " 🚨 Critical: $CRITICAL_COUNT" >&2
echo " 🔴 High: $HIGH_COUNT" >&2
echo " 🟡 Moderate: $MODERATE_COUNT" >&2
echo " 🟢 Low: $LOW_COUNT" >&2
if [ "$CRITICAL_COUNT" -gt 0 ]; then
report_security "CRITICAL" "$CRITICAL_COUNT critical vulnerabilities found"
fi
if [ "$HIGH_COUNT" -gt 0 ]; then
report_security "ERROR" "$HIGH_COUNT high severity vulnerabilities found"
fi
if [ "$MODERATE_COUNT" -gt 0 ]; then
report_security "WARNING" "$MODERATE_COUNT moderate severity vulnerabilities found"
fi
# Show top vulnerabilities
TOP_VULNS=$(jq -r '.vulnerabilities | to_entries | .[0:3] | .[] | " • " + .key + " (" + .value.severity + ")"' "$NPM_AUDIT_OUTPUT" 2>/dev/null || echo "")
if [ -n "$TOP_VULNS" ]; then
echo " 🎯 Top vulnerabilities:" >&2
echo "$TOP_VULNS" >&2
fi
else
report_security "PASS" "No vulnerabilities found in npm dependencies"
fi
else
report_security "WARNING" "jq not available - limited vulnerability parsing"
fi
else
# npm audit failed, check if it's due to vulnerabilities
AUDIT_EXIT_CODE=$?
if [ $AUDIT_EXIT_CODE -eq 1 ]; then
# Exit code 1 means vulnerabilities found
report_security "ERROR" "npm audit found vulnerabilities (exit code 1)"
# Try to extract basic info
VULN_COUNT=$(grep -o 'vulnerabilities' "$NPM_AUDIT_OUTPUT" 2>/dev/null | wc -l || echo "0")
if [ "$VULN_COUNT" -gt 0 ]; then
echo " ⚠️ Estimated vulnerabilities: $VULN_COUNT" >&2
fi
else
report_security "ERROR" "npm audit failed with exit code $AUDIT_EXIT_CODE"
fi
fi
rm -f "$NPM_AUDIT_OUTPUT"
# Check for yarn if available
if [[ "$PACKAGE_MANAGER" == "yarn" ]] && command -v yarn &> /dev/null; then
echo " 🧶 Running yarn audit..." >&2
YARN_AUDIT_OUTPUT="/tmp/yarn_audit_$$"
if yarn audit --json > "$YARN_AUDIT_OUTPUT" 2>&1; then
report_security "PASS" "Yarn audit completed successfully"
else
report_security "WARNING" "Yarn audit found issues or failed"
fi
rm -f "$YARN_AUDIT_OUTPUT"
fi
else
report_security "WARNING" "npm not available - cannot perform Node.js security scan"
fi
fi
# 2. Python Security Scanning
if [[ "$PACKAGE_MANAGER" == "pip" ]] || [[ "$PACKAGE_MANAGER" == "pipenv" ]]; then
echo "🐍 Python security scanning..." >&2
# Check for safety tool
if command -v safety &> /dev/null; then
echo " 🔍 Running safety check..." >&2
SAFETY_OUTPUT="/tmp/safety_output_$$"
if safety check --json > "$SAFETY_OUTPUT" 2>&1; then
report_security "PASS" "Safety check completed - no vulnerabilities found"
else
# Safety found vulnerabilities
SAFETY_EXIT_CODE=$?
if [ $SAFETY_EXIT_CODE -eq 64 ]; then
# Exit code 64 means vulnerabilities found
report_security "ERROR" "Safety found vulnerabilities in Python dependencies"
# Try to parse vulnerabilities
if command -v jq &> /dev/null && [ -f "$SAFETY_OUTPUT" ]; then
VULN_COUNT=$(jq length "$SAFETY_OUTPUT" 2>/dev/null || echo "0")
if [ "$VULN_COUNT" -gt 0 ]; then
echo " 📊 Found $VULN_COUNT Python vulnerabilities" >&2
TOTAL_VULNERABILITIES=$((TOTAL_VULNERABILITIES + VULN_COUNT))
# Show first few vulnerabilities
jq -r '.[0:3] | .[] | " • " + .package + " (" + .vulnerability_id + ")"' "$SAFETY_OUTPUT" 2>/dev/null | while read line; do
echo "$line" >&2
done
fi
fi
else
report_security "WARNING" "Safety check failed with exit code $SAFETY_EXIT_CODE"
fi
fi
rm -f "$SAFETY_OUTPUT"
elif command -v pip &> /dev/null; then
echo " 🔍 Safety not available, using pip-audit if available..." >&2
if command -v pip-audit &> /dev/null; then
PIP_AUDIT_OUTPUT="/tmp/pip_audit_$$"
if pip-audit --format=json > "$PIP_AUDIT_OUTPUT" 2>&1; then
report_security "PASS" "pip-audit completed - no vulnerabilities found"
else
report_security "ERROR" "pip-audit found vulnerabilities in Python dependencies"
fi
rm -f "$PIP_AUDIT_OUTPUT"
else
report_security "WARNING" "No Python security tools available (safety, pip-audit)"
fi
else
report_security "WARNING" "Python/pip not available - cannot perform Python security scan"
fi
fi
# 3. Ruby Security Scanning
if [[ "$PACKAGE_MANAGER" == "bundler" ]]; then
echo "💎 Ruby security scanning..." >&2
if command -v bundler-audit &> /dev/null; then
echo " 🔍 Running bundler-audit..." >&2
BUNDLER_AUDIT_OUTPUT="/tmp/bundler_audit_$$"
if bundler-audit check > "$BUNDLER_AUDIT_OUTPUT" 2>&1; then
report_security "PASS" "bundler-audit completed - no vulnerabilities found"
else
report_security "ERROR" "bundler-audit found vulnerabilities in Ruby dependencies"
# Count vulnerabilities
RUBY_VULNS=$(grep -c 'Vulnerability found' "$BUNDLER_AUDIT_OUTPUT" 2>/dev/null || echo "0")
if [ "$RUBY_VULNS" -gt 0 ]; then
echo " 📊 Found $RUBY_VULNS Ruby vulnerabilities" >&2
TOTAL_VULNERABILITIES=$((TOTAL_VULNERABILITIES + RUBY_VULNS))
fi
fi
rm -f "$BUNDLER_AUDIT_OUTPUT"
else
report_security "WARNING" "bundler-audit not available - install with 'gem install bundler-audit'"
fi
fi
# 4. Go Security Scanning
if [[ "$PACKAGE_MANAGER" == "go" ]]; then
echo "🐹 Go security scanning..." >&2
if command -v govulncheck &> /dev/null; then
echo " 🔍 Running govulncheck..." >&2
GOVULN_OUTPUT="/tmp/govuln_output_$$"
if govulncheck ./... > "$GOVULN_OUTPUT" 2>&1; then
report_security "PASS" "govulncheck completed - no vulnerabilities found"
else
report_security "ERROR" "govulncheck found vulnerabilities in Go dependencies"
# Count vulnerabilities
GO_VULNS=$(grep -c 'Vulnerability' "$GOVULN_OUTPUT" 2>/dev/null || echo "0")
if [ "$GO_VULNS" -gt 0 ]; then
echo " 📊 Found $GO_VULNS Go vulnerabilities" >&2
TOTAL_VULNERABILITIES=$((TOTAL_VULNERABILITIES + GO_VULNS))
fi
fi
rm -f "$GOVULN_OUTPUT"
else
report_security "WARNING" "govulncheck not available - install with 'go install golang.org/x/vuln/cmd/govulncheck@latest'"
fi
fi
# 5. PHP Security Scanning
if [[ "$PACKAGE_MANAGER" == "composer" ]]; then
echo "🐘 PHP security scanning..." >&2
if command -v composer &> /dev/null; then
echo " 🔍 Running composer audit..." >&2
COMPOSER_AUDIT_OUTPUT="/tmp/composer_audit_$$"
if composer audit > "$COMPOSER_AUDIT_OUTPUT" 2>&1; then
report_security "PASS" "Composer audit completed - no vulnerabilities found"
else
report_security "ERROR" "Composer audit found vulnerabilities in PHP dependencies"
# Count vulnerabilities
PHP_VULNS=$(grep -c 'vulnerability' "$COMPOSER_AUDIT_OUTPUT" 2>/dev/null || echo "0")
if [ "$PHP_VULNS" -gt 0 ]; then
echo " 📊 Found $PHP_VULNS PHP vulnerabilities" >&2
TOTAL_VULNERABILITIES=$((TOTAL_VULNERABILITIES + PHP_VULNS))
fi
fi
rm -f "$COMPOSER_AUDIT_OUTPUT"
else
report_security "WARNING" "Composer not available - cannot perform PHP security scan"
fi
fi
# 6. License Compliance Check
echo "📋 License compliance checking..." >&2
# Basic license check for Node.js projects
if [[ "$PACKAGE_MANAGER" == "npm" ]] && command -v npx &> /dev/null; then
if npx license-checker --summary >/dev/null 2>&1; then
LICENSE_SUMMARY=$(npx license-checker --summary 2>/dev/null | head -10)
echo " 📄 License summary available" >&2
else
report_security "INFO" "license-checker not available for license compliance"
fi
fi
# 7. Generate Security Report
echo "" >&2
echo "📋 Security Scan Summary:" >&2
echo "=========================" >&2
echo " 📄 File: $FILE_NAME" >&2
echo " 🔧 Package Manager: $PACKAGE_MANAGER" >&2
echo " 📝 Language: $LANGUAGE" >&2
echo " 🔒 Total Vulnerabilities: $TOTAL_VULNERABILITIES" >&2
if [ "$CRITICAL_SEVERITY" -gt 0 ]; then
echo " 🚨 Critical: $CRITICAL_SEVERITY" >&2
fi
if [ "$HIGH_SEVERITY" -gt 0 ]; then
echo " 🔴 High: $HIGH_SEVERITY" >&2
fi
if [ "$MEDIUM_SEVERITY" -gt 0 ]; then
echo " 🟡 Medium: $MEDIUM_SEVERITY" >&2
fi
if [ "$LOW_SEVERITY" -gt 0 ]; then
echo " 🟢 Low: $LOW_SEVERITY" >&2
fi
echo " ⚠️ Warnings: $WARNINGS" >&2
echo " ❌ Errors: $ERRORS" >&2
# Security status assessment
if [ "$CRITICAL_SEVERITY" -gt 0 ]; then
echo " 🚨 Status: CRITICAL - Immediate action required" >&2
elif [ "$HIGH_SEVERITY" -gt 0 ]; then
echo " 🔴 Status: HIGH RISK - Update dependencies soon" >&2
elif [ "$MEDIUM_SEVERITY" -gt 0 ]; then
echo " 🟡 Status: MODERATE RISK - Plan updates" >&2
elif [ "$LOW_SEVERITY" -gt 0 ]; then
echo " 🟢 Status: LOW RISK - Monitor and update when convenient" >&2
elif [ "$TOTAL_VULNERABILITIES" -eq 0 ] && [ "$ERRORS" -eq 0 ]; then
echo " ✅ Status: SECURE - No known vulnerabilities" >&2
else
echo " ⚠️ Status: UNKNOWN - Scan completed with issues" >&2
fi
echo "" >&2
echo "💡 Security Best Practices:" >&2
echo " • Run security scans regularly (weekly/monthly)" >&2
echo " • Keep dependencies up to date" >&2
echo " • Use dependency pinning for critical applications" >&2
echo " • Review security advisories for your dependencies" >&2
echo " • Consider using automated dependency update tools" >&2
echo " • Implement security scanning in CI/CD pipelines" >&2
# Exit with error if critical or high severity vulnerabilities found
if [ "$CRITICAL_SEVERITY" -gt 0 ] || [ "$HIGH_SEVERITY" -gt 0 ]; then
echo "⚠️ Security scan completed with high-priority vulnerabilities" >&2
exit 1
fi
else
# Not a package file, exit silently
exit 0
fi
exit 0{
"hooks": {
"postToolUse": {
"script": "./.claude/hooks/package-vulnerability-scanner.sh",
"matchers": [
"write",
"edit"
]
}
}
}.claude/settings.local.json~/.claude/settings.json.claude/settings.json{
"hooks": {
"postToolUse": {
"script": "./.claude/hooks/package-vulnerability-scanner.sh",
"matchers": ["write", "edit"]
}
}
}
#!/usr/bin/env bash
# Read the tool input from stdin
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
# Check if this is a dependency or package file
if [[ "$FILE_PATH" == *package.json ]] || [[ "$FILE_PATH" == *requirements.txt ]] || [[ "$FILE_PATH" == *Pipfile ]] || [[ "$FILE_PATH" == *Gemfile ]] || [[ "$FILE_PATH" == *go.mod ]] || [[ "$FILE_PATH" == *yarn.lock ]] || [[ "$FILE_PATH" == *package-lock.json ]] || [[ "$FILE_PATH" == *composer.json ]]; then
echo "🔒 Package Vulnerability Scanner for: $(basename "$FILE_PATH")" >&2
# Initialize security counters
TOTAL_VULNERABILITIES=0
HIGH_SEVERITY=0
MEDIUM_SEVERITY=0
LOW_SEVERITY=0
CRITICAL_SEVERITY=0
FIXABLE_VULNERABILITIES=0
ERRORS=0
WARNINGS=0
# Function to report security findings
report_security() {
local level="$1"
local message="$2"
case "$level" in
"CRITICAL")
echo "🚨 CRITICAL: $message" >&2
ERRORS=$((ERRORS + 1))
;;
"ERROR")
echo "❌ ERROR: $message" >&2
ERRORS=$((ERRORS + 1))
;;
"WARNING")
echo "⚠️ WARNING: $message" >&2
WARNINGS=$((WARNINGS + 1))
;;
"INFO")
echo "ℹ️ INFO: $message" >&2
;;
"PASS")
echo "✅ PASS: $message" >&2
;;
esac
}
# Detect package manager and language
PACKAGE_MANAGER=""
LANGUAGE=""
SCAN_COMMAND=""
FILE_NAME=$(basename "$FILE_PATH")
FILE_DIR=$(dirname "$FILE_PATH")
echo "📊 Analyzing package file: $FILE_NAME" >&2
# Determine package manager and language
case "$FILE_NAME" in
"package.json")
PACKAGE_MANAGER="npm"
LANGUAGE="Node.js"
;;
"yarn.lock")
PACKAGE_MANAGER="yarn"
LANGUAGE="Node.js"
;;
"package-lock.json")
PACKAGE_MANAGER="npm"
LANGUAGE="Node.js"
;;
"requirements.txt")
PACKAGE_MANAGER="pip"
LANGUAGE="Python"
;;
"Pipfile")
PACKAGE_MANAGER="pipenv"
LANGUAGE="Python"
;;
"Gemfile")
PACKAGE_MANAGER="bundler"
LANGUAGE="Ruby"
;;
"go.mod")
PACKAGE_MANAGER="go"
LANGUAGE="Go"
;;
"composer.json")
PACKAGE_MANAGER="composer"
LANGUAGE="PHP"
;;
*)
report_security "WARNING" "Unknown package file type: $FILE_NAME"
exit 0
;;
esac
echo " 🔧 Package Manager: $PACKAGE_MANAGER" >&2
echo " 📝 Language: $LANGUAGE" >&2
# 1. Node.js Security Scanning
if [[ "$PACKAGE_MANAGER" == "npm" ]] || [[ "$PACKAGE_MANAGER" == "yarn" ]]; then
echo "📦 Node.js security scanning..." >&2
# Check if npm is available
if command -v npm &> /dev/null; then
echo " 🔍 Running npm audit..." >&2
NPM_AUDIT_OUTPUT="/tmp/npm_audit_$$"
# Run npm audit with JSON output
if npm audit --json > "$NPM_AUDIT_OUTPUT" 2>&1; then
# Parse npm audit results
if command -v jq &> /dev/null; then
AUDIT_SUMMARY=$(jq -r '.metadata.vulnerabilities' "$NPM_AUDIT_OUTPUT" 2>/dev/null || echo '{}')
if [ "$AUDIT_SUMMARY" != "{}" ] && [ "$AUDIT_SUMMARY" != "null" ]; then
# Extract vulnerability counts
CRITICAL_COUNT=$(echo "$AUDIT_SUMMARY" | jq -r '.critical // 0')
HIGH_COUNT=$(echo "$AUDIT_SUMMARY" | jq -r '.high // 0')
MODERATE_COUNT=$(echo "$AUDIT_SUMMARY" | jq -r '.moderate // 0')
LOW_COUNT=$(echo "$AUDIT_SUMMARY" | jq -r '.low // 0')
TOTAL_VULNERABILITIES=$((CRITICAL_COUNT + HIGH_COUNT + MODERATE_COUNT + LOW_COUNT))
CRITICAL_SEVERITY=$CRITICAL_COUNT
HIGH_SEVERITY=$HIGH_COUNT
MEDIUM_SEVERITY=$MODERATE_COUNT
LOW_SEVERITY=$LOW_COUNT
echo " 📊 Vulnerability summary:" >&2
echo " 🚨 Critical: $CRITICAL_COUNT" >&2
echo " 🔴 High: $HIGH_COUNT" >&2
echo " 🟡 Moderate: $MODERATE_COUNT" >&2
echo " 🟢 Low: $LOW_COUNT" >&2
if [ "$CRITICAL_COUNT" -gt 0 ]; then
report_security "CRITICAL" "$CRITICAL_COUNT critical vulnerabilities found"
fi
if [ "$HIGH_COUNT" -gt 0 ]; then
report_security "ERROR" "$HIGH_COUNT high severity vulnerabilities found"
fi
if [ "$MODERATE_COUNT" -gt 0 ]; then
report_security "WARNING" "$MODERATE_COUNT moderate severity vulnerabilities found"
fi
# Show top vulnerabilities
TOP_VULNS=$(jq -r '.vulnerabilities | to_entries | .[0:3] | .[] | " • " + .key + " (" + .value.severity + ")"' "$NPM_AUDIT_OUTPUT" 2>/dev/null || echo "")
if [ -n "$TOP_VULNS" ]; then
echo " 🎯 Top vulnerabilities:" >&2
echo "$TOP_VULNS" >&2
fi
else
report_security "PASS" "No vulnerabilities found in npm dependencies"
fi
else
report_security "WARNING" "jq not available - limited vulnerability parsing"
fi
else
# npm audit failed, check if it's due to vulnerabilities
AUDIT_EXIT_CODE=$?
if [ $AUDIT_EXIT_CODE -eq 1 ]; then
# Exit code 1 means vulnerabilities found
report_security "ERROR" "npm audit found vulnerabilities (exit code 1)"
# Try to extract basic info
VULN_COUNT=$(grep -o 'vulnerabilities' "$NPM_AUDIT_OUTPUT" 2>/dev/null | wc -l || echo "0")
if [ "$VULN_COUNT" -gt 0 ]; then
echo " ⚠️ Estimated vulnerabilities: $VULN_COUNT" >&2
fi
else
report_security "ERROR" "npm audit failed with exit code $AUDIT_EXIT_CODE"
fi
fi
rm -f "$NPM_AUDIT_OUTPUT"
# Check for yarn if available
if [[ "$PACKAGE_MANAGER" == "yarn" ]] && command -v yarn &> /dev/null; then
echo " 🧶 Running yarn audit..." >&2
YARN_AUDIT_OUTPUT="/tmp/yarn_audit_$$"
if yarn audit --json > "$YARN_AUDIT_OUTPUT" 2>&1; then
report_security "PASS" "Yarn audit completed successfully"
else
report_security "WARNING" "Yarn audit found issues or failed"
fi
rm -f "$YARN_AUDIT_OUTPUT"
fi
else
report_security "WARNING" "npm not available - cannot perform Node.js security scan"
fi
fi
# 2. Python Security Scanning
if [[ "$PACKAGE_MANAGER" == "pip" ]] || [[ "$PACKAGE_MANAGER" == "pipenv" ]]; then
echo "🐍 Python security scanning..." >&2
# Check for safety tool
if command -v safety &> /dev/null; then
echo " 🔍 Running safety check..." >&2
SAFETY_OUTPUT="/tmp/safety_output_$$"
if safety check --json > "$SAFETY_OUTPUT" 2>&1; then
report_security "PASS" "Safety check completed - no vulnerabilities found"
else
# Safety found vulnerabilities
SAFETY_EXIT_CODE=$?
if [ $SAFETY_EXIT_CODE -eq 64 ]; then
# Exit code 64 means vulnerabilities found
report_security "ERROR" "Safety found vulnerabilities in Python dependencies"
# Try to parse vulnerabilities
if command -v jq &> /dev/null && [ -f "$SAFETY_OUTPUT" ]; then
VULN_COUNT=$(jq length "$SAFETY_OUTPUT" 2>/dev/null || echo "0")
if [ "$VULN_COUNT" -gt 0 ]; then
echo " 📊 Found $VULN_COUNT Python vulnerabilities" >&2
TOTAL_VULNERABILITIES=$((TOTAL_VULNERABILITIES + VULN_COUNT))
# Show first few vulnerabilities
jq -r '.[0:3] | .[] | " • " + .package + " (" + .vulnerability_id + ")"' "$SAFETY_OUTPUT" 2>/dev/null | while read line; do
echo "$line" >&2
done
fi
fi
else
report_security "WARNING" "Safety check failed with exit code $SAFETY_EXIT_CODE"
fi
fi
rm -f "$SAFETY_OUTPUT"
elif command -v pip &> /dev/null; then
echo " 🔍 Safety not available, using pip-audit if available..." >&2
if command -v pip-audit &> /dev/null; then
PIP_AUDIT_OUTPUT="/tmp/pip_audit_$$"
if pip-audit --format=json > "$PIP_AUDIT_OUTPUT" 2>&1; then
report_security "PASS" "pip-audit completed - no vulnerabilities found"
else
report_security "ERROR" "pip-audit found vulnerabilities in Python dependencies"
fi
rm -f "$PIP_AUDIT_OUTPUT"
else
report_security "WARNING" "No Python security tools available (safety, pip-audit)"
fi
else
report_security "WARNING" "Python/pip not available - cannot perform Python security scan"
fi
fi
# 3. Ruby Security Scanning
if [[ "$PACKAGE_MANAGER" == "bundler" ]]; then
echo "💎 Ruby security scanning..." >&2
if command -v bundler-audit &> /dev/null; then
echo " 🔍 Running bundler-audit..." >&2
BUNDLER_AUDIT_OUTPUT="/tmp/bundler_audit_$$"
if bundler-audit check > "$BUNDLER_AUDIT_OUTPUT" 2>&1; then
report_security "PASS" "bundler-audit completed - no vulnerabilities found"
else
report_security "ERROR" "bundler-audit found vulnerabilities in Ruby dependencies"
# Count vulnerabilities
RUBY_VULNS=$(grep -c 'Vulnerability found' "$BUNDLER_AUDIT_OUTPUT" 2>/dev/null || echo "0")
if [ "$RUBY_VULNS" -gt 0 ]; then
echo " 📊 Found $RUBY_VULNS Ruby vulnerabilities" >&2
TOTAL_VULNERABILITIES=$((TOTAL_VULNERABILITIES + RUBY_VULNS))
fi
fi
rm -f "$BUNDLER_AUDIT_OUTPUT"
else
report_security "WARNING" "bundler-audit not available - install with 'gem install bundler-audit'"
fi
fi
# 4. Go Security Scanning
if [[ "$PACKAGE_MANAGER" == "go" ]]; then
echo "🐹 Go security scanning..." >&2
if command -v govulncheck &> /dev/null; then
echo " 🔍 Running govulncheck..." >&2
GOVULN_OUTPUT="/tmp/govuln_output_$$"
if govulncheck ./... > "$GOVULN_OUTPUT" 2>&1; then
report_security "PASS" "govulncheck completed - no vulnerabilities found"
else
report_security "ERROR" "govulncheck found vulnerabilities in Go dependencies"
# Count vulnerabilities
GO_VULNS=$(grep -c 'Vulnerability' "$GOVULN_OUTPUT" 2>/dev/null || echo "0")
if [ "$GO_VULNS" -gt 0 ]; then
echo " 📊 Found $GO_VULNS Go vulnerabilities" >&2
TOTAL_VULNERABILITIES=$((TOTAL_VULNERABILITIES + GO_VULNS))
fi
fi
rm -f "$GOVULN_OUTPUT"
else
report_security "WARNING" "govulncheck not available - install with 'go install golang.org/x/vuln/cmd/govulncheck@latest'"
fi
fi
# 5. PHP Security Scanning
if [[ "$PACKAGE_MANAGER" == "composer" ]]; then
echo "🐘 PHP security scanning..." >&2
if command -v composer &> /dev/null; then
echo " 🔍 Running composer audit..." >&2
COMPOSER_AUDIT_OUTPUT="/tmp/composer_audit_$$"
if composer audit > "$COMPOSER_AUDIT_OUTPUT" 2>&1; then
report_security "PASS" "Composer audit completed - no vulnerabilities found"
else
report_security "ERROR" "Composer audit found vulnerabilities in PHP dependencies"
# Count vulnerabilities
PHP_VULNS=$(grep -c 'vulnerability' "$COMPOSER_AUDIT_OUTPUT" 2>/dev/null || echo "0")
if [ "$PHP_VULNS" -gt 0 ]; then
echo " 📊 Found $PHP_VULNS PHP vulnerabilities" >&2
TOTAL_VULNERABILITIES=$((TOTAL_VULNERABILITIES + PHP_VULNS))
fi
fi
rm -f "$COMPOSER_AUDIT_OUTPUT"
else
report_security "WARNING" "Composer not available - cannot perform PHP security scan"
fi
fi
# 6. License Compliance Check
echo "📋 License compliance checking..." >&2
# Basic license check for Node.js projects
if [[ "$PACKAGE_MANAGER" == "npm" ]] && command -v npx &> /dev/null; then
if npx license-checker --summary >/dev/null 2>&1; then
LICENSE_SUMMARY=$(npx license-checker --summary 2>/dev/null | head -10)
echo " 📄 License summary available" >&2
else
report_security "INFO" "license-checker not available for license compliance"
fi
fi
# 7. Generate Security Report
echo "" >&2
echo "📋 Security Scan Summary:" >&2
echo "=========================" >&2
echo " 📄 File: $FILE_NAME" >&2
echo " 🔧 Package Manager: $PACKAGE_MANAGER" >&2
echo " 📝 Language: $LANGUAGE" >&2
echo " 🔒 Total Vulnerabilities: $TOTAL_VULNERABILITIES" >&2
if [ "$CRITICAL_SEVERITY" -gt 0 ]; then
echo " 🚨 Critical: $CRITICAL_SEVERITY" >&2
fi
if [ "$HIGH_SEVERITY" -gt 0 ]; then
echo " 🔴 High: $HIGH_SEVERITY" >&2
fi
if [ "$MEDIUM_SEVERITY" -gt 0 ]; then
echo " 🟡 Medium: $MEDIUM_SEVERITY" >&2
fi
if [ "$LOW_SEVERITY" -gt 0 ]; then
echo " 🟢 Low: $LOW_SEVERITY" >&2
fi
echo " ⚠️ Warnings: $WARNINGS" >&2
echo " ❌ Errors: $ERRORS" >&2
# Security status assessment
if [ "$CRITICAL_SEVERITY" -gt 0 ]; then
echo " 🚨 Status: CRITICAL - Immediate action required" >&2
elif [ "$HIGH_SEVERITY" -gt 0 ]; then
echo " 🔴 Status: HIGH RISK - Update dependencies soon" >&2
elif [ "$MEDIUM_SEVERITY" -gt 0 ]; then
echo " 🟡 Status: MODERATE RISK - Plan updates" >&2
elif [ "$LOW_SEVERITY" -gt 0 ]; then
echo " 🟢 Status: LOW RISK - Monitor and update when convenient" >&2
elif [ "$TOTAL_VULNERABILITIES" -eq 0 ] && [ "$ERRORS" -eq 0 ]; then
echo " ✅ Status: SECURE - No known vulnerabilities" >&2
else
echo " ⚠️ Status: UNKNOWN - Scan completed with issues" >&2
fi
echo "" >&2
echo "💡 Security Best Practices:" >&2
echo " • Run security scans regularly (weekly/monthly)" >&2
echo " • Keep dependencies up to date" >&2
echo " • Use dependency pinning for critical applications" >&2
echo " • Review security advisories for your dependencies" >&2
echo " • Consider using automated dependency update tools" >&2
echo " • Implement security scanning in CI/CD pipelines" >&2
# Exit with error if critical or high severity vulnerabilities found
if [ "$CRITICAL_SEVERITY" -gt 0 ] || [ "$HIGH_SEVERITY" -gt 0 ]; then
echo "⚠️ Security scan completed with high-priority vulnerabilities" >&2
exit 1
fi
else
# Not a package file, exit silently
exit 0
fi
exit 0
Complete hook script that performs multi-language vulnerability scanning
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
if [[ "$FILE_PATH" == *package.json ]] || [[ "$FILE_PATH" == *requirements.txt ]]; then
echo "🔒 Package Vulnerability Scanner for: $(basename "$FILE_PATH")" >&2
if [[ "$FILE_PATH" == *package.json ]]; then
if command -v npm &> /dev/null; then
echo "📦 Running npm audit..." >&2
if npm audit --json 2>/dev/null | jq -r '.metadata.vulnerabilities' 2>/dev/null | grep -q '"critical"\|"high"'; then
echo "❌ Vulnerabilities found" >&2
exit 1
else
echo "✅ No critical or high vulnerabilities" >&2
fi
fi
elif [[ "$FILE_PATH" == *requirements.txt ]]; then
if command -v safety &> /dev/null; then
echo "🐍 Running safety check..." >&2
if ! safety check --json 2>/dev/null; then
echo "❌ Python vulnerabilities found" >&2
exit 1
fi
fi
fi
fi
exit 0
Complete hook configuration for .claude/settings.json to enable package vulnerability scanning
{
"hooks": {
"postToolUse": {
"script": "./.claude/hooks/package-vulnerability-scanner.sh",
"matchers": ["write", "edit"]
}
}
}
Enhanced hook script for npm audit with detailed severity classification and exit code handling
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [[ "$FILE_PATH" == *package.json ]]; then
if command -v npm &> /dev/null && command -v jq &> /dev/null; then
NPM_AUDIT_OUTPUT="/tmp/npm_audit_$$"
npm audit --json > "$NPM_AUDIT_OUTPUT" 2>&1
AUDIT_EXIT_CODE=$?
if [ $AUDIT_EXIT_CODE -eq 1 ]; then
AUDIT_SUMMARY=$(jq -r '.metadata.vulnerabilities' "$NPM_AUDIT_OUTPUT" 2>/dev/null || echo '{}')
CRITICAL_COUNT=$(echo "$AUDIT_SUMMARY" | jq -r '.critical // 0')
HIGH_COUNT=$(echo "$AUDIT_SUMMARY" | jq -r '.high // 0')
MODERATE_COUNT=$(echo "$AUDIT_SUMMARY" | jq -r '.moderate // 0')
LOW_COUNT=$(echo "$AUDIT_SUMMARY" | jq -r '.low // 0')
echo "📊 Vulnerability Summary:" >&2
echo " 🚨 Critical: $CRITICAL_COUNT" >&2
echo " 🔴 High: $HIGH_COUNT" >&2
echo " 🟡 Moderate: $MODERATE_COUNT" >&2
echo " 🟢 Low: $LOW_COUNT" >&2
if [ "$CRITICAL_COUNT" -gt 0 ] || [ "$HIGH_COUNT" -gt 0 ]; then
exit 1
fi
fi
rm -f "$NPM_AUDIT_OUTPUT"
fi
fi
exit 0
Enhanced hook script for Python security scanning with safety and pip-audit fallback
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [[ "$FILE_PATH" == *requirements.txt ]]; then
if command -v safety &> /dev/null; then
SAFETY_OUTPUT="/tmp/safety_output_$$"
safety check --json > "$SAFETY_OUTPUT" 2>&1
SAFETY_EXIT_CODE=$?
if [ $SAFETY_EXIT_CODE -eq 64 ]; then
if command -v jq &> /dev/null && [ -f "$SAFETY_OUTPUT" ]; then
VULN_COUNT=$(jq length "$SAFETY_OUTPUT" 2>/dev/null || echo "0")
echo "📊 Found $VULN_COUNT Python vulnerabilities" >&2
jq -r '.[0:3] | .[] | " • " + .package + " (" + .vulnerability_id + ")"' "$SAFETY_OUTPUT" 2>/dev/null | while read line; do
echo "$line" >&2
done
fi
exit 1
fi
rm -f "$SAFETY_OUTPUT"
elif command -v pip-audit &> /dev/null; then
echo "🐍 Using pip-audit as fallback..." >&2
pip-audit --format=json 2>&1
fi
fi
exit 0
Enhanced hook script for Go security scanning with govulncheck integration
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [[ "$FILE_PATH" == *go.mod ]]; then
if command -v govulncheck &> /dev/null; then
GOVULN_OUTPUT="/tmp/govuln_output_$$"
if govulncheck ./... > "$GOVULN_OUTPUT" 2>&1; then
echo "✅ Go security scan completed - no vulnerabilities found" >&2
else
GO_VULNS=$(grep -c 'Vulnerability' "$GOVULN_OUTPUT" 2>/dev/null || echo "0")
if [ "$GO_VULNS" -gt 0 ]; then
echo "📊 Found $GO_VULNS Go vulnerabilities" >&2
exit 1
fi
fi
rm -f "$GOVULN_OUTPUT"
else
echo "⚠️ govulncheck not available - install with 'go install golang.org/x/vuln/cmd/govulncheck@latest'" >&2
fi
fi
exit 0
Hook handles exit code 1 as vulnerabilities found, not failure. To prevent blocking: wrap in || true or check $AUDIT_EXIT_CODE: if [ $AUDIT_EXIT_CODE -eq 1 ]; then report_security "ERROR" .... Verify npm audit exit codes. Test with various vulnerability scenarios.
Install jq: brew install jq (macOS), apt-get install jq (Ubuntu), or npm install -g jq. Hook falls back gracefully: jq -r '.metadata.vulnerabilities' ... 2>/dev/null || echo '{}'. Verify jq installation. Test with various JSON parsing scenarios.
Free tier has 30-day delay for vulnerability data. Use pip-audit as fallback: pip install pip-audit, hook auto-detects: if command -v pip-audit &> /dev/null; then pip-audit --format=json. Verify safety/pip-audit availability. Test with various Python package scenarios.
Add hash check to skip unchanged files: FILE_HASH=$(md5sum "$FILE_PATH") and cache. Or limit to root only: if [[ "$FILE_PATH" != ./package.json ]]; then exit 0; fi. Verify file path patterns. Test with various package file locations.
Hook provides structured counts: CRITICAL_SEVERITY, HIGH_SEVERITY, MEDIUM_SEVERITY, LOW_SEVERITY. Parse from npm audit JSON: CRITICAL_COUNT=$(echo "$AUDIT_SUMMARY" | jq -r '.critical // 0'). Verify severity parsing. Test with various vulnerability severity levels.
Install govulncheck: go install golang.org/x/vuln/cmd/govulncheck@latest. Verify Go installation and PATH. Test with various Go module structures. Ensure Go 1.18+ for govulncheck support.
Install bundler-audit: gem install bundler-audit. Verify Ruby and gem installation. Test with various Gemfile structures. Ensure bundler is available for Gemfile parsing.
Composer audit requires Composer 2.4+. Update Composer: composer self-update. Verify Composer version: composer --version. Test with various composer.json structures. Ensure Composer is properly installed.
Show that Package Vulnerability Scanner - Hooks is listed on HeyClaude. Paste this Markdown into your README — it renders the badge and links back to this page.
[](https://heyclau.de/entry/hooks/package-vulnerability-scanner)Package Vulnerability Scanner - Hooks side by side with 3 alternatives on trust, install, platform support, and disclosed safety notes — all from reviewed registry metadata.
2 trust signals differ across this comparison (Source provenance, Submitter).
| Field | Scans for security vulnerabilities when package.json or requirements.txt files are modified. Open dossier | PostToolUse hook that flags risky package-lock.json, yarn.lock, and pnpm-lock.yaml edits: missing lockfile updates, unexpected registry hosts, and dependency count spikes before merge. Open dossier | A Stop hook that runs npm audit, pip-audit, safety, or bundler-audit automatically at the end of every Claude Code session, detecting CVEs and outdated packages across Node.js, Python, and Ruby projects. Open dossier | Comprehensive Docker image vulnerability scanning with layer analysis, base image recommendations, and security best practices enforcement. This PostToolUse hook automatically scans Docker images for vulnerabilities when Dockerfiles are modified, providing real-time security validation during development. Open dossier |
|---|---|---|---|---|
| Next steps | ||||
| Trust | ||||
| Review status | ReviewedMaintainer reviewed | ReviewedMaintainer reviewed | ReviewedMaintainer reviewed | ReviewedMaintainer reviewed |
| Package trust | Package not verified | Package not verified | Package not verified | Package not verified |
| Source provenanceDiffers | Source-backed | Submission linkedSource submission | Source-backed | Source-backed |
| SubmitterDiffers | — | kiannidev | — | — |
| Install risk | Review first | Review first | Review first | Review first |
| Notes | Safety ✓ Privacy ✓ | Safety ✓ Privacy ✓ | Safety ✓ Privacy ✓ | Safety ✓ Privacy ✓ |
| Brand | — | — | — | |
| Category | hooks | hooks | hooks | hooks |
| Source | source-backed | source-backed | source-backed | source-backed |
| Author | JSONbored | kiannidev | JSONbored | JSONbored |
| Added | 2025-09-19 | 2026-06-17 | 2025-09-19 | 2025-10-19 |
| Platforms | Claude Code | Claude Code | Claude Code | Claude Code |
| Source repo | — | — | — | — |
| Safety notes | ✓Runs automatically on its configured Claude Code hook event and executes shell logic that can read, modify, or delete files in your project (and may run builds, installs, or network calls); review the script and scope it to expected paths before enabling. | ✓Read-only advisory hook; it does not block writes unless you wrap it with strict exit handling. Does not substitute for npm audit, OSV scans, or CI dependency review. | ✓Runs automatically at session end and invokes local package-manager audit tools when dependency lockfiles are present. May contact package registries or vulnerability advisory services through npm, yarn, safety, pip, or bundler-audit. Writes a timestamped security-audit log in the current working directory. | ✓Runs automatically on its configured Claude Code hook event and executes shell logic that can read, modify, or delete files in your project (and may run builds, installs, or network calls); review the script and scope it to expected paths before enabling. |
| Privacy notes | ✓Receives Claude Code hook input (session metadata, file paths, and tool output) and reads local project files; review what the script logs or forwards to external services and keep credentials out of its output. | ✓Lockfile paths and registry hostnames are printed locally to stderr for the active session. | ✓Reads dependency manifests and lockfiles to identify package managers and audit targets. The generated audit log may include package names, versions, vulnerability identifiers, and remediation output. External audit tools may send package metadata to their configured registries or advisory services. | ✓Receives Claude Code hook input (session metadata, file paths, and tool output) and reads local project files; review what the script logs or forwards to external services and keep credentials out of its output. |
| Prerequisites | — none listed |
| — none listed | — none listed |
| Install | | | | |
| Config | | | | |
| Citations | ||||
| Claim | Unclaimed | Unclaimed | Unclaimed | Unclaimed |
Source-backed guides for putting this to work.
Audit MCP client configuration before sharing it with a team.
Loading live community signals…
A short, calm digest of reviewed Claude resources. Unsubscribe any time.