Skip to content

Commit 5fc5153

Browse files
Merge pull request #254 from secvisogram/196-csaf-2.1_optional_test_6.2.25
196 csaf 2.1 optional test 6.2.25
2 parents 1085486 + de09415 commit 5fc5153

File tree

5 files changed

+122
-2
lines changed

5 files changed

+122
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,6 @@ The following tests are not yet implemented and therefore missing:
332332
- Recommended Test 6.2.20
333333
- Recommended Test 6.2.21
334334
- Recommended Test 6.2.24
335-
- Recommended Test 6.2.25
336335
- Recommended Test 6.2.26
337336
- Recommended Test 6.2.27
338337
- Recommended Test 6.2.28
@@ -461,6 +460,7 @@ export const recommendedTest_6_2_17: DocumentTest
461460
export const recommendedTest_6_2_18: DocumentTest
462461
export const recommendedTest_6_2_22: DocumentTest
463462
export const recommendedTest_6_2_23: DocumentTest
463+
export const recommendedTest_6_2_25: DocumentTest
464464
```
465465
466466
[(back to top)](#bsi-csaf-validator-lib)

csaf_2_1/recommendedTests.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export { recommendedTest_6_2_19 } from './recommendedTests/recommendedTest_6_2_1
2828
export { recommendedTest_6_2_20 } from './recommendedTests/recommendedTest_6_2_20.js'
2929
export { recommendedTest_6_2_22 } from './recommendedTests/recommendedTest_6_2_22.js'
3030
export { recommendedTest_6_2_23 } from './recommendedTests/recommendedTest_6_2_23.js'
31+
export { recommendedTest_6_2_25 } from './recommendedTests/recommendedTest_6_2_25.js'
3132
export { recommendedTest_6_2_27 } from './recommendedTests/recommendedTest_6_2_27.js'
3233
export { recommendedTest_6_2_28 } from './recommendedTests/recommendedTest_6_2_28.js'
3334
export { recommendedTest_6_2_29 } from './recommendedTests/recommendedTest_6_2_29.js'
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
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+
optionalProperties: {
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 recommended test 6.2.25 of the CSAF 2.1 standard.
46+
*
47+
* @param {any} doc
48+
*/
49+
export async function recommendedTest_6_2_25(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+
if (vulnerability.cwes) {
61+
for (let j = 0; j < vulnerability.cwes.length; ++j) {
62+
const cwe = vulnerability.cwes.at(j)
63+
if (validateCWE(cwe)) {
64+
const cwec = cwecMap.get(cwe.version)
65+
if (cwec) {
66+
const entry = (await cwec()).default.weaknesses.find(
67+
(w) => w.id === cwe.id
68+
)
69+
//NOTE: the usage property is not available in cwe version 4.11 and older
70+
if (
71+
entry?.usage !== 'Allowed' &&
72+
entry?.usage !== 'Allowed-with-Review'
73+
) {
74+
context.warnings.push({
75+
instancePath: `/vulnerabilities/${i}/cwes/${j}/id`,
76+
message:
77+
'the usage of the weakness with the given id is not allowed',
78+
})
79+
}
80+
}
81+
}
82+
}
83+
}
84+
}
85+
86+
return context
87+
}

tests/csaf_2_1/oasis.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ const excluded = [
3636
'6.2.20',
3737
'6.2.21',
3838
'6.2.24',
39-
'6.2.25',
4039
'6.2.26',
4140
'6.2.30',
4241
'6.2.31',
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import assert from 'node:assert'
2+
import { recommendedTest_6_2_25 } from '../../csaf_2_1/recommendedTests.js'
3+
4+
describe('recommendedTest_6_2_25', function () {
5+
it('only runs on relevant documents', async function () {
6+
assert.equal(
7+
(await recommendedTest_6_2_25({ vulnerabilities: 'mydoc' })).warnings
8+
.length,
9+
0
10+
)
11+
})
12+
it('skips empty objects', async function () {
13+
assert.equal(
14+
(
15+
await recommendedTest_6_2_25({
16+
vulnerabilities: [
17+
{
18+
cwes: [
19+
{
20+
id: 'CWE-20',
21+
name: 'Improper Input Validation',
22+
version: '4.13',
23+
},
24+
],
25+
},
26+
{}, // should be ignored
27+
],
28+
})
29+
).warnings.length,
30+
1
31+
)
32+
})
33+
})

0 commit comments

Comments
 (0)