feat(ql3): establish 3.0 incubation baseline

This commit is contained in:
whyour
2026-08-12 00:25:26 +08:00
parent 4bf92dcfeb
commit c699c32461
2817 changed files with 779642 additions and 653 deletions
@@ -0,0 +1,300 @@
#!/usr/bin/env node
'use strict';
const fs = require('node:fs');
const path = require('node:path');
const { TextDecoder } = require('node:util');
const FIXTURE = 'qinglong/image-os-vulnerability-exceptions@v1';
const IMAGES = Object.freeze(['admin', 'control', 'control-ai', 'local']);
const MAX_POLICY_BYTES = 256 * 1024;
const MAX_EXCEPTIONS = 128;
const MAX_EXCEPTION_DAYS = 30;
const CONTROL_PATTERN = /[\u0000-\u001f\u007f]/;
const CVE_PATTERN = /^CVE-[0-9]{4}-[0-9]{4,}$/;
const OWNER_PATTERN = /^[a-z0-9][a-z0-9._/-]{1,127}$/;
const TICKET_PATTERN = /^[A-Z][A-Z0-9]{1,15}-[1-9][0-9]{0,9}$/;
const PURL_PATTERN = /^pkg:(?:apk|deb|rpm)\/[A-Za-z0-9._~%+-]+\/[A-Za-z0-9._~%+-]+@[A-Za-z0-9._~%+:-]+$/;
const DEFAULT_ROOT = path.resolve(__dirname, '..');
const POLICY_PATH = 'deploy/containers/ql3-os-vulnerability-exceptions.json';
class ImageOsVulnerabilityPolicyError extends Error {
constructor(message) {
super(`QingLong image OS vulnerability policy failed: ${message}`);
this.name = 'ImageOsVulnerabilityPolicyError';
}
}
function fail(message) {
throw new ImageOsVulnerabilityPolicyError(message);
}
function exactKeys(value, keys) {
return (
value !== null &&
typeof value === 'object' &&
!Array.isArray(value) &&
JSON.stringify(Object.keys(value).sort()) ===
JSON.stringify([...keys].sort())
);
}
function uniqueSorted(values) {
return (
Array.isArray(values) &&
values.length > 0 &&
new Set(values).size === values.length &&
JSON.stringify(values) === JSON.stringify([...values].sort())
);
}
function boundedText(value, minimum, maximum) {
return (
typeof value === 'string' &&
value.length >= minimum &&
value.length <= maximum &&
!CONTROL_PATTERN.test(value)
);
}
function utcDay(value) {
if (typeof value !== 'string' || !/^\d{4}-\d{2}-\d{2}$/.test(value)) {
return null;
}
const milliseconds = Date.parse(`${value}T00:00:00.000Z`);
return Number.isFinite(milliseconds) &&
new Date(milliseconds).toISOString().slice(0, 10) === value
? milliseconds
: null;
}
function auditImageOsVulnerabilityPolicy(policy, dependencies = { now: Date.now }) {
if (!exactKeys(dependencies, ['now']) || typeof dependencies.now !== 'function') {
fail('clock is invalid');
}
const nowMs = dependencies.now();
if (!Number.isSafeInteger(nowMs) || nowMs < 0) fail('clock is invalid');
const todayMs = Date.parse(new Date(nowMs).toISOString().slice(0, 10));
const findings = [];
const add = (code, id = null) => findings.push(Object.freeze({ code, id }));
if (
!exactKeys(policy, ['schemaVersion', 'fixture', 'exceptions']) ||
policy?.schemaVersion !== 1 ||
policy?.fixture !== FIXTURE ||
!Array.isArray(policy?.exceptions) ||
policy.exceptions.length > MAX_EXCEPTIONS
) {
add('QL3_IMAGE_OS_VULNERABILITY_POLICY_SHAPE');
return Object.freeze({
compatible: false,
findings: Object.freeze(findings),
exceptionCount: 0,
imageExceptionCounts: Object.freeze({
admin: 0,
control: 0,
'control-ai': 0,
local: 0,
}),
});
}
const counts = { admin: 0, control: 0, 'control-ai': 0, local: 0 };
const seen = new Set();
let previousId = '';
for (const exception of policy.exceptions) {
const id = exception?.id ?? null;
if (
!exactKeys(exception, [
'id',
'images',
'purls',
'owner',
'ticket',
'expiresOn',
'rationale',
]) ||
!CVE_PATTERN.test(id ?? '') ||
seen.has(id) ||
id <= previousId
) {
add('QL3_IMAGE_OS_VULNERABILITY_EXCEPTION_ID', id);
continue;
}
seen.add(id);
previousId = id;
if (
!uniqueSorted(exception.images) ||
exception.images.some((image) => !IMAGES.includes(image))
) {
add('QL3_IMAGE_OS_VULNERABILITY_EXCEPTION_IMAGES', id);
} else {
for (const image of exception.images) counts[image] += 1;
}
if (
!uniqueSorted(exception.purls) ||
exception.purls.some((purl) => !PURL_PATTERN.test(purl))
) {
add('QL3_IMAGE_OS_VULNERABILITY_EXCEPTION_PURLS', id);
}
if (!OWNER_PATTERN.test(exception.owner ?? '')) {
add('QL3_IMAGE_OS_VULNERABILITY_EXCEPTION_OWNER', id);
}
if (!TICKET_PATTERN.test(exception.ticket ?? '')) {
add('QL3_IMAGE_OS_VULNERABILITY_EXCEPTION_TICKET', id);
}
if (!boundedText(exception.rationale, 20, 512)) {
add('QL3_IMAGE_OS_VULNERABILITY_EXCEPTION_RATIONALE', id);
}
const expiryMs = utcDay(exception.expiresOn);
if (
expiryMs === null ||
expiryMs <= todayMs ||
expiryMs - todayMs > MAX_EXCEPTION_DAYS * 24 * 60 * 60 * 1000
) {
add('QL3_IMAGE_OS_VULNERABILITY_EXCEPTION_EXPIRY', id);
}
}
return Object.freeze({
compatible: findings.length === 0,
findings: Object.freeze(findings),
exceptionCount: policy.exceptions.length,
imageExceptionCounts: Object.freeze(counts),
});
}
function readPolicy(root = DEFAULT_ROOT) {
const filePath = path.join(path.resolve(root), POLICY_PATH);
const stat = fs.lstatSync(filePath);
if (
!stat.isFile() ||
stat.isSymbolicLink() ||
stat.size < 2 ||
stat.size > MAX_POLICY_BYTES ||
fs.realpathSync(filePath) !== filePath
) {
fail('policy must be one canonical bounded regular file');
}
let bytes;
try {
bytes = fs.readFileSync(filePath);
return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes));
} catch (error) {
if (error instanceof ImageOsVulnerabilityPolicyError) throw error;
fail('policy must contain UTF-8 JSON');
} finally {
if (bytes) bytes.fill(0);
}
}
function renderTrivyIgnore(policy, image, dependencies = { now: Date.now }) {
if (!IMAGES.includes(image)) fail('image is invalid');
const audit = auditImageOsVulnerabilityPolicy(policy, dependencies);
if (!audit.compatible) fail('policy is incompatible');
const selected = policy.exceptions.filter((entry) => entry.images.includes(image));
const lines = ['vulnerabilities:'];
if (selected.length === 0) lines.push(' []');
for (const exception of selected) {
lines.push(` - id: ${JSON.stringify(exception.id)}`);
lines.push(' purls:');
for (const purl of exception.purls) {
lines.push(` - ${JSON.stringify(purl)}`);
}
lines.push(` expired_at: ${exception.expiresOn}`);
lines.push(
` statement: ${JSON.stringify(`owner=${exception.owner}; ticket=${exception.ticket}; rationale=${exception.rationale}`)}`,
);
}
return `${lines.join('\n')}\n`;
}
function writeNoReplace(filePath, value) {
if (
typeof filePath !== 'string' ||
!path.isAbsolute(filePath) ||
CONTROL_PATTERN.test(filePath) ||
fs.existsSync(filePath) ||
fs.realpathSync(path.dirname(filePath)) !== path.dirname(filePath)
) {
fail('output path must be unused in one canonical directory');
}
let descriptor = -1;
const bytes = Buffer.from(value, 'utf8');
try {
descriptor = fs.openSync(
filePath,
fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL,
0o600,
);
fs.writeFileSync(descriptor, bytes);
fs.fsyncSync(descriptor);
} finally {
bytes.fill(0);
if (descriptor >= 0) fs.closeSync(descriptor);
}
}
function parseArguments(argv) {
if (argv.length === 0) return Object.freeze({ mode: 'audit' });
const values = {};
for (const argument of argv) {
if (argument === '--') continue;
const match = /^--([a-z-]+)=(.+)$/.exec(argument);
if (!match || Object.hasOwn(values, match[1])) fail('arguments are invalid');
values[match[1]] = match[2];
}
if (
JSON.stringify(Object.keys(values).sort()) !==
JSON.stringify(['image', 'output'])
) {
fail('arguments are invalid');
}
return Object.freeze({ mode: 'render', image: values.image, output: values.output });
}
function runCli(argv, root = DEFAULT_ROOT, dependencies = { now: Date.now }) {
const options = parseArguments(argv);
const policy = readPolicy(root);
const audit = auditImageOsVulnerabilityPolicy(policy, dependencies);
if (!audit.compatible) fail('policy is incompatible');
if (options.mode === 'render') {
writeNoReplace(
options.output,
renderTrivyIgnore(policy, options.image, dependencies),
);
}
const report = {
schemaVersion: 1,
fixture: FIXTURE,
compatible: true,
exceptionCount: audit.exceptionCount,
imageExceptionCounts: audit.imageExceptionCounts,
};
process.stdout.write(`${JSON.stringify(report)}\n`);
return report;
}
if (require.main === module) {
try {
runCli(process.argv.slice(2));
} catch (error) {
process.stderr.write(
`${error instanceof Error ? error.message : 'policy audit failed'}\n`,
);
process.exitCode = 1;
}
}
module.exports = {
FIXTURE,
IMAGES,
MAX_EXCEPTION_DAYS,
ImageOsVulnerabilityPolicyError,
auditImageOsVulnerabilityPolicy,
parseArguments,
readPolicy,
renderTrivyIgnore,
runCli,
writeNoReplace,
};