with one click
npm-audit
// Investigate and decide on npm audit vulnerabilities—fix vs. allowlist pattern with shared gate utility
// Investigate and decide on npm audit vulnerabilities—fix vs. allowlist pattern with shared gate utility
| name | npm-audit |
| description | Investigate and decide on npm audit vulnerabilities—fix vs. allowlist pattern with shared gate utility |
| version | 1.0.0 |
Use this skill when:
npm audit --omit=dev --audit-level=moderate is failing in the release gate (scripts/publish/bump-version.sh)package.json overrides or audit allowlistsAdvisory IDs are passed as the first argument to scripts/lib/check-audit-gate.sh. An empty string
means strict mode (no advisories allowed).
Keep all call sites in sync when adding or removing IDs:
scripts/publish/bump-version.shscripts/publish/sync-develop-to-staging.shscripts/publish/sync-staging-to-main.shDocument rationale in docs/development/security/NPM-AUDIT-ALLOWLIST.md whenever the allowlist is
non-empty.
npm audit --omit=dev --json > temp/audit-report.json
node --input-type=module -e "
import fs from 'fs';
const audit = JSON.parse(fs.readFileSync('temp/audit-report.json', 'utf8'));
for (const [pkg, data] of Object.entries(audit.vulnerabilities || {})) {
if (Array.isArray(data.via)) {
for (const adv of data.via) {
if (typeof adv === 'object') {
console.log(\`\${pkg}: \${adv.severity} - \${adv.title} (Advisory \${adv.source})\`);
console.log(\` URL: \${adv.url}\`);
console.log(\` Via: \${data.via}\`);
}
}
}
}
"
This shows:
For each vulnerability, understand the full path:
npm ls <vulnerable-package> --all
Example output for uuid@9.0.1:
podverse@5.4.12
└── (transitive)
└── firebase-admin@13.8.0
└── @google-cloud/storage@7.19.0
└── teeny-request@9.0.0
└── uuid@9.0.1 (vulnerable)
Root cause types:
Direct dependency outdated
package.json is not at latestnpm upgrade <package>Transitive dependency in resolvable chain
Transitive dependency in constrained chain (most common)
# In package.json, try an override like:
"overrides": {
"uuid": "14.0.0",
"teeny-request": {
"uuid": "14.0.0"
}
}
npm install and re-auditNested optional dependency bug (hardest case)
package-lock.json shows node_modules/teeny-request/node_modules/uuid@9.0.1 even though you have "uuid": "14.0.0" in overridesFix if:
Direct dependency upgrade resolves it
A recent major version of an intermediate package resolves it
npm overrides can successfully force the resolution (verify in package-lock.json)
The vulnerability is directly exploitable in Podverse's usage
Allowlist if:
If allowlisting, always document why in docs/development/security/NPM-AUDIT-ALLOWLIST.md:
### Advisory XXXXX: <vulnerability name>
**Affected chain:** pkg1 → pkg2 → pkg3 → vulnerable-pkg
**Why it's allowlisted:**
- Latest pkg3@X.Y still pins vulnerable-pkg@<14
- Downgrading pkg1 causes regressions (list them)
- Replacing pkg1 would require major refactor (explain scope)
**Risk level:** Transitive-only; not directly exploitable because [reason].
### When to revisit:
- When pkg1 releases X+1.0.0 with upgraded dependencies
- When pkg3 releases Y+1.0.0 that drops the vulnerable dep
Then pass the same comma-separated IDs from each publish script that invokes check-audit-gate.sh,
for example:
"$SCRIPT_DIR/../lib/check-audit-gate.sh" "1113977" "release"
Note upstream upgrades or override removals in docs/development/security/NPM-AUDIT-ALLOWLIST.md so the
allowlist can shrink again later.
Symptom: Root package.json has "uuid": "14.0.0" override, but npm audit still reports uuid@9.0.1 in the output.
Why: Optional dependencies get their own node_modules folder, and npm doesn't always apply overrides there.
Verification:
# Check the lockfile for nested node_modules
grep -A2 'node_modules/teeny-request/node_modules/uuid' package-lock.json
If you see a nested uuid entry with version < 14, the override didn't work.
Options:
"teeny-request": "11.x""@google-cloud/storage": "8.0.0"Symptom: Running npm audit fix --force downgrades critical packages like firebase-admin@10.1.0.
Why: --force prioritizes clearing vulnerabilities over semver compatibility.
Solution: Never use --force in monorepos. Instead, carefully upgrade intermediate packages one at a time and check side effects.
npm run build:packages && npm run build succeedsdocs/development/security/NPM-AUDIT-ALLOWLIST.mdcheck-audit-gate.shdocs/development/security/NPM-AUDIT-ALLOWLIST.md — Allowlist policy and historyscripts/lib/check-audit-gate.sh — Shared moderate+ audit gatescripts/publish/bump-version.sh — Release audit invocation[HINT] Download the complete skill directory including SKILL.md and all related files