Both workflows now parse package-lock.json directly instead of trusting npm ls. The lockfile correctly marks minimatch as dev: true and doesn't contain npm/tar at all —

so all three npm-internal packages will be filtered out regardless of which npm version CI uses.
This commit is contained in:
maziggy
2026-02-20 19:32:07 +01:00
parent 4991192246
commit 7c0eeed8d5
2 changed files with 16 additions and 20 deletions
+8 -10
View File
@@ -152,20 +152,18 @@ jobs:
- name: Run npm audit
working-directory: frontend
run: |
# Only audit production dependencies and filter out npm-internal packages
# (npm audit reports vulnerabilities in its own bundled deps like tar/minimatch).
# Only audit production dependencies and filter out npm-internal packages.
# npm 10.x audit/ls reports vulns in its own bundled deps (npm, tar, minimatch)
# so we parse package-lock.json directly to get the real prod dep list.
npm audit --omit=dev --json > /tmp/audit.json 2>/dev/null || true
npm ls --omit=dev --all --json 2>/dev/null > /tmp/deps.json || true
python3 -c "
import json, sys, subprocess
import json, sys
data = json.load(open('/tmp/audit.json'))
deps = json.load(open('/tmp/deps.json'))
lock = json.load(open('package-lock.json'))
prod = set()
def walk(obj):
for name, info in (obj.get('dependencies') or {}).items():
prod.add(name)
walk(info)
walk(deps)
for path, info in lock.get('packages', {}).items():
if path and not info.get('dev') and not info.get('devOptional'):
prod.add(path.split('node_modules/')[-1])
vulns = data.get('vulnerabilities', {})
fixable = {n: v for n, v in vulns.items()
if n in prod and v.get('severity') in ('high', 'critical') and v.get('fixAvailable')}
+8 -10
View File
@@ -278,23 +278,21 @@ jobs:
working-directory: frontend
run: |
npm audit --omit=dev --json > npm-audit-raw.json 2>/dev/null || true
# Filter audit results to only include actual project dependencies
# (npm audit sometimes reports vulnerabilities in the npm CLI itself)
# Filter audit results to only include actual project dependencies.
# npm 10.x audit/ls reports vulns in its own bundled deps (npm, tar, minimatch)
# so we parse package-lock.json directly to get the real prod dep list.
node -e "
const fs = require('fs');
const raw = fs.readFileSync('npm-audit-raw.json', 'utf8');
let results;
try { results = JSON.parse(raw); } catch { results = { vulnerabilities: {} }; }
const depTree = JSON.parse(require('child_process').execSync(
'npm ls --omit=dev --all --json 2>/dev/null', { encoding: 'utf8' }
));
const lock = JSON.parse(fs.readFileSync('package-lock.json', 'utf8'));
const prodDeps = new Set();
(function walk(obj) {
for (const [name, info] of Object.entries(obj.dependencies || {})) {
prodDeps.add(name);
walk(info);
for (const [path, info] of Object.entries(lock.packages || {})) {
if (path && !info.dev && !info.devOptional) {
prodDeps.add(path.split('node_modules/').pop());
}
})(depTree);
}
const vulns = results.vulnerabilities || {};
const filtered = {};
for (const [name, info] of Object.entries(vulns)) {