Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,6 @@ The following tests are not yet implemented and therefore missing:
- Recommended Test 6.2.50.3
- Recommended Test 6.2.51
- Recommended Test 6.2.52
- Recommended Test 6.2.53
- Recommended Test 6.2.54.1
- Recommended Test 6.2.54.2
- Recommended Test 6.2.54.4
Expand Down Expand Up @@ -494,6 +493,7 @@ export const recommendedTest_6_2_41: DocumentTest
export const recommendedTest_6_2_43: DocumentTest
export const recommendedTest_6_2_47: DocumentTest
export const recommendedTest_6_2_48: DocumentTest
export const recommendedTest_6_2_53: DocumentTest
export const recommendedTest_6_2_54_3: DocumentTest
```

Expand Down
1 change: 1 addition & 0 deletions csaf_2_1/recommendedTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ export { recommendedTest_6_2_41 } from './recommendedTests/recommendedTest_6_2_4
export { recommendedTest_6_2_43 } from './recommendedTests/recommendedTest_6_2_43.js'
export { recommendedTest_6_2_47 } from './recommendedTests/recommendedTest_6_2_47.js'
export { recommendedTest_6_2_48 } from './recommendedTests/recommendedTest_6_2_48.js'
export { recommendedTest_6_2_53 } from './recommendedTests/recommendedTest_6_2_53.js'
export { recommendedTest_6_2_54_3 } from './recommendedTests/recommendedTest_6_2_54_3.js'
88 changes: 88 additions & 0 deletions csaf_2_1/recommendedTests/recommendedTest_6_2_53.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { Ajv } from 'ajv/dist/jtd.js'
import { entries } from '../../rvisc.js'

const ajv = new Ajv()

/** @type {Array<{ system_name: string; common_name: string; text_pattern: RegExp }>} */
const registeredIdSystems = entries.map(
(
/** @type {{ system_name: string; common_name: string; text_pattern: string }} */ entry
) => ({
Comment on lines +6 to +10

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** @type {Array<{ system_name: string; common_name: string; text_pattern: RegExp }>} */
const registeredIdSystems = entries.map(
(
/** @type {{ system_name: string; common_name: string; text_pattern: string }} */ entry
) => ({
const registeredIdSystems = entries.map(
(entry) => ({

system_name: entry.system_name,
common_name: entry.common_name,
text_pattern: new RegExp(entry.text_pattern),
})
)

/*
This is the jtd schema that needs to match the input document so that the
test is activated. If this schema doesn't match it normally means that the input
document does not validate against the csaf json schema or optional fields that
the test checks are not present.
*/
const inputSchema = /** @type {const} */ ({
additionalProperties: true,

properties: {
vulnerabilities: {
elements: {
additionalProperties: true,
optionalProperties: {
ids: {
elements: {
additionalProperties: true,
optionalProperties: {
system_name: { type: 'string' },
text: { type: 'string' },
},
},
},
},
},
},
},
})

const validate = ajv.compile(inputSchema)

/** @typedef {import('ajv/dist/jtd.js').JTDDataType<typeof inputSchema>} InputSchema */
/** @typedef {InputSchema['vulnerabilities'][number]} Vulnerability */
Comment on lines +48 to +49

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** @typedef {import('ajv/dist/jtd.js').JTDDataType<typeof inputSchema>} InputSchema */
/** @typedef {InputSchema['vulnerabilities'][number]} Vulnerability */


/**
* This implements the recommended test 6.2.53 of the CSAF 2.1 standard.
*
* @param {unknown} doc
*/
export function recommendedTest_6_2_53(doc) {
const ctx = {
warnings:
/** @type {Array<{ instancePath: string; message: string }>} */ ([]),
}

if (!validate(doc)) {
return ctx
}

/** @type {Array<Vulnerability>} */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** @type {Array<Vulnerability>} */

const vulnerabilities = doc.vulnerabilities
vulnerabilities.forEach((vulnerability, vulnIndex) => {
const ids = vulnerability.ids ?? []
ids.forEach((id, idIndex) => {
if (id.system_name === undefined || id.text === undefined) return

const registeredSystem = registeredIdSystems.find(
(entry) => entry.system_name === id.system_name
)
if (!registeredSystem) return

if (!registeredSystem.text_pattern.test(id.text)) {
ctx.warnings.push({
instancePath: `/vulnerabilities/${vulnIndex}/ids/${idIndex}/text`,
message: `the text does not match the text_pattern of the registered ID system "${registeredSystem.common_name}"`,
})
}
})
})

return ctx
}
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"mandatoryTests.js",
"optionalTests.js",
"README.md",
"rvisc.js",
"schemaTests.js",
"strip.js",
"validate.js",
Expand Down Expand Up @@ -102,6 +103,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"
Expand Down
35 changes: 35 additions & 0 deletions rvisc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// This file is generated from csaf/registry/id/registry.json by scripts/rvisc-importRegistry.js.
// Do not edit by hand.

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
32 changes: 32 additions & 0 deletions scripts/rvisc-importRegistry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env node

import { readFile, writeFile } 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(
`// This file is generated from ${REGISTRY_FILE} by scripts/rvisc-importRegistry.js.
// Do not edit by hand.\n\nconst rvisc = (${JSON.stringify(json)})\n
export default rvisc\n\nexport const entries = rvisc.entries`,
{
...(await prettier.resolveConfig(OUTPUT_FILE)),
filepath: OUTPUT_FILE,
}
)
)
1 change: 0 additions & 1 deletion tests/csaf_2_1/oasis.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const excluded = [
'6.2.50.3',
'6.2.51',
'6.2.52',
'6.2.53',
'6.2.54.1',
'6.2.54.2',
'6.2.54.4',
Expand Down
42 changes: 42 additions & 0 deletions tests/csaf_2_1/recommendedTest_6_2_53.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { recommendedTest_6_2_53 } from '../../csaf_2_1/recommendedTests/recommendedTest_6_2_53.js'

describe('recommendedTest_6_2_53', function () {
it('only runs on relevant documents', function () {
expect(recommendedTest_6_2_53({}).warnings.length).to.equal(0)
})

it('does not warn when ids are absent', function () {
expect(
recommendedTest_6_2_53({ vulnerabilities: [{}] }).warnings.length
).to.equal(0)
})

it('does not warn when text is absent', function () {
expect(
recommendedTest_6_2_53({
vulnerabilities: [
{
ids: [{ system_name: 'https://example.com' }],
},
],
}).warnings.length
).to.equal(0)
})

it('does not warn when system_name is not in the registry', function () {
expect(
recommendedTest_6_2_53({
vulnerabilities: [
{
ids: [
{
system_name: 'https://unknown-system.example.com',
text: 'some-text',
},
],
},
],
}).warnings.length
).to.equal(0)
})
})