diff --git a/README.md b/README.md index 2910de45..010180b5 100644 --- a/README.md +++ b/README.md @@ -320,7 +320,6 @@ The following tests are not yet implemented and therefore missing: - Mandatory Test 6.1.54 - Mandatory Test 6.1.55 - Mandatory Test 6.1.59 -- Mandatory Test 6.1.60.1 - Mandatory Test 6.1.60.2 - Mandatory Test 6.1.60.3 @@ -463,6 +462,7 @@ export const mandatoryTest_6_1_53: DocumentTest export const mandatoryTest_6_1_57: DocumentTest export const mandatoryTest_6_1_58: DocumentTest export const mandatoryTest_6_1_61: DocumentTest +export const mandatoryTest_6_1_60_1: DocumentTest ``` [(back to top)](#bsi-csaf-validator-lib) diff --git a/csaf_2_1/csafAjv.js b/csaf_2_1/csafAjv.js index 9c05c814..429f5d87 100644 --- a/csaf_2_1/csafAjv.js +++ b/csaf_2_1/csafAjv.js @@ -26,7 +26,7 @@ csafAjv.addSchema(cvss_v3_1, 'https://www.first.org/cvss/cvss-v3.1.json') csafAjv.addSchema(cvss_meta, 'https://www.first.org/cvss/meta.json') csafAjv.addSchema( content_schema, - 'https://docs.oasis-open.org/csaf/csaf/v2.1/schema/extension-metaschema.json#/$defs/content_schema_t' + 'https://docs.oasis-open.org/csaf/csaf/v2.1/schema/extension-metaschema.json' ) csafAjv.addSchema( meta_format_assertion, diff --git a/csaf_2_1/csafAjv/content_schema.js b/csaf_2_1/csafAjv/content_schema.js index a985c9bb..cdee0f62 100644 --- a/csaf_2_1/csafAjv/content_schema.js +++ b/csaf_2_1/csafAjv/content_schema.js @@ -194,7 +194,7 @@ export default { uniqueItems: true, items: { type: 'string', - enum: ['critical', 'high_value', 'informational'], + enum: ['essential', 'significant', 'supplementary'], }, }, }, diff --git a/csaf_2_1/csafAjv/extension-content.js b/csaf_2_1/csafAjv/extension-content.js index 9a79f18c..031fc052 100644 --- a/csaf_2_1/csafAjv/extension-content.js +++ b/csaf_2_1/csafAjv/extension-content.js @@ -18,7 +18,7 @@ export default { title: 'Extension Category', description: 'Holds the category of the extension content.', type: 'string', - enum: ['critical', 'high_value', 'informational'], + enum: ['essential', 'significant', 'supplementary'], }, content: { title: 'Content', diff --git a/csaf_2_1/mandatoryTests.js b/csaf_2_1/mandatoryTests.js index bf9715a3..801a2a1e 100644 --- a/csaf_2_1/mandatoryTests.js +++ b/csaf_2_1/mandatoryTests.js @@ -65,6 +65,7 @@ export { mandatoryTest_6_1_45 } from './mandatoryTests/mandatoryTest_6_1_45.js' export { mandatoryTest_6_1_46 } from './mandatoryTests/mandatoryTest_6_1_46.js' export { mandatoryTest_6_1_51 } from './mandatoryTests/mandatoryTest_6_1_51.js' export { mandatoryTest_6_1_52 } from './mandatoryTests/mandatoryTest_6_1_52.js' +export { mandatoryTest_6_1_60_1 } from './mandatoryTests/mandatoryTest_6_1_60_1.js' export { mandatoryTest_6_1_53 } from './mandatoryTests/mandatoryTest_6_1_53.js' export { mandatoryTest_6_1_57 } from './mandatoryTests/mandatoryTest_6_1_57.js' export { mandatoryTest_6_1_58 } from './mandatoryTests/mandatoryTest_6_1_58.js' diff --git a/csaf_2_1/mandatoryTests/mandatoryTest_6_1_60_1.js b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_60_1.js new file mode 100644 index 00000000..65daa2c3 --- /dev/null +++ b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_60_1.js @@ -0,0 +1,49 @@ +import { walkPath } from '../../lib/walkPaths.js' +import csafAjv from '../csafAjv.js' + +const X_EXTENSIONS_PATHS /** @type {string[]} */ = [ + '/document/x_extensions[]', + '/product_tree/branches[*]/product/x_extensions[]', + '/product_tree/full_product_names[]/x_extensions[]', + '/product_tree/product_paths[]/full_product_name/x_extensions[]', + '/vulnerabilities[]/metrics[]/content/x_extensions[]', + '/vulnerabilities[]/x_extensions[]', + '/x_extensions[]', +] + +const validateExtensionContent = csafAjv.getSchema( + 'https://docs.oasis-open.org/csaf/csaf/v2.1/schema/extension-content.json' +) + +/** + * This implements the mandatory test 6.1.60.1 of the CSAF 2.1 standard. + * + * + * @param {unknown} doc + */ +export async function mandatoryTest_6_1_60_1(doc) { + const ctx = { + errors: + /** @type {Array<{ instancePath: string; message: string }>} */ ([]), + isValid: true, + } + + if (typeof validateExtensionContent !== 'function') return ctx + + for (const path of X_EXTENSIONS_PATHS) { + await walkPath(doc, path, async (instancePath, value) => { + if (!validateExtensionContent(value)) { + ctx.isValid = false + const ajvErrors = validateExtensionContent.errors ?? [] + ajvErrors.forEach((err) => { + ctx.errors.push({ + instancePath: `${instancePath}${err.instancePath}`, + message: err.message ?? 'invalid extension content', + }) + }) + } + }) + } + + return ctx +} diff --git a/tests/csaf_2_1/mandatoryTest_6_1_60_1.js b/tests/csaf_2_1/mandatoryTest_6_1_60_1.js new file mode 100644 index 00000000..4d99a1b3 --- /dev/null +++ b/tests/csaf_2_1/mandatoryTest_6_1_60_1.js @@ -0,0 +1,24 @@ +import assert from 'node:assert/strict' +import csafAjv from '../../csaf_2_1/csafAjv.js' + +describe('mandatoryTest_6_1_60_1', function () { + it('returns a valid empty result when the extension-content schema is unavailable', async function () { + const originalGetSchema = csafAjv.getSchema.bind(csafAjv) + csafAjv.getSchema = () => undefined + + let result + try { + const freshModule = await import( + '../../csaf_2_1/mandatoryTests/mandatoryTest_6_1_60_1.js?guard-test=' + + Date.now() + ) + result = await freshModule.mandatoryTest_6_1_60_1({ + x_extensions: { foo: 'bar' }, + }) + } finally { + csafAjv.getSchema = originalGetSchema + } + + assert.deepEqual(result, { errors: [], isValid: true }) + }) +}) diff --git a/tests/csaf_2_1/oasis.js b/tests/csaf_2_1/oasis.js index f6b8d926..abc93671 100644 --- a/tests/csaf_2_1/oasis.js +++ b/tests/csaf_2_1/oasis.js @@ -22,7 +22,6 @@ const excluded = [ '6.1.55', '6.1.56', '6.1.59', - '6.1.60.1', '6.1.60.2', '6.1.60.3', '6.2.11',