From f4c3b23849bd2bf5f73690c10aa7b7631a29c0eb Mon Sep 17 00:00:00 2001 From: bendo-eXX Date: Wed, 29 Jul 2026 15:29:58 +0200 Subject: [PATCH 1/2] feat(CSAF2.1): add recommendedTest_6_2_53.js --- .../recommendedTest_6_2_53.js | 10 ++---- package.json | 5 +++ rvisc.js | 32 +++++++++++++++++++ scripts/rvisc-importRegistry.js | 32 +++++++++++++++++++ tests/csaf_2_1/recommendedTest_6_2_53.js | 2 +- 5 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 rvisc.js create mode 100644 scripts/rvisc-importRegistry.js diff --git a/csaf_2_1/recommendedTests/recommendedTest_6_2_53.js b/csaf_2_1/recommendedTests/recommendedTest_6_2_53.js index 65d7fb8d..433992dd 100644 --- a/csaf_2_1/recommendedTests/recommendedTest_6_2_53.js +++ b/csaf_2_1/recommendedTests/recommendedTest_6_2_53.js @@ -1,16 +1,10 @@ -import { createRequire } from 'module' import { Ajv } from 'ajv/dist/jtd.js' +import { entries } from '../../rvisc.js' const ajv = new Ajv() -const require = createRequire(import.meta.url) -const registry = - /** @type {{ entries: Array<{ system_name: string; text_pattern: string }> }} */ ( - // @ts-ignore — registry.json lives in the excluded csaf/ subtree - require('../../csaf/registry/id/registry.json') - ) /** @type {Array<{ system_name: string; text_pattern: RegExp }>} */ -const registeredIdSystems = registry.entries.map( +const registeredIdSystems = entries.map( (/** @type {{ system_name: string; text_pattern: string }} */ entry) => ({ system_name: entry.system_name, text_pattern: new RegExp(entry.text_pattern), diff --git a/package.json b/package.json index 372f7863..09fed786 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "mandatoryTests.js", "optionalTests.js", "README.md", + "rvisc.js", "schemaTests.js", "strip.js", "validate.js", @@ -100,6 +101,10 @@ "types": "./build/lib/shared/cwec.d.ts", "import": "./lib/shared/cwec.js" }, + "./rvisc.js": { + "types": "./build/rvisc.d.ts", + "import": "./rvisc.js" + }, "./lib/shared/cvss2.js": { "types": "./build/lib/shared/cvss2.d.ts", "import": "./lib/shared/cvss2.js" diff --git a/rvisc.js b/rvisc.js new file mode 100644 index 00000000..cb992c1e --- /dev/null +++ b/rvisc.js @@ -0,0 +1,32 @@ +const rvisc = { + $schema: + 'https://raw.githubusercontent.com/oasis-tcs/csaf/master/registry/id/schema/registry.schema.json', + entries: [ + { + common_name: 'OASIS Open CSAF TC GitHub Issues', + example_identifiers: ['#1217'], + published: '2026-01-28T17:45:00Z', + summary: + 'Contains identifiers for issues in the official standard repository of the OASIS Open CSAF TC.', + system_name: 'https://github.com/oasis-tcs/csaf', + text_pattern: '^#[1-9]\\d*$', + updated: '2026-01-28T17:45:00Z', + }, + { + common_name: 'EUVD IDs', + example_identifiers: ['EUVD-2026-4660'], + published: '2026-01-28T18:00:00Z', + summary: + 'Contains identifiers from the European Vulnerability Database (EUVD).', + system_name: 'https://euvd.enisa.europa.eu', + text_pattern: '^EUVD-[1-9][0-9]{3}-[0-9]{4,}$', + updated: '2026-02-06T15:35:00Z', + }, + ], + last_updated: '2026-02-06T15:35:00Z', + registry_version: 1, +} + +export default rvisc + +export const entries = rvisc.entries diff --git a/scripts/rvisc-importRegistry.js b/scripts/rvisc-importRegistry.js new file mode 100644 index 00000000..0ebf8464 --- /dev/null +++ b/scripts/rvisc-importRegistry.js @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +import { writeFile, readFile } from 'node:fs/promises' +import prettier from 'prettier' + +/** + * Converts the RVISC registry (`csaf/registry/id/registry.json`, part of + * the `csaf/` git subtree and excluded from the npm package) into a plain + * ESM module (`rvisc.js`) that works in Node and in the browser. + * + * Run again after `csaf/registry/id/registry.json` was updated: + * + * node scripts/rvisc-importRegistry.js + */ + +const REGISTRY_FILE = 'csaf/registry/id/registry.json' +const OUTPUT_FILE = 'rvisc.js' + +const json = JSON.parse(await readFile(REGISTRY_FILE, 'utf-8')) + +await writeFile( + OUTPUT_FILE, + prettier.format( + `const rvisc = (${JSON.stringify( + json + )})\n\nexport default rvisc\n\nexport const entries = rvisc.entries`, + { + ...(await prettier.resolveConfig(OUTPUT_FILE)), + filepath: OUTPUT_FILE, + } + ) +) diff --git a/tests/csaf_2_1/recommendedTest_6_2_53.js b/tests/csaf_2_1/recommendedTest_6_2_53.js index 9d767128..4aaa3c59 100644 --- a/tests/csaf_2_1/recommendedTest_6_2_53.js +++ b/tests/csaf_2_1/recommendedTest_6_2_53.js @@ -5,7 +5,7 @@ describe('recommendedTest_6_2_53', function () { it('only runs on relevant documents', function () { assert.equal(recommendedTest_6_2_53({}).warnings.length, 0) }) - // + it('does not warn when ids are absent', function () { assert.equal( recommendedTest_6_2_53({ vulnerabilities: [{}] }).warnings.length, From e6a7f24deba518a147755690a4df7cc96090ae10 Mon Sep 17 00:00:00 2001 From: bendo-eXX Date: Wed, 29 Jul 2026 15:35:27 +0200 Subject: [PATCH 2/2] feat(CSAF2.1): add recommendedTest_6_2_53.js --- .../recommendedTests/recommendedTest_6_2_53.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/csaf_2_1/recommendedTests/recommendedTest_6_2_53.js b/csaf_2_1/recommendedTests/recommendedTest_6_2_53.js index 433992dd..046a5ed7 100644 --- a/csaf_2_1/recommendedTests/recommendedTest_6_2_53.js +++ b/csaf_2_1/recommendedTests/recommendedTest_6_2_53.js @@ -46,18 +46,18 @@ const validate = ajv.compile(inputSchema) /** @typedef {InputSchema['vulnerabilities'][number]} Vulnerability */ /** - * For each item in vulnerabilities[].ids[] that has a registered system_name, - * it is tested that the text matches the text_pattern from the RVISC registry. + * This implements the recommended test 6.2.53 of the CSAF 2.1 standard. * * @param {unknown} doc */ export function recommendedTest_6_2_53(doc) { - /** @type {Array<{ message: string; instancePath: string }>} */ - const warnings = [] - const context = { warnings } + const ctx = { + warnings: + /** @type {Array<{ instancePath: string; message: string }>} */ ([]), + } if (!validate(doc)) { - return context + return ctx } /** @type {Array} */ @@ -73,7 +73,7 @@ export function recommendedTest_6_2_53(doc) { if (!registeredSystem) return if (!registeredSystem.text_pattern.test(id.text)) { - warnings.push({ + ctx.warnings.push({ instancePath: `/vulnerabilities/${vulnIndex}/ids/${idIndex}/text`, message: `the text does not match the text_pattern of the registered ID system "${id.system_name}"`, }) @@ -81,5 +81,5 @@ export function recommendedTest_6_2_53(doc) { }) }) - return context + return ctx }