Skip to content

Instantly share code, notes, and snippets.

@millancore
Created April 1, 2026 13:10
Show Gist options
  • Select an option

  • Save millancore/fb149033192e223ff0bb1adbcb251bae to your computer and use it in GitHub Desktop.

Select an option

Save millancore/fb149033192e223ff0bb1adbcb251bae to your computer and use it in GitHub Desktop.
NPM Audit Table format with jq
#!/usr/bin/env bash
# npm-audit: Run npm audit and display results in a table view using jq + column
# Usage: npm-audit [--severity critical|high|moderate|low|info]
set -euo pipefail
FILTER=""
usage() {
echo "Usage: npm-audit [--severity critical|high|moderate|low|info]"
echo " --severity Show only vulnerabilities at or above the given level"
exit 0
}
while [[ $# -gt 0 ]]; do
case "$1" in
--severity|-s)
FILTER="${2:-}"
shift 2
;;
--help|-h) usage ;;
*) echo "Unknown option: $1"; usage ;;
esac
done
if [[ -n "$FILTER" ]]; then
case "$FILTER" in
critical|high|moderate|low|info) ;;
*) echo "Invalid severity: $FILTER. Must be one of: critical high moderate low info"; exit 1 ;;
esac
fi
severity_color() {
case "$1" in
critical) printf '\033[0;31m' ;;
high) printf '\033[0;31m' ;;
moderate) printf '\033[1;33m' ;;
low) printf '\033[0;36m' ;;
info) printf '\033[0;37m' ;;
*) printf '' ;;
esac
}
# Run audit and capture JSON
AUDIT_JSON=$(npm audit --json 2>/dev/null || true)
if [ -z "$AUDIT_JSON" ]; then
echo "Error: npm audit returned no output. Are you in a Node.js project directory?" >&2
exit 1
fi
# Check for vulnerabilities count
VULN_COUNT=$(echo "$AUDIT_JSON" | jq '.metadata.vulnerabilities | .total // (.critical + .high + .moderate + .low + .info)' 2>/dev/null || echo 0)
if [ "$VULN_COUNT" -eq 0 ] 2>/dev/null; then
echo -e "\033[1mNo vulnerabilities found.\033[0m"
exit 0
fi
# Print summary header
echo ""
echo -e "\033[1mNPM Audit Report\033[0m"
[[ -n "$FILTER" ]] && echo -e "Filter: \033[1m$FILTER\033[0m and above"
# Print summary counts
echo ""
echo -e "\033[1mSummary:\033[0m"
echo "$AUDIT_JSON" | jq -r '
.metadata.vulnerabilities |
(if .critical > 0 then " \u001b[0;31mCritical : \(.critical)\u001b[0m" else empty end),
(if .high > 0 then " \u001b[0;31mHigh : \(.high)\u001b[0m" else empty end),
(if .moderate > 0 then " \u001b[1;33mModerate : \(.moderate)\u001b[0m" else empty end),
(if .low > 0 then " \u001b[0;36mLow : \(.low)\u001b[0m" else empty end),
(if .info > 0 then " \u001b[0;37mInfo : \(.info)\u001b[0m" else empty end)
'
echo ""
echo "================================================================================"
printf "\033[1m%-10s %-25s %-15s %s\033[0m\n" "SEVERITY" "PACKAGE" "VERSION" "URL"
echo "--------------------------------------------------------------------------------"
# Severity order map: critical=0, high=1, moderate=2, low=3, info=4
# Filter thresholds (show this level and above, i.e. lower or equal numeric order)
FILTER_LEVEL=4
case "$FILTER" in
critical) FILTER_LEVEL=0 ;;
high) FILTER_LEVEL=1 ;;
moderate) FILTER_LEVEL=2 ;;
low) FILTER_LEVEL=3 ;;
info) FILTER_LEVEL=4 ;;
esac
# Extract, sort by severity order, apply filter, print rows
echo "$AUDIT_JSON" | jq -r '
def sev_order: {"critical":0,"high":1,"moderate":2,"low":3,"info":4};
[
.vulnerabilities // {} |
to_entries[] |
.value as $v |
{
order: ($v.severity | sev_order[.] // 99),
sev: $v.severity,
pkg: $v.name,
ver: ($v.range // "unknown"),
url: ($v.via | if type == "array" then
map(if type == "object" then .url // "" else "" end) | map(select(. != "")) | first // "n/a"
else "" end)
}
] | sort_by(.order)[] |
"\(.order)|\(.sev)|\(.pkg)|\(.ver)|\(.url)"
' | while IFS='|' read -r order sev pkg ver url; do
if [[ "$order" -le "$FILTER_LEVEL" ]]; then
color=$(severity_color "$sev")
[[ ${#pkg} -gt 25 ]] && pkg="${pkg:0:24}…"
[[ ${#ver} -gt 15 ]] && ver="${ver:0:14}…"
printf "${color}%-10s\033[0m %-25s %-15s \033[0;34m%s\033[0m\n" "$sev" "$pkg" "$ver" "$url"
fi
done
echo "================================================================================"
echo ""
echo -e "Total vulnerabilities: \033[1m${VULN_COUNT}\033[0m"
echo ""
echo "Run 'npm audit fix' to fix automatically, or 'npm audit fix --force' to force."
echo ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment