Skip to content

Commit 42b3186

Browse files
feat(CSAF2.1): #364 add recommended test 6.2.44
1 parent fbc3fd4 commit 42b3186

File tree

8 files changed

+8863
-2
lines changed

8 files changed

+8863
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,6 @@ The following tests are not yet implemented and therefore missing:
364364
- Recommended Test 6.2.41
365365
- Recommended Test 6.2.42
366366
- Recommended Test 6.2.43
367-
- Recommended Test 6.2.44
368367
- Recommended Test 6.2.45
369368
- Recommended Test 6.2.46
370369
@@ -462,6 +461,7 @@ export const recommendedTest_6_2_16: DocumentTest
462461
export const recommendedTest_6_2_17: DocumentTest
463462
export const recommendedTest_6_2_18: DocumentTest
464463
export const recommendedTest_6_2_22: DocumentTest
464+
export const recommendedTest_6_2_44: DocumentTest
465465
```
466466
467467
[(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
@@ -31,3 +31,4 @@ export { recommendedTest_6_2_27 } from './recommendedTests/recommendedTest_6_2_2
3131
export { recommendedTest_6_2_28 } from './recommendedTests/recommendedTest_6_2_28.js'
3232
export { recommendedTest_6_2_29 } from './recommendedTests/recommendedTest_6_2_29.js'
3333
export { recommendedTest_6_2_38 } from './recommendedTests/recommendedTest_6_2_38.js'
34+
export { recommendedTest_6_2_44 } from './recommendedTests/recommendedTest_6_2_44.js'
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import Ajv from 'ajv/dist/jtd.js'
2+
import { parse, validate } from 'license-expressions'
3+
import license_information from '../../lib/license/license_information.js'
4+
5+
const ajv = new Ajv()
6+
7+
/*
8+
This is the jtd schema that needs to match the input document so that the
9+
test is activated. If this schema doesn't match, it normally means that the input
10+
document does not validate against the csaf JSON schema or optional fields that
11+
the test checks are not present.
12+
*/
13+
const inputSchema = /** @type {const} */ ({
14+
additionalProperties: true,
15+
properties: {
16+
document: {
17+
additionalProperties: true,
18+
properties: {
19+
license_expression: {
20+
type: 'string',
21+
},
22+
},
23+
},
24+
},
25+
})
26+
27+
const ABOUT_CODE_LICENSE_REF_PREFIX = 'LicenseRef-scancode-'
28+
29+
const DEPRECATED_ABOUT_CODE_LICENSE_KEYS = new Set(
30+
license_information.licenses
31+
.filter((license) => license.deprecated && license.source === 'aboutCode')
32+
.map((license) => license.license_key)
33+
)
34+
35+
const DEPRECATED_SPDX_LICENSE_KEYS = new Set(
36+
license_information.licenses
37+
.filter((license) => license.deprecated && license.source === 'spdx')
38+
.map((license) => license.license_key)
39+
)
40+
41+
const validateSchema = ajv.compile(inputSchema)
42+
43+
/**
44+
* Check whether the license identifiers ref is a deprecated Aboutcode's license
45+
* @param {string} licenseRefToCheck
46+
* @return {boolean}
47+
*/
48+
function isDeprecatedLicenseRef(licenseRefToCheck) {
49+
if (!licenseRefToCheck.startsWith(ABOUT_CODE_LICENSE_REF_PREFIX)) {
50+
return false
51+
} else {
52+
const licenseKey = licenseRefToCheck.substring(
53+
ABOUT_CODE_LICENSE_REF_PREFIX.length
54+
)
55+
return DEPRECATED_ABOUT_CODE_LICENSE_KEYS.has(licenseKey)
56+
}
57+
}
58+
59+
/**
60+
* Recursively checks if a parsed license expression contains deprecated licenses
61+
*
62+
* @param {import('license-expressions').ParsedSpdxExpression} parsedExpression - The parsed license expression
63+
* @returns {Array<string>} all deprecated licenses
64+
*/
65+
function allDeprecatedLicenses(parsedExpression) {
66+
/** @type {Array<string>} */
67+
const deprecatedLicenses = []
68+
// If it's a LicenseRef type directly
69+
if (
70+
'licenseRef' in parsedExpression &&
71+
isDeprecatedLicenseRef(parsedExpression.licenseRef)
72+
) {
73+
deprecatedLicenses.push(parsedExpression.licenseRef)
74+
}
75+
76+
if (
77+
'license' in parsedExpression &&
78+
DEPRECATED_SPDX_LICENSE_KEYS.has(parsedExpression.license)
79+
) {
80+
deprecatedLicenses.push(parsedExpression.license)
81+
}
82+
83+
if (
84+
'exception' in parsedExpression &&
85+
parsedExpression.exception &&
86+
DEPRECATED_SPDX_LICENSE_KEYS.has(parsedExpression.exception)
87+
) {
88+
deprecatedLicenses.push(parsedExpression.exception)
89+
}
90+
91+
// If it's a conjunction, check both sides
92+
if ('conjunction' in parsedExpression) {
93+
deprecatedLicenses.push(...allDeprecatedLicenses(parsedExpression.left))
94+
deprecatedLicenses.push(...allDeprecatedLicenses(parsedExpression.right))
95+
}
96+
97+
// If it's a LicenseInfo type, it doesn't contain not listed licenses
98+
return deprecatedLicenses
99+
}
100+
101+
/**
102+
* Checks if a license expression string contains deprecated licenses
103+
*
104+
* @param {string} licenseToCheck - The license expression to check
105+
* @returns {Array<string>} all deprecated licenses
106+
*/
107+
export function allDeprecatedInLicenseString(licenseToCheck) {
108+
const parseResult = parse(licenseToCheck)
109+
return allDeprecatedLicenses(parseResult)
110+
}
111+
112+
/**
113+
* It MUST be tested that all license identifier and exceptions used are not deprecated.
114+
* This SHALL be tested for the SPDX license list and Aboutcode's "ScanCode LicenseDB".
115+
* The test MAY be skipped for other license inventorying entities.
116+
*
117+
* @param {unknown} doc
118+
*/
119+
export function recommendedTest_6_2_44(doc) {
120+
/*
121+
The `ctx` variable holds the state that is accumulated during the test run and is
122+
finally returned by the function.
123+
*/
124+
const ctx = {
125+
warnings:
126+
/** @type {Array<{ instancePath: string; message: string }>} */ ([]),
127+
}
128+
129+
if (!validateSchema(doc)) {
130+
return ctx
131+
}
132+
133+
const licenseToCheck = doc.document.license_expression
134+
135+
if (validate(licenseToCheck).valid) {
136+
const deprecatedLicenseIdentifier =
137+
allDeprecatedInLicenseString(licenseToCheck)
138+
139+
deprecatedLicenseIdentifier.forEach((licenseKey) => {
140+
ctx.warnings.push({
141+
instancePath: '/document/license_expression',
142+
message: `License identifier ${licenseKey} is deprecated `,
143+
})
144+
})
145+
}
146+
147+
return ctx
148+
}

0 commit comments

Comments
 (0)