From cb16a936ba57c793b27426442189ac7f18eaedf9 Mon Sep 17 00:00:00 2001 From: chirschenberger Date: Tue, 24 Jun 2025 14:04:57 +0200 Subject: [PATCH 01/10] feat: add mandatory test 6.1.47 --- csaf_2_1/mandatoryTests.js | 3 +- .../mandatoryTests/mandatoryTest_6_1_47.js | 107 ++++++++++++++++++ tests/csaf_2_1/mandatoryTest_6_1_47.js | 8 ++ tests/csaf_2_1/oasis.js | 1 - 4 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js create mode 100644 tests/csaf_2_1/mandatoryTest_6_1_47.js diff --git a/csaf_2_1/mandatoryTests.js b/csaf_2_1/mandatoryTests.js index d5a7706b..6d09e7a1 100644 --- a/csaf_2_1/mandatoryTests.js +++ b/csaf_2_1/mandatoryTests.js @@ -59,4 +59,5 @@ export { mandatoryTest_6_1_40 } from './mandatoryTests/mandatoryTest_6_1_40.js' export { mandatoryTest_6_1_41 } from './mandatoryTests/mandatoryTest_6_1_41.js' export { mandatoryTest_6_1_43 } from './mandatoryTests/mandatoryTest_6_1_43.js' export { mandatoryTest_6_1_45 } from './mandatoryTests/mandatoryTest_6_1_45.js' -export { mandatoryTest_6_1_52 } from './mandatoryTests/mandatoryTest_6_1_52.js' +export { mandatoryTest_6_1_47 } from './mandatoryTests/mandatoryTest_6_1_47.js' +export { mandatoryTest_6_1_52 } from './mandatoryTests/mandatoryTest_6_1_52.js' \ No newline at end of file diff --git a/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js new file mode 100644 index 00000000..b68a7494 --- /dev/null +++ b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js @@ -0,0 +1,107 @@ +import Ajv from 'ajv/dist/jtd.js' + +const ajv = new Ajv() + +/* + 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: { + document: { + additionalProperties: true, + properties: { + tracking: { + additionalProperties: true, + properties: { + id: { type: 'string' }, + }, + }, + }, + }, + vulnerabilities: { + elements: { + additionalProperties: true, + optionalProperties: { + cve: { type: 'string' }, + ids: { + elements: { + additionalProperties: true, + optionalProperties: { + text: { type: 'string' }, + }, + }, + }, + metrics: { + elements: { + additionalProperties: true, + optionalProperties: { + content: { + additionalProperties: true, + properties: { + ssvc_v1: { + additionalProperties: true, + properties: { + id: { type: 'string' }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, +}) + +const validateInput = ajv.compile(inputSchema) + +/** + * This implements the mandatory test 6.1.47 of the CSAF 2.1 standard. + * + * @param {any} doc + */ +export function mandatoryTest_6_1_47(doc) { + const ctx = { + errors: + /** @type {Array<{ instancePath: string; message: string }>} */ ([]), + isValid: true, + } + + if (!validateInput(doc)) { + return ctx + } + + doc.vulnerabilities.forEach((vulnerability, vulnerabilityIndex) => { + vulnerability.metrics?.forEach((metric, metricIndex) => { + const ssvcId = metric.content?.ssvc_v1.id + if (ssvcId === doc.document.tracking.id) { + if (doc.vulnerabilities.length > 1) { + ctx.isValid = false + ctx.errors.push({ + instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/id`, + message: + 'the ssvc id equals the `document/tracking/id` even the csaf document has multiple vulnerabilities', + }) + } + } else { + const idTexts = vulnerability.ids?.map((id) => id.text) + if (ssvcId !== vulnerability.cve && !idTexts?.includes(ssvcId)) { + ctx.isValid = false + ctx.errors.push({ + instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/id`, + message: + 'the ssvc id does neither match the `cve` nor it matches the `text` of any item in the `ids` array', + }) + } + } + }) + }) + + return ctx +} diff --git a/tests/csaf_2_1/mandatoryTest_6_1_47.js b/tests/csaf_2_1/mandatoryTest_6_1_47.js new file mode 100644 index 00000000..400897c9 --- /dev/null +++ b/tests/csaf_2_1/mandatoryTest_6_1_47.js @@ -0,0 +1,8 @@ +import assert from 'node:assert/strict' +import { mandatoryTest_6_1_47 } from '../../csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js' + +describe('mandatoryTest_6_1_47', function () { + it('only runs on relevant documents', function () { + assert.equal(mandatoryTest_6_1_47({ document: 'mydoc' }).isValid, true) + }) +}) diff --git a/tests/csaf_2_1/oasis.js b/tests/csaf_2_1/oasis.js index 0e9d2e60..b4c46ad2 100644 --- a/tests/csaf_2_1/oasis.js +++ b/tests/csaf_2_1/oasis.js @@ -23,7 +23,6 @@ const excluded = [ '6.1.42', '6.1.44', '6.1.46', - '6.1.47', '6.1.48', '6.1.49', '6.1.50', From bf3ed993340dbc5714f2ef7cac17086f47a8ab28 Mon Sep 17 00:00:00 2001 From: chirschenberger Date: Tue, 24 Jun 2025 14:23:27 +0200 Subject: [PATCH 02/10] docs: update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6f4f9297..e740e1a4 100644 --- a/README.md +++ b/README.md @@ -317,7 +317,6 @@ The following tests are not yet implemented and therefore missing: - Mandatory Test 6.1.42 - Mandatory Test 6.1.44 - Mandatory Test 6.1.46 -- Mandatory Test 6.1.47 - Mandatory Test 6.1.48 - Mandatory Test 6.1.49 - Mandatory Test 6.1.50 @@ -434,6 +433,7 @@ export const mandatoryTest_6_1_40: DocumentTest export const mandatoryTest_6_1_41: DocumentTest export const mandatoryTest_6_1_43: DocumentTest export const mandatoryTest_6_1_45: DocumentTest +export const mandatoryTest_6_1_47: DocumentTest export const mandatoryTest_6_1_52: DocumentTest ``` From 6e509a5ec7fafff83bd4a1c7b05be5a70725856b Mon Sep 17 00:00:00 2001 From: chirschenberger Date: Tue, 24 Jun 2025 15:37:05 +0200 Subject: [PATCH 03/10] refactor: change string literals in error messages --- csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js index b68a7494..1a3ead91 100644 --- a/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js +++ b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js @@ -85,8 +85,8 @@ export function mandatoryTest_6_1_47(doc) { ctx.isValid = false ctx.errors.push({ instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/id`, - message: - 'the ssvc id equals the `document/tracking/id` even the csaf document has multiple vulnerabilities', + message: `the ssvc id equals the 'document/tracking/id' + even the csaf document has multiple vulnerabilities `, }) } } else { @@ -95,8 +95,8 @@ export function mandatoryTest_6_1_47(doc) { ctx.isValid = false ctx.errors.push({ instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/id`, - message: - 'the ssvc id does neither match the `cve` nor it matches the `text` of any item in the `ids` array', + message: `the ssvc id does neither match the 'cve' + nor it matches the 'text' of any item in the 'ids' array`, }) } } From 009103eff5b4ece59e6f0cf28ecfb295c093e115 Mon Sep 17 00:00:00 2001 From: chirschenberger Date: Tue, 24 Jun 2025 17:16:38 +0200 Subject: [PATCH 04/10] feat: change ssvc_v1 property to optionalProperty in inputSchema --- .../mandatoryTests/mandatoryTest_6_1_47.js | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js index 1a3ead91..0a99a2a8 100644 --- a/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js +++ b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js @@ -41,7 +41,7 @@ const inputSchema = /** @type {const} */ ({ optionalProperties: { content: { additionalProperties: true, - properties: { + optionalProperties: { ssvc_v1: { additionalProperties: true, properties: { @@ -79,25 +79,27 @@ export function mandatoryTest_6_1_47(doc) { doc.vulnerabilities.forEach((vulnerability, vulnerabilityIndex) => { vulnerability.metrics?.forEach((metric, metricIndex) => { - const ssvcId = metric.content?.ssvc_v1.id - if (ssvcId === doc.document.tracking.id) { - if (doc.vulnerabilities.length > 1) { - ctx.isValid = false - ctx.errors.push({ - instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/id`, - message: `the ssvc id equals the 'document/tracking/id' + if (metric.content?.ssvc_v1) { + const ssvcId = metric.content.ssvc_v1.id + if (ssvcId === doc.document.tracking.id) { + if (doc.vulnerabilities.length > 1) { + ctx.isValid = false + ctx.errors.push({ + instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/id`, + message: `the ssvc id equals the 'document/tracking/id' even the csaf document has multiple vulnerabilities `, - }) - } - } else { - const idTexts = vulnerability.ids?.map((id) => id.text) - if (ssvcId !== vulnerability.cve && !idTexts?.includes(ssvcId)) { - ctx.isValid = false - ctx.errors.push({ - instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/id`, - message: `the ssvc id does neither match the 'cve' + }) + } + } else { + const idTexts = vulnerability.ids?.map((id) => id.text) + if (ssvcId !== vulnerability.cve && !idTexts?.includes(ssvcId)) { + ctx.isValid = false + ctx.errors.push({ + instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/id`, + message: `the ssvc id does neither match the 'cve' nor it matches the 'text' of any item in the 'ids' array`, - }) + }) + } } } }) From ce2b50fb173ec83d772ffb1d3edd0b12f2cc98af Mon Sep 17 00:00:00 2001 From: chirschenberger Date: Wed, 25 Jun 2025 13:54:29 +0200 Subject: [PATCH 05/10] refactor: split error messages and concatenate them to avoid line breaks as well as too long LOC --- csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js index 0a99a2a8..952291cf 100644 --- a/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js +++ b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js @@ -86,8 +86,9 @@ export function mandatoryTest_6_1_47(doc) { ctx.isValid = false ctx.errors.push({ instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/id`, - message: `the ssvc id equals the 'document/tracking/id' - even the csaf document has multiple vulnerabilities `, + message: + `the ssvc id equals the 'document/tracking/id' ` + + `even the csaf document has multiple vulnerabilities `, }) } } else { @@ -96,8 +97,9 @@ export function mandatoryTest_6_1_47(doc) { ctx.isValid = false ctx.errors.push({ instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/id`, - message: `the ssvc id does neither match the 'cve' - nor it matches the 'text' of any item in the 'ids' array`, + message: + `the ssvc id does neither match the 'cve' ` + + `nor it matches the 'text' of any item in the 'ids' array`, }) } } From 21e6351c5eb37fed3e0a51321196b5291d0622cc Mon Sep 17 00:00:00 2001 From: chirschenberger Date: Wed, 25 Jun 2025 14:25:23 +0200 Subject: [PATCH 06/10] feat: add test for input schema --- tests/csaf_2_1/mandatoryTest_6_1_47.js | 36 ++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/csaf_2_1/mandatoryTest_6_1_47.js b/tests/csaf_2_1/mandatoryTest_6_1_47.js index 400897c9..71df6be4 100644 --- a/tests/csaf_2_1/mandatoryTest_6_1_47.js +++ b/tests/csaf_2_1/mandatoryTest_6_1_47.js @@ -1,8 +1,44 @@ import assert from 'node:assert/strict' import { mandatoryTest_6_1_47 } from '../../csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js' +import { expect } from 'chai' + +const validInputSchemaTestWithEmptyVulnerability6_1_47 = { + vulnerabilities: [ + {}, // even this vulnerability is empty, the test should not fail due to the inputSchema + { + cve: 'CVE-1900-0001', + metrics: [ + { + content: { + ssvc_v1: { + id: 'CVE-1900-0001', + schemaVersion: '1-0-1', + selections: [ + { + name: 'Exploitation', + namespace: 'ssvc', + values: ['None'], + version: '1.1.0', + }, + ], + timestamp: '2024-01-24T10:00:00.000Z', + }, + }, + products: ['CSAFPID-9080700'], + }, + ], + }, + ], +} describe('mandatoryTest_6_1_47', function () { it('only runs on relevant documents', function () { assert.equal(mandatoryTest_6_1_47({ document: 'mydoc' }).isValid, true) }) + it('test input schema with empty json object in vulnerabilities', async function () { + const result = mandatoryTest_6_1_47( + validInputSchemaTestWithEmptyVulnerability6_1_47 + ) + expect(result.errors.length).to.eq(0) + }) }) From b0977a76e0db1a917fb393b40a8fac12ffda0aea Mon Sep 17 00:00:00 2001 From: chirschenberger Date: Thu, 26 Jun 2025 13:07:28 +0200 Subject: [PATCH 07/10] feat: change some properties to optionalProperties and adapt inputSchema test accordingly --- csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js | 8 ++++---- tests/csaf_2_1/mandatoryTest_6_1_47.js | 11 ++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js index 952291cf..05569a11 100644 --- a/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js +++ b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js @@ -13,10 +13,10 @@ const inputSchema = /** @type {const} */ ({ properties: { document: { additionalProperties: true, - properties: { + optionalProperties: { tracking: { additionalProperties: true, - properties: { + optionalProperties: { id: { type: 'string' }, }, }, @@ -44,7 +44,7 @@ const inputSchema = /** @type {const} */ ({ optionalProperties: { ssvc_v1: { additionalProperties: true, - properties: { + optionalProperties: { id: { type: 'string' }, }, }, @@ -81,7 +81,7 @@ export function mandatoryTest_6_1_47(doc) { vulnerability.metrics?.forEach((metric, metricIndex) => { if (metric.content?.ssvc_v1) { const ssvcId = metric.content.ssvc_v1.id - if (ssvcId === doc.document.tracking.id) { + if (ssvcId === doc.document.tracking?.id) { if (doc.vulnerabilities.length > 1) { ctx.isValid = false ctx.errors.push({ diff --git a/tests/csaf_2_1/mandatoryTest_6_1_47.js b/tests/csaf_2_1/mandatoryTest_6_1_47.js index 71df6be4..4ff85765 100644 --- a/tests/csaf_2_1/mandatoryTest_6_1_47.js +++ b/tests/csaf_2_1/mandatoryTest_6_1_47.js @@ -2,16 +2,17 @@ import assert from 'node:assert/strict' import { mandatoryTest_6_1_47 } from '../../csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js' import { expect } from 'chai' -const validInputSchemaTestWithEmptyVulnerability6_1_47 = { +const failingInputSchemaTestWithEmptyVulnerability6_1_47 = { + document: {}, vulnerabilities: [ - {}, // even this vulnerability is empty, the test should not fail due to the inputSchema + {}, // even this vulnerability is empty, the test should run { cve: 'CVE-1900-0001', metrics: [ { content: { ssvc_v1: { - id: 'CVE-1900-0001', + id: 'CVE-1900-0002', schemaVersion: '1-0-1', selections: [ { @@ -37,8 +38,8 @@ describe('mandatoryTest_6_1_47', function () { }) it('test input schema with empty json object in vulnerabilities', async function () { const result = mandatoryTest_6_1_47( - validInputSchemaTestWithEmptyVulnerability6_1_47 + failingInputSchemaTestWithEmptyVulnerability6_1_47 ) - expect(result.errors.length).to.eq(0) + expect(result.errors.length).to.eq(1) }) }) From 7c39e5b8455d470d2c5ffaee0fab427d34937593 Mon Sep 17 00:00:00 2001 From: chirschenberger Date: Wed, 10 Sep 2025 16:15:44 +0200 Subject: [PATCH 08/10] feat: adapt mandatory test 6.1.47 --- .../mandatoryTests/mandatoryTest_6_1_47.js | 36 +++++++++---------- tests/csaf_2_1/mandatoryTest_6_1_47.js | 14 +++++--- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js index 05569a11..95b0c6e1 100644 --- a/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js +++ b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js @@ -42,10 +42,10 @@ const inputSchema = /** @type {const} */ ({ content: { additionalProperties: true, optionalProperties: { - ssvc_v1: { + ssvc_v2: { additionalProperties: true, optionalProperties: { - id: { type: 'string' }, + target_ids: { elements: { type: 'string' } }, }, }, }, @@ -79,30 +79,30 @@ export function mandatoryTest_6_1_47(doc) { doc.vulnerabilities.forEach((vulnerability, vulnerabilityIndex) => { vulnerability.metrics?.forEach((metric, metricIndex) => { - if (metric.content?.ssvc_v1) { - const ssvcId = metric.content.ssvc_v1.id - if (ssvcId === doc.document.tracking?.id) { - if (doc.vulnerabilities.length > 1) { - ctx.isValid = false - ctx.errors.push({ - instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/id`, - message: - `the ssvc id equals the 'document/tracking/id' ` + - `even the csaf document has multiple vulnerabilities `, - }) + if (metric.content?.ssvc_v2) { + metric.content.ssvc_v2.target_ids?.forEach((ssvcId, ssvcIdIndex) => { + if (ssvcId === doc.document.tracking?.id) { + if (doc.vulnerabilities.length > 1) { + ctx.isValid = false + ctx.errors.push({ + instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v2/${ssvcIdIndex}`, + message: + `the ssvc id equals the "document/tracking/id" ` + + `even the csaf document has multiple vulnerabilities `, + }) + } } - } else { const idTexts = vulnerability.ids?.map((id) => id.text) if (ssvcId !== vulnerability.cve && !idTexts?.includes(ssvcId)) { ctx.isValid = false ctx.errors.push({ - instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/id`, + instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v2/${ssvcIdIndex}`, message: - `the ssvc id does neither match the 'cve' ` + - `nor it matches the 'text' of any item in the 'ids' array`, + `the ssvc id does neither match the "cve" ` + + `nor it matches the "text" of any item in the "ids" array`, }) } - } + }) } }) }) diff --git a/tests/csaf_2_1/mandatoryTest_6_1_47.js b/tests/csaf_2_1/mandatoryTest_6_1_47.js index 4ff85765..9f2ebd85 100644 --- a/tests/csaf_2_1/mandatoryTest_6_1_47.js +++ b/tests/csaf_2_1/mandatoryTest_6_1_47.js @@ -11,17 +11,21 @@ const failingInputSchemaTestWithEmptyVulnerability6_1_47 = { metrics: [ { content: { - ssvc_v1: { - id: 'CVE-1900-0002', - schemaVersion: '1-0-1', + ssvc_v2: { + schemaVersion: '2.0.0', selections: [ { - name: 'Exploitation', + key: 'E', namespace: 'ssvc', - values: ['None'], + values: [ + { + key: 'N', + }, + ], version: '1.1.0', }, ], + target_ids: ['CVE-1900-0002'], timestamp: '2024-01-24T10:00:00.000Z', }, }, From 118c342e3c29e142655aa7fb869ee9bcb8e153c5 Mon Sep 17 00:00:00 2001 From: chirschenberger Date: Wed, 10 Sep 2025 16:31:35 +0200 Subject: [PATCH 09/10] style: run prettier --- csaf_2_1/mandatoryTests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csaf_2_1/mandatoryTests.js b/csaf_2_1/mandatoryTests.js index 6d09e7a1..e160405c 100644 --- a/csaf_2_1/mandatoryTests.js +++ b/csaf_2_1/mandatoryTests.js @@ -60,4 +60,4 @@ export { mandatoryTest_6_1_41 } from './mandatoryTests/mandatoryTest_6_1_41.js' export { mandatoryTest_6_1_43 } from './mandatoryTests/mandatoryTest_6_1_43.js' export { mandatoryTest_6_1_45 } from './mandatoryTests/mandatoryTest_6_1_45.js' export { mandatoryTest_6_1_47 } from './mandatoryTests/mandatoryTest_6_1_47.js' -export { mandatoryTest_6_1_52 } from './mandatoryTests/mandatoryTest_6_1_52.js' \ No newline at end of file +export { mandatoryTest_6_1_52 } from './mandatoryTests/mandatoryTest_6_1_52.js' From be65c21eaa04c9034fa9b04411ddd9fe30aa3b14 Mon Sep 17 00:00:00 2001 From: chirschenberger Date: Wed, 10 Sep 2025 16:33:09 +0200 Subject: [PATCH 10/10] feat: change error message --- csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js index 95b0c6e1..10976494 100644 --- a/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js +++ b/csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js @@ -88,7 +88,7 @@ export function mandatoryTest_6_1_47(doc) { instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v2/${ssvcIdIndex}`, message: `the ssvc id equals the "document/tracking/id" ` + - `even the csaf document has multiple vulnerabilities `, + `but the csaf document has multiple vulnerabilities`, }) } }