mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
* ci: audit dependency security without gating releases * ci: audit stable release tags instead of running daily * ci: isolate release audit data and fix integration checks * ci: require exact audit inputs and ignore candidate archive attributes
88 lines
3.2 KiB
JavaScript
88 lines
3.2 KiB
JavaScript
import { runProcessSync } from '@orca/process-host'
|
|
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
import { join, resolve } from 'node:path'
|
|
import { pathToFileURL } from 'node:url'
|
|
import {
|
|
AUDIT_WORKSPACES,
|
|
evaluateSecurityAudit,
|
|
securityExceptions
|
|
} from './dependency-security-audit.mjs'
|
|
import { resolvePnpmCliInvocation } from './pnpm-cli-invocation.mjs'
|
|
|
|
const ROOT = resolve(import.meta.dirname, '../..')
|
|
|
|
export function readSecurityAudit(result) {
|
|
if (
|
|
result.signal ||
|
|
result.timedOut ||
|
|
result.outputTruncated ||
|
|
(result.code !== 0 && result.code !== 1)
|
|
) {
|
|
throw new Error(`Dependency audit failed (${result.code}): ${result.stderr || result.stdout}`)
|
|
}
|
|
const report = JSON.parse(result.stdout)
|
|
if (result.code === 1 && Object.keys(report.advisories ?? {}).length === 0) {
|
|
throw new Error('Audit failed without a vulnerability report')
|
|
}
|
|
return report
|
|
}
|
|
|
|
export function checkDependencySecurity(root = ROOT, workspaces = AUDIT_WORKSPACES) {
|
|
const exceptions = securityExceptions.parse(
|
|
JSON.parse(readFileSync(join(ROOT, 'config/dependency-security-exceptions.json'), 'utf8'))
|
|
)
|
|
const reportDir = join(ROOT, 'tmp/dependency-security')
|
|
mkdirSync(reportDir, { recursive: true })
|
|
const { command, prefixArgs } = resolvePnpmCliInvocation()
|
|
const today = new Date().toISOString().slice(0, 10)
|
|
let passed = true
|
|
for (const workspace of workspaces) {
|
|
const report = { workspace, checkedAt: new Date().toISOString() }
|
|
try {
|
|
const result = runProcessSync({
|
|
program: command,
|
|
args: [
|
|
...prefixArgs,
|
|
'audit',
|
|
'--json',
|
|
'--ignore-pnpmfile',
|
|
'--registry=https://registry.npmjs.org'
|
|
],
|
|
cwd: join(root, workspace),
|
|
timeoutMs: 120_000,
|
|
maxOutputBytes: 32 * 1024 * 1024
|
|
})
|
|
report.audit = readSecurityAudit(result)
|
|
report.findings = evaluateSecurityAudit(report.audit, workspace, exceptions, { root, today })
|
|
for (const item of report.findings) {
|
|
console.log(
|
|
`${workspace}: ${item.exception ? 'PATCHED' : item.blocking ? 'BLOCKING' : 'FINDING'} ${item.package}@${item.version} ${item.severity} ${item.advisory} ${item.url}`
|
|
)
|
|
}
|
|
if (report.findings.some((item) => item.blocking)) {
|
|
passed = false
|
|
}
|
|
console.log(`${workspace}: ${report.findings.length} finding(s)`)
|
|
} catch (error) {
|
|
report.error = error.message
|
|
console.error(`${workspace}: ${error.message}`)
|
|
passed = false
|
|
}
|
|
const name = workspace === '.' ? 'desktop' : workspace.replaceAll('/', '-')
|
|
writeFileSync(join(reportDir, `${name}.json`), `${JSON.stringify(report, null, 2)}\n`)
|
|
}
|
|
console.log(`Dependency reports: ${reportDir}`)
|
|
return passed ? 0 : 1
|
|
}
|
|
|
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
const workspaces = process.argv.slice(3)
|
|
if (workspaces.some((workspace) => !AUDIT_WORKSPACES.includes(workspace))) {
|
|
throw new Error('Unknown dependency audit workspace')
|
|
}
|
|
process.exitCode = checkDependencySecurity(
|
|
resolve(process.argv[2] ?? ROOT),
|
|
workspaces.length ? workspaces : AUDIT_WORKSPACES
|
|
)
|
|
}
|