|
@@ -152,21 +152,30 @@ jobs:
|
|
|
- name: Run npm audit
|
|
- name: Run npm audit
|
|
|
working-directory: frontend
|
|
working-directory: frontend
|
|
|
run: |
|
|
run: |
|
|
|
- # Only audit production dependencies — dev dependency vulnerabilities
|
|
|
|
|
- # don't affect end users. Detailed audits are handled by security.yml.
|
|
|
|
|
|
|
+ # Only audit production dependencies and filter out npm-internal packages
|
|
|
|
|
+ # (npm audit reports vulnerabilities in its own bundled deps like tar/minimatch).
|
|
|
npm audit --omit=dev --json > /tmp/audit.json 2>/dev/null || true
|
|
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 "
|
|
python3 -c "
|
|
|
- import json, sys
|
|
|
|
|
|
|
+ import json, sys, subprocess
|
|
|
data = json.load(open('/tmp/audit.json'))
|
|
data = json.load(open('/tmp/audit.json'))
|
|
|
|
|
+ deps = json.load(open('/tmp/deps.json'))
|
|
|
|
|
+ prod = set()
|
|
|
|
|
+ def walk(obj):
|
|
|
|
|
+ for name, info in (obj.get('dependencies') or {}).items():
|
|
|
|
|
+ prod.add(name)
|
|
|
|
|
+ walk(info)
|
|
|
|
|
+ walk(deps)
|
|
|
vulns = data.get('vulnerabilities', {})
|
|
vulns = data.get('vulnerabilities', {})
|
|
|
fixable = {n: v for n, v in vulns.items()
|
|
fixable = {n: v for n, v in vulns.items()
|
|
|
- if v.get('severity') in ('high', 'critical') and v.get('fixAvailable')}
|
|
|
|
|
|
|
+ if n in prod and v.get('severity') in ('high', 'critical') and v.get('fixAvailable')}
|
|
|
|
|
+ skipped = len(vulns) - len({n: v for n, v in vulns.items() if n in prod})
|
|
|
if fixable:
|
|
if fixable:
|
|
|
for name, v in fixable.items():
|
|
for name, v in fixable.items():
|
|
|
print(f'FIXABLE {v[\"severity\"].upper()}: {name}')
|
|
print(f'FIXABLE {v[\"severity\"].upper()}: {name}')
|
|
|
sys.exit(1)
|
|
sys.exit(1)
|
|
|
- total = sum(1 for v in vulns.values() if v.get('severity') in ('high', 'critical'))
|
|
|
|
|
- print(f'npm audit: {total} high/critical (0 fixable), {len(vulns)} total known')
|
|
|
|
|
|
|
+ total = sum(1 for n, v in vulns.items() if n in prod and v.get('severity') in ('high', 'critical'))
|
|
|
|
|
+ print(f'npm audit: {total} high/critical (0 fixable), {len(vulns)} total ({skipped} npm-internal filtered)')
|
|
|
"
|
|
"
|
|
|
|
|
|
|
|
frontend-typecheck:
|
|
frontend-typecheck:
|