36 lines
1.6 KiB
JavaScript
36 lines
1.6 KiB
JavaScript
import { createHash } from 'node:crypto'
|
|
import { execFile } from 'node:child_process'
|
|
import { readFile, writeFile } from 'node:fs/promises'
|
|
import { promisify } from 'node:util'
|
|
import { resolve } from 'node:path'
|
|
|
|
const run = promisify(execFile)
|
|
const root = resolve(new URL('..', import.meta.url).pathname)
|
|
const lockPath = resolve(root, 'package-lock.json')
|
|
const outputPath = resolve(root, 'config/npm-audit-critical.json')
|
|
const lockfileSha256 = createHash('sha256').update(await readFile(lockPath)).digest('hex')
|
|
let stdout = ''
|
|
let exitCode = 0
|
|
try {
|
|
({ stdout } = await run(resolve(root, 'npmw'), ['audit', '--omit=dev', '--audit-level=critical', '--json'], { cwd: root, maxBuffer: 16 * 1024 * 1024 }))
|
|
} catch (error) {
|
|
exitCode = error.code ?? 1
|
|
stdout = error.stdout ?? ''
|
|
}
|
|
if (!stdout.trim()) throw new Error(`npm audit produced no JSON output (exit ${exitCode}).`)
|
|
const audit = JSON.parse(stdout)
|
|
const vulnerabilities = audit.vulnerabilities ?? {}
|
|
const critical = Number(audit.metadata?.vulnerabilities?.critical ?? 0)
|
|
const report = {
|
|
schemaVersion: 1,
|
|
status: critical === 0 ? 'pass' : 'failed',
|
|
command: 'npm audit --omit=dev --audit-level=critical --json',
|
|
lockfileSha256,
|
|
auditReportVersion: audit.auditReportVersion,
|
|
metadata: audit.metadata,
|
|
vulnerabilities,
|
|
}
|
|
await writeFile(outputPath, `${JSON.stringify(report, null, 2)}\n`)
|
|
console.log(JSON.stringify({ status: report.status === 'pass' ? 'dependency-audit-generated' : 'dependency-audit-failed', output: outputPath, critical, total: audit.metadata?.vulnerabilities?.total ?? null, lockfileSha256 }, null, 2))
|
|
if (critical > 0) process.exit(1)
|