Skip to content

Commit eacf2d0

Browse files
authored
Merge pull request #574 from secvisogram/fix/csaf-2.1_mandatory_test_6.1.27.5
fix(CSAF2.1): fix mandatoryTest_6_1_27_5.js
2 parents 5e5636f + 663c89b commit eacf2d0

4 files changed

Lines changed: 110 additions & 2 deletions

File tree

csaf_2_1/mandatoryTests.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export {
2121
mandatoryTest_6_1_27_2,
2222
mandatoryTest_6_1_27_3,
2323
mandatoryTest_6_1_27_4,
24-
mandatoryTest_6_1_27_5,
2524
mandatoryTest_6_1_27_6,
2625
mandatoryTest_6_1_27_7,
2726
mandatoryTest_6_1_27_8,
@@ -43,6 +42,7 @@ export { mandatoryTest_6_1_9 } from './mandatoryTests/mandatoryTest_6_1_9.js'
4342
export { mandatoryTest_6_1_10 } from './mandatoryTests/mandatoryTest_6_1_10.js'
4443
export { mandatoryTest_6_1_11 } from './mandatoryTests/mandatoryTest_6_1_11.js'
4544
export { mandatoryTest_6_1_13 } from './mandatoryTests/mandatoryTest_6_1_13.js'
45+
export { mandatoryTest_6_1_27_5 } from './mandatoryTests/mandatoryTest_6_1_27_5.js'
4646
export { mandatoryTest_6_1_27_12 } from './mandatoryTests/mandatoryTest_6_1_27_12.js'
4747
export { mandatoryTest_6_1_27_14 } from './mandatoryTests/mandatoryTest_6_1_27_14.js'
4848
export { mandatoryTest_6_1_27_15 } from './mandatoryTests/mandatoryTest_6_1_27_15.js'
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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+
category: {
18+
type: 'string',
19+
},
20+
},
21+
},
22+
vulnerabilities: {
23+
elements: {
24+
additionalProperties: true,
25+
optionalProperties: {
26+
notes: {
27+
elements: {
28+
additionalProperties: true,
29+
properties: {},
30+
},
31+
},
32+
},
33+
},
34+
},
35+
},
36+
})
37+
38+
const validate = ajv.compile(inputSchema)
39+
/**
40+
* @param {any} doc
41+
*/
42+
export function mandatoryTest_6_1_27_5(doc) {
43+
/** @type {Array<{ message: string; instancePath: string }>} */
44+
const errors = []
45+
let isValid = true
46+
47+
if (!validate(doc)) return { errors, isValid }
48+
49+
const checkedDocumentCategories = new Set([
50+
'csaf_security_advisory',
51+
'csaf_vex',
52+
'csaf_deprecated_security_advisory',
53+
])
54+
55+
if (!checkedDocumentCategories.has(doc.document?.category)) {
56+
return { errors, isValid }
57+
}
58+
59+
const vulnerabilities = doc.vulnerabilities
60+
if (Array.isArray(vulnerabilities)) {
61+
vulnerabilities.forEach((vulnerability, vulnerabilityIndex) => {
62+
if (!vulnerability.notes || vulnerability.notes.length === 0) {
63+
isValid = false
64+
errors.push({
65+
instancePath: `/vulnerabilities/${vulnerabilityIndex}`,
66+
message: 'needs a `notes` attribute',
67+
})
68+
}
69+
})
70+
}
71+
72+
return { errors, isValid }
73+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import assert from 'node:assert/strict'
2+
import { mandatoryTest_6_1_27_5 } from '../../csaf_2_1/mandatoryTests/mandatoryTest_6_1_27_5.js'
3+
4+
describe('mandatoryTest_6_1_27_5', function () {
5+
it('only runs on relevant documents', function () {
6+
assert.equal(mandatoryTest_6_1_27_5({ document: 'mydoc' }).isValid, true)
7+
})
8+
9+
it('returns valid for documents with irrelevant category', function () {
10+
assert.equal(
11+
mandatoryTest_6_1_27_5({
12+
document: { category: 'csaf_base' },
13+
vulnerabilities: [{}],
14+
}).isValid,
15+
true
16+
)
17+
})
18+
19+
it('returns invalid when vulnerability has no notes', function () {
20+
const result = mandatoryTest_6_1_27_5({
21+
document: { category: 'csaf_security_advisory' },
22+
vulnerabilities: [{}],
23+
})
24+
assert.equal(result.isValid, false)
25+
assert.equal(result.errors.length, 1)
26+
})
27+
28+
it('returns invalid when vulnerability has empty notes array', function () {
29+
const result = mandatoryTest_6_1_27_5({
30+
document: { category: 'csaf_security_advisory' },
31+
vulnerabilities: [{ notes: [] }],
32+
})
33+
assert.equal(result.isValid, false)
34+
assert.equal(result.errors.length, 1)
35+
})
36+
})

tests/csaf_2_1/oasis.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ const excluded = [
9898
const skippedTests = new Set([
9999
'mandatory/oasis_csaf_tc-csaf_2_1-2024-6-1-01-12.json',
100100
'mandatory/oasis_csaf_tc-csaf_2_1-2024-6-1-03-01.json',
101-
'mandatory/oasis_csaf_tc-csaf_2_1-2024-6-1-27-05-03.json',
102101
])
103102

104103
/** @typedef {import('../../lib/shared/types.js').DocumentTest} DocumentTest */

0 commit comments

Comments
 (0)