Skip to content

Commit 03e078e

Browse files
feat: add mandatory test 6.1.47
1 parent 612c1e9 commit 03e078e

File tree

4 files changed

+116
-1
lines changed

4 files changed

+116
-1
lines changed

csaf_2_1/mandatoryTests.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,4 @@ export { mandatoryTest_6_1_38 } from './mandatoryTests/mandatoryTests_6_1_38.js'
4747
export { mandatoryTest_6_1_39 } from './mandatoryTests/mandatoryTest_6_1_39.js'
4848
export { mandatoryTest_6_1_40 } from './mandatoryTests/mandatoryTest_6_1_40.js'
4949
export { mandatoryTest_6_1_41 } from './mandatoryTests/mandatoryTest_6_1_41.js'
50+
export { mandatoryTest_6_1_47 } from './mandatoryTests/mandatoryTest_6_1_47.js'
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import Ajv from 'ajv/dist/jtd.js'
2+
3+
const ajv = new Ajv()
4+
5+
/*
6+
This is the jtd schema that needs to match the input document so that the
7+
test is activated. If this schema doesn't match it normally means that the input
8+
document does not validate against the csaf json schema or optional fields that
9+
the test checks are not present.
10+
*/
11+
const inputSchema = /** @type {const} */ ({
12+
additionalProperties: true,
13+
properties: {
14+
document: {
15+
additionalProperties: true,
16+
properties: {
17+
tracking: {
18+
additionalProperties: true,
19+
properties: {
20+
id: { type: 'string' },
21+
},
22+
},
23+
},
24+
},
25+
vulnerabilities: {
26+
elements: {
27+
additionalProperties: true,
28+
optionalProperties: {
29+
cve: { type: 'string' },
30+
ids: {
31+
elements: {
32+
additionalProperties: true,
33+
optionalProperties: {
34+
text: { type: 'string' },
35+
},
36+
},
37+
},
38+
metrics: {
39+
elements: {
40+
additionalProperties: true,
41+
optionalProperties: {
42+
content: {
43+
additionalProperties: true,
44+
properties: {
45+
ssvc_v1: {
46+
additionalProperties: true,
47+
properties: {
48+
id: { type: 'string' },
49+
},
50+
},
51+
},
52+
},
53+
},
54+
},
55+
},
56+
},
57+
},
58+
},
59+
},
60+
})
61+
62+
const validateInput = ajv.compile(inputSchema)
63+
64+
/**
65+
* This implements the mandatory test 6.1.47 of the CSAF 2.1 standard.
66+
*
67+
* @param {any} doc
68+
*/
69+
export function mandatoryTest_6_1_47(doc) {
70+
const ctx = {
71+
errors:
72+
/** @type {Array<{ instancePath: string; message: string }>} */ ([]),
73+
isValid: true,
74+
}
75+
76+
if (!validateInput(doc)) {
77+
return ctx
78+
}
79+
80+
doc.vulnerabilities.forEach((vulnerability, vulnerabilityIndex) => {
81+
vulnerability.metrics?.forEach((metric, metricIndex) => {
82+
const ssvcId = metric.content?.ssvc_v1.id
83+
if (ssvcId === doc.document.tracking.id) {
84+
if (doc.vulnerabilities.length > 1) {
85+
ctx.isValid = false
86+
ctx.errors.push({
87+
instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/id`,
88+
message:
89+
'the ssvc id equals the `document/tracking/id` even the csaf document has multiple vulnerabilities',
90+
})
91+
}
92+
} else {
93+
const idTexts = vulnerability.ids?.map((id) => id.text)
94+
if (ssvcId !== vulnerability.cve && !idTexts?.includes(ssvcId)) {
95+
ctx.isValid = false
96+
ctx.errors.push({
97+
instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/id`,
98+
message:
99+
'the ssvc id does neither match the `cve` nor it matches the `text` of any item in the `ids` array',
100+
})
101+
}
102+
}
103+
})
104+
})
105+
106+
return ctx
107+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import assert from 'node:assert/strict'
2+
import { mandatoryTest_6_1_47 } from '../../csaf_2_1/mandatoryTests/mandatoryTest_6_1_47.js'
3+
4+
describe('mandatoryTest_6_1_47', function () {
5+
it('only runs on relevant documents', function () {
6+
assert.equal(mandatoryTest_6_1_47({ document: 'mydoc' }).isValid, true)
7+
})
8+
})

tests/csaf_2_1/oasis.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ const excluded = [
3434
'6.1.44',
3535
'6.1.45',
3636
'6.1.46',
37-
'6.1.47',
3837
'6.1.48',
3938
'6.1.49',
4039
'6.1.50',

0 commit comments

Comments
 (0)