#!/usr/bin/env node const MAX_INPUT_BYTES = 16 * 1024 * 1024; const MAX_ADVISORIES = 10_000; const MAX_FINDINGS_PER_ADVISORY = 10_000; const MAX_PATHS_PER_FINDING = 10_000; const MAX_TEXT_LENGTH = 16_384; const BLOCKED_SEVERITIES = new Set(['high', 'critical']); const KNOWN_SEVERITIES = new Set([ 'info', 'low', 'moderate', 'high', 'critical', ]); const PROFILE_IMPORTERS = Object.freeze([ 'packages/ql3-runtime-core', 'packages/ql3-local-command-file', 'packages/ql3-local-sqlite', 'packages/ql3-local-secret', 'packages/ql3-local-owner-console', 'packages/ql3-local-owner-cli', 'packages/ql3-local-owner-maintenance', 'packages/ql3-local-admin', 'packages/ql3-local-application', 'packages/ql3-local-execution', 'packages/ql3-local-process', 'packages/ql3-cluster-postgres', 'packages/ql3-cluster-control', 'packages/ql3-cluster-admin', 'packages/ql3-worker-runtime', ]); class ProfileVulnerabilityAuditError extends Error { constructor(message) { super(`QingLong profile vulnerability audit failed: ${message}`); this.name = 'ProfileVulnerabilityAuditError'; } } function boundedText(value, name) { if ( typeof value !== 'string' || value.length < 1 || value.length > MAX_TEXT_LENGTH || /[\0\r\n]/.test(value) ) { throw new ProfileVulnerabilityAuditError(`${name} is invalid`); } return value; } function boundedArray(value, maximum, name) { if (!Array.isArray(value) || value.length > maximum) { throw new ProfileVulnerabilityAuditError(`${name} is invalid`); } return value; } function emptySummary() { return { info: new Set(), low: new Set(), moderate: new Set(), high: new Set(), critical: new Set(), modules: new Set(), pathCount: 0, }; } function publicSummary(summary) { return Object.freeze({ advisories: Object.freeze({ info: summary.info.size, low: summary.low.size, moderate: summary.moderate.size, high: summary.high.size, critical: summary.critical.size, }), modules: Object.freeze([...summary.modules].sort()), pathCount: summary.pathCount, compatible: summary.high.size === 0 && summary.critical.size === 0, }); } function importerFromPath(dependencyPath) { const separator = dependencyPath.indexOf(' > '); return separator === -1 ? dependencyPath : dependencyPath.slice(0, separator); } function advisoryIdentity(advisory) { const value = advisory.github_advisory_id ?? advisory.id; if ( (typeof value !== 'string' && typeof value !== 'number') || String(value).length > 128 ) { throw new ProfileVulnerabilityAuditError('advisory identity is invalid'); } return String(value); } function auditProfileVulnerabilities(audit) { if (!audit || typeof audit !== 'object' || Array.isArray(audit)) { throw new ProfileVulnerabilityAuditError('audit document is invalid'); } if ( !audit.advisories || typeof audit.advisories !== 'object' || Array.isArray(audit.advisories) ) { throw new ProfileVulnerabilityAuditError('advisories are unavailable'); } const advisories = Object.values(audit.advisories); if (advisories.length > MAX_ADVISORIES) { throw new ProfileVulnerabilityAuditError('advisory budget exceeded'); } const summaries = new Map([ ['.', emptySummary()], ...PROFILE_IMPORTERS.map((importer) => [importer, emptySummary()]), ]); const findings = []; const findingKeys = new Set(); const unknownImporters = new Set(); for (const advisory of advisories) { if (!advisory || typeof advisory !== 'object' || Array.isArray(advisory)) { throw new ProfileVulnerabilityAuditError('advisory is invalid'); } const advisoryId = advisoryIdentity(advisory); const moduleName = boundedText(advisory.module_name, 'module name'); const severity = boundedText(advisory.severity, 'severity'); if (!KNOWN_SEVERITIES.has(severity)) { throw new ProfileVulnerabilityAuditError('severity is unsupported'); } const advisoryFindings = boundedArray( advisory.findings, MAX_FINDINGS_PER_ADVISORY, 'advisory findings', ); for (const finding of advisoryFindings) { if (!finding || typeof finding !== 'object' || Array.isArray(finding)) { throw new ProfileVulnerabilityAuditError('finding is invalid'); } const version = boundedText(finding.version, 'finding version'); const paths = boundedArray( finding.paths, MAX_PATHS_PER_FINDING, 'finding paths', ); for (const dependencyPathValue of paths) { const dependencyPath = boundedText( dependencyPathValue, 'dependency path', ); const importer = importerFromPath(dependencyPath); const summary = summaries.get(importer); if (summary) { summary[severity].add(advisoryId); summary.modules.add(moduleName); summary.pathCount += 1; } else { unknownImporters.add(importer); } if ( BLOCKED_SEVERITIES.has(severity) && (importer !== '.' || !summary) ) { const code = summary ? 'PROFILE_HIGH_CRITICAL_ADVISORY' : 'UNREVIEWED_IMPORTER_HIGH_CRITICAL_ADVISORY'; const findingKey = [ code, importer, advisoryId, moduleName, version, ].join('\0'); if (!findingKeys.has(findingKey)) { findingKeys.add(findingKey); findings.push({ code, importer, advisoryId, moduleName, severity, version, }); } } } } } findings.sort( (left, right) => left.importer.localeCompare(right.importer) || left.moduleName.localeCompare(right.moduleName) || left.advisoryId.localeCompare(right.advisoryId), ); const profileImporters = Object.fromEntries( PROFILE_IMPORTERS.map((importer) => [ importer, publicSummary(summaries.get(importer)), ]), ); const legacyRoot = publicSummary(summaries.get('.')); return Object.freeze({ schemaVersion: 1, threshold: 'high', profileImporters: Object.freeze(profileImporters), legacyRoot, unknownImporters: Object.freeze([...unknownImporters].sort()), findings: Object.freeze(findings), compatible: findings.length === 0, }); } function main() { let input = ''; process.stdin.setEncoding('utf8'); process.stdin.on('data', (chunk) => { input += chunk; if (Buffer.byteLength(input) > MAX_INPUT_BYTES) { process.stdin.destroy( new ProfileVulnerabilityAuditError('input budget exceeded'), ); } }); process.stdin.on('end', () => { try { const report = auditProfileVulnerabilities(JSON.parse(input)); process.stdout.write(`${JSON.stringify(report)}\n`); if (!report.compatible) process.exitCode = 1; } catch (error) { process.stderr.write( `${error instanceof Error ? error.message : String(error)}\n`, ); process.exitCode = 1; } }); process.stdin.on('error', (error) => { process.stderr.write( `${error instanceof Error ? error.message : String(error)}\n`, ); process.exitCode = 1; }); } module.exports = { PROFILE_IMPORTERS, ProfileVulnerabilityAuditError, auditProfileVulnerabilities, }; if (require.main === module) main();