Skip to content

Commit 2ea40f3

Browse files
feat: add optional test 6.2.23
1 parent e0bc7c3 commit 2ea40f3

File tree

4 files changed

+129
-0
lines changed

4 files changed

+129
-0
lines changed

csaf_2_1/optionalTests.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export {
2+
optionalTest_6_2_1,
3+
optionalTest_6_2_2,
4+
optionalTest_6_2_4,
5+
optionalTest_6_2_5,
6+
optionalTest_6_2_6,
7+
optionalTest_6_2_7,
8+
optionalTest_6_2_8,
9+
optionalTest_6_2_9,
10+
optionalTest_6_2_10,
11+
optionalTest_6_2_11,
12+
optionalTest_6_2_12,
13+
optionalTest_6_2_13,
14+
optionalTest_6_2_14,
15+
optionalTest_6_2_15,
16+
optionalTest_6_2_16,
17+
optionalTest_6_2_17,
18+
optionalTest_6_2_18,
19+
optionalTest_6_2_19,
20+
optionalTest_6_2_20,
21+
} from '../optionalTests.js'
22+
export { optionalTest_6_2_3 } from './optionalTests/optionalTest_6_2_3.js'
23+
export { optionalTest_6_2_23 } from './optionalTests/optionalTest_6_2_23.js'
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import Ajv from 'ajv/dist/jtd.js'
2+
import { cwecMap } from '../../lib/cwec.js'
3+
4+
const ajv = new Ajv()
5+
6+
/*
7+
This is the jtd schema that needs to match the input document so that the
8+
test is activated. If this schema doesn't match it normally means that the input
9+
document does not validate against the csaf json schema or optional fields that
10+
the test checks are not present.
11+
*/
12+
const inputSchema = /** @type {const} */ ({
13+
additionalProperties: true,
14+
properties: {
15+
vulnerabilities: {
16+
elements: {
17+
additionalProperties: true,
18+
properties: {
19+
cwes: {
20+
elements: {
21+
additionalProperties: true,
22+
properties: {},
23+
},
24+
},
25+
},
26+
},
27+
},
28+
},
29+
})
30+
31+
const validateInput = ajv.compile(inputSchema)
32+
33+
const cweSchema = /** @type {const} */ ({
34+
additionalProperties: true,
35+
properties: {
36+
id: { type: 'string' },
37+
version: { type: 'string' },
38+
name: { type: 'string' },
39+
},
40+
})
41+
42+
const validateCWE = ajv.compile(cweSchema)
43+
44+
/**
45+
* This implements the optional test 6.2.23 of the CSAF 2.1 standard.
46+
*
47+
* @param {any} doc
48+
*/
49+
export async function optionalTest_6_2_23(doc) {
50+
/** @type {Array<{ message: string; instancePath: string }>} */
51+
const warnings = []
52+
const context = { warnings }
53+
54+
if (!validateInput(doc)) {
55+
return context
56+
}
57+
58+
for (let i = 0; i < doc.vulnerabilities.length; ++i) {
59+
const vulnerability = doc.vulnerabilities[i]
60+
for (let j = 0; j < vulnerability.cwes.length; ++j) {
61+
const cwe = vulnerability.cwes.at(j)
62+
if (validateCWE(cwe)) {
63+
const cwec = cwecMap.get(cwe.version)
64+
if (!cwec) {
65+
context.warnings.push({
66+
instancePath: `/vulnerabilities/${i}/cwes/${j}/version`,
67+
message: 'no such cwe version is recognized',
68+
})
69+
continue
70+
}
71+
const entry = (await cwec()).default.weaknesses.find(
72+
(w) => w.id === cwe.id
73+
)
74+
if (!entry) {
75+
context.warnings.push({
76+
instancePath: `/vulnerabilities/${i}/cwes/${j}/id`,
77+
message: `no weakness with this id is recognized in CWE ${cwe.version}`,
78+
})
79+
continue
80+
}
81+
if (entry.status === 'Deprecated') {
82+
context.warnings.push({
83+
instancePath: `/vulnerabilities/${i}/cwes/${j}/id`,
84+
message:
85+
'the status of the weakness with the given id is deprecated',
86+
})
87+
continue
88+
}
89+
}
90+
}
91+
}
92+
93+
return context
94+
}

tests/csaf_2_1/oasis.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const excluded = [
4444
'6.2.19',
4545
'6.2.20',
4646
'6.2.21',
47+
'6.2.22',
4748
'6.2.23',
4849
'6.2.24',
4950
'6.2.25',
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import assert from 'node:assert'
2+
import { optionalTest_6_2_23 } from '../../csaf_2_1/optionalTests.js'
3+
4+
describe('optionalTest_6_2_23', function () {
5+
it('only runs on relevant documents', async function () {
6+
assert.equal(
7+
(await optionalTest_6_2_23({ vulnerabilities: 'mydoc' })).warnings.length,
8+
0
9+
)
10+
})
11+
})

0 commit comments

Comments
 (0)