diff --git a/csaf_2_1/informativeTests.js b/csaf_2_1/informativeTests.js index d5ec4ced..12269510 100644 --- a/csaf_2_1/informativeTests.js +++ b/csaf_2_1/informativeTests.js @@ -1,5 +1,4 @@ export { - informativeTest_6_3_2, informativeTest_6_3_3, informativeTest_6_3_5, informativeTest_6_3_6, @@ -11,3 +10,4 @@ export { } from '../informativeTests.js' export { informativeTest_6_3_1 } from './informativeTests/informativeTest_6_3_1.js' export { informativeTest_6_3_4 } from './informativeTests/informativeTest_6_3_4.js' +export { informativeTest_6_3_2 } from './informativeTests/informativeTest_6_3_2.js' diff --git a/csaf_2_1/informativeTests/informativeTest_6_3_2.js b/csaf_2_1/informativeTests/informativeTest_6_3_2.js new file mode 100644 index 00000000..0861d54b --- /dev/null +++ b/csaf_2_1/informativeTests/informativeTest_6_3_2.js @@ -0,0 +1,72 @@ +import Ajv from 'ajv/dist/jtd.js' + +const ajv = new Ajv() + +const inputSchema = /** @type {const} */ ({ + additionalProperties: true, + properties: { + vulnerabilities: { + elements: { + additionalProperties: true, + optionalProperties: { + metrics: { + elements: { + additionalProperties: true, + optionalProperties: { + content: { + additionalProperties: true, + optionalProperties: { + cvss_v3: { + additionalProperties: true, + optionalProperties: { + version: { type: 'string' }, + vectorString: { type: 'string' }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, +}) + +const validateInput = ajv.compile(inputSchema) + +/** + * For each item in the list of metrics which contains the cvss_v3 object under + * content it MUST be tested that CVSS v3.0 is not used. + * @param {unknown} doc + * @returns + */ +export function informativeTest_6_3_2(doc) { + const ctx = { + infos: /** @type {Array<{ message: string; instancePath: string }>} */ ([]), + } + + if (!validateInput(doc)) { + return ctx + } + + doc.vulnerabilities.forEach((vulnerability, vulnerabilityIndex) => { + const metrics = vulnerability.metrics + metrics?.forEach((metric, metricIndex) => { + if (metric.content?.cvss_v3) { + if ( + metric.content.cvss_v3.version === '3.0' || + metric.content.cvss_v3.vectorString?.startsWith('CVSS:3.0') + ) { + ctx.infos.push({ + instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/cvss_v3/version`, + message: 'It is recommended to upgrade to CVSS v3.1.', + }) + } + } + }) + }) + + return ctx +} diff --git a/tests/csaf_2_1/informativeTest_6_3_2.js b/tests/csaf_2_1/informativeTest_6_3_2.js new file mode 100644 index 00000000..aa04d939 --- /dev/null +++ b/tests/csaf_2_1/informativeTest_6_3_2.js @@ -0,0 +1,30 @@ +import assert from 'node:assert/strict' +import { informativeTest_6_3_2 } from '../../csaf_2_1/informativeTests/informativeTest_6_3_2.js' + +describe('informativeTest_6_3_2', function () { + it('only runs on relevant documents', function () { + assert.equal(informativeTest_6_3_2({ document: 'mydoc' }).infos.length, 0) + }) + it('test input schema with not considered json object in vulnerabilities', function () { + assert.equal( + informativeTest_6_3_2({ + document: {}, + vulnerabilities: [ + {}, + { + metrics: [ + { + content: { + cvss_v3: { + version: '3.0', + }, + }, + }, + ], + }, + ], + }).infos.length, + 1 + ) + }) +}) diff --git a/tests/csaf_2_1/oasis.js b/tests/csaf_2_1/oasis.js index 6fb44c13..62d6bd4d 100644 --- a/tests/csaf_2_1/oasis.js +++ b/tests/csaf_2_1/oasis.js @@ -71,7 +71,6 @@ const excluded = [ '6.2.44', '6.2.45', '6.2.46', - '6.3.2', '6.3.14', '6.3.15', '6.3.12',