Skip to content

Commit 01a1dd2

Browse files
feat(CSAF2.1): #287 add mandatory test 6.1.26
1 parent fbc3fd4 commit 01a1dd2

File tree

5 files changed

+113
-3
lines changed

5 files changed

+113
-3
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,6 @@ The following tests are not yet implemented and therefore missing:
318318
- Mandatory Test 6.1.27.12
319319
- Mandatory Test 6.1.27.13
320320
- Mandatory Test 6.1.27.15
321-
- Mandatory Test 6.1.27.16
322321
- Mandatory Test 6.1.27.17
323322
- Mandatory Test 6.1.27.18
324323
- Mandatory Test 6.1.27.19

csaf_2_1/mandatoryTests.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ export {
1515
mandatoryTest_6_1_23,
1616
mandatoryTest_6_1_24,
1717
mandatoryTest_6_1_25,
18-
mandatoryTest_6_1_26,
1918
mandatoryTest_6_1_27_1,
2019
mandatoryTest_6_1_27_2,
2120
mandatoryTest_6_1_27_3,
@@ -41,6 +40,7 @@ export { mandatoryTest_6_1_9 } from './mandatoryTests/mandatoryTest_6_1_9.js'
4140
export { mandatoryTest_6_1_10 } from './mandatoryTests/mandatoryTest_6_1_10.js'
4241
export { mandatoryTest_6_1_11 } from './mandatoryTests/mandatoryTest_6_1_11.js'
4342
export { mandatoryTest_6_1_13 } from './mandatoryTests/mandatoryTest_6_1_13.js'
43+
export { mandatoryTest_6_1_26 } from './mandatoryTests/mandatoryTest_6_1_26.js'
4444
export { mandatoryTest_6_1_27_14 } from './mandatoryTests/mandatoryTest_6_1_27_14.js'
4545
export { mandatoryTest_6_1_34 } from './mandatoryTests/mandatoryTest_6_1_34.js'
4646
export { mandatoryTest_6_1_35 } from './mandatoryTests/mandatoryTest_6_1_35.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+
3+
const jtdAjv = 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+
},
23+
})
24+
25+
const validateInput = jtdAjv.compile(inputSchema)
26+
27+
const profileValues = [
28+
'csaf_base',
29+
'csaf_security_incident_response',
30+
'csaf_informational_advisory',
31+
'csaf_security_advisory',
32+
'csaf_vex',
33+
'csaf_deprecated_security_advisory',
34+
'csaf_withdrawn',
35+
'csaf_superseded',
36+
]
37+
const otherProfileValues = [
38+
'securityincidentresponse',
39+
'informationaladvisory',
40+
'securityadvisory',
41+
'vex',
42+
'deprecatedsecurityadvisory',
43+
'withdrawn',
44+
'superseded',
45+
]
46+
47+
/**
48+
* It MUST be tested that the document category is not equal to the (case-insensitive) name (without the prefix csaf_)
49+
* or value of any other profile than "CSAF Base". Any occurrences of dash, whitespace, and underscore characters are
50+
* removed from the values on both sides before the match.
51+
* Also, the value MUST NOT start with the reserved prefix csaf_ except if the value is csaf_base.
52+
* @param {unknown} doc
53+
*/
54+
export function mandatoryTest_6_1_26(doc) {
55+
const ctx = {
56+
errors:
57+
/** @type {Array<{ instancePath: string; message: string }>} */ ([]),
58+
isValid: true,
59+
}
60+
if (!validateInput(doc)) {
61+
return ctx
62+
}
63+
64+
/** @type {string} */
65+
const category = doc.document.category
66+
67+
// Skip test if profile is not "CSAF Base" but one of the other profiles or matches exactly "csaf_base"
68+
if (profileValues.includes(category)) {
69+
return ctx
70+
}
71+
72+
// Fail on reserved prefix
73+
if (category.toLowerCase().startsWith('csaf_')) {
74+
ctx.isValid = false
75+
ctx.errors.push({
76+
instancePath: `/document/category`,
77+
message: `reserved prefix used`,
78+
})
79+
80+
return ctx
81+
}
82+
83+
// Fail on name similarity
84+
if (
85+
otherProfileValues.includes(category.replace(/[_-\s]+/g, '').toLowerCase())
86+
) {
87+
ctx.isValid = false
88+
ctx.errors.push({
89+
instancePath: `/document/category`,
90+
message: `value prohibited`,
91+
})
92+
}
93+
return ctx
94+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import assert from 'node:assert/strict'
2+
import { mandatoryTest_6_1_26 } from '../../csaf_2_1/mandatoryTests/mandatoryTest_6_1_26.js'
3+
4+
describe('mandatoryTest_6_1_26', function () {
5+
it('only runs on relevant documents', function () {
6+
assert.equal(mandatoryTest_6_1_26({ document: 'mydoc' }).isValid, true)
7+
})
8+
it('check use of reserved prefix csaf_ except if the value is csaf_base', function () {
9+
assert.equal(
10+
mandatoryTest_6_1_26({
11+
document: {
12+
category: 'csaf_invalid',
13+
},
14+
}).isValid,
15+
false
16+
)
17+
})
18+
})

tests/csaf_2_1/oasis.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ const excluded = [
1313
'6.1.6',
1414
'6.1.14',
1515
'6.1.16',
16-
'6.1.26',
1716
'6.1.27.3',
1817
'6.1.27.4',
1918
'6.1.27.6',

0 commit comments

Comments
 (0)