@cdxgen/cdxgen 13.6.0 → 13.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -8
- package/bin/audit.js +7 -4
- package/bin/cdxgen.js +256 -37
- package/bin/convert.js +146 -22
- package/bin/evinse.js +25 -3
- package/bin/repl.js +47 -3
- package/bin/sign.js +211 -34
- package/bin/tracebom.js +18 -6
- package/bin/validate.js +18 -3
- package/bin/verify.js +113 -5
- package/data/behavior-taxonomy.schema.json +1491 -0
- package/data/cyclonedx-2.0-bundled.schema.json +18606 -5528
- package/data/cyclonedx-2.0-cryptography-defs.schema.json +857 -0
- package/data/pqc-migration.json +239 -0
- package/data/remediations.json +52 -0
- package/data/rules/cbom-security.yaml +4 -3
- package/data/rules/package-integrity.yaml +28 -0
- package/lib/audit/index.js +25 -3
- package/lib/cli/bomAssembly.js +80 -1
- package/lib/cli/cliOptions.js +121 -17
- package/lib/cli/index.js +609 -898
- package/lib/cli/jsBom.js +3 -0
- package/lib/cli/jvmBom.js +365 -40
- package/lib/cli/managedBom.js +19 -3
- package/lib/cli/nativeBom.js +10 -0
- package/lib/core/env.js +26 -0
- package/lib/core/fs.js +126 -3
- package/lib/core/globPatterns.js +218 -0
- package/lib/core/processTree.js +99 -12
- package/lib/core/projectConfig.js +332 -25
- package/lib/core/toolRegistry.js +15 -1
- package/lib/ecosystems/denoutils.js +2 -2
- package/lib/ecosystems/golem.js +3 -8
- package/lib/ecosystems/gradleutils.js +1082 -6
- package/lib/ecosystems/jsEvidence.js +90 -38
- package/lib/ecosystems/kosi.js +3 -5
- package/lib/ecosystems/npmVersionResolution.js +376 -0
- package/lib/ecosystems/parsers-python.js +89 -28
- package/lib/ecosystems/parsers-rust.js +117 -15
- package/lib/ecosystems/remote/huggingface.js +22 -0
- package/lib/ecosystems/rusi.js +2 -4
- package/lib/ecosystems/scalasem.js +2 -1
- package/lib/evinser/evinser.js +196 -34
- package/lib/evinser/scalasem.js +5 -1
- package/lib/helpers/agenticToolutils.js +112 -1
- package/lib/helpers/bomSigner.js +43 -9
- package/lib/helpers/jssSigner.js +1276 -0
- package/lib/inventory/agentBlueprint.js +193 -0
- package/lib/inventory/agentToolNames.js +145 -0
- package/lib/inventory/aiCollector.js +153 -7
- package/lib/inventory/aiInventory.js +44 -8
- package/lib/inventory/aiProviders.js +324 -0
- package/lib/inventory/bomUtils.js +8 -1
- package/lib/inventory/ciParsers/githubActionsLock.js +821 -0
- package/lib/inventory/citations.js +31 -2
- package/lib/inventory/communityAiConfigParser.js +978 -80
- package/lib/inventory/cyclonedx20.js +152 -0
- package/lib/inventory/cyclonedx20Common.js +286 -0
- package/lib/inventory/cyclonedx20Derived.js +159 -0
- package/lib/inventory/cyclonedx20Parties.js +552 -0
- package/lib/inventory/cyclonedx20Read.js +768 -0
- package/lib/inventory/cyclonedx20ReadCommon.js +374 -0
- package/lib/inventory/cyclonedx20ReadComponents.js +692 -0
- package/lib/inventory/cyclonedx20ReadContext.js +380 -0
- package/lib/inventory/cyclonedx20ReadEvidence.js +466 -0
- package/lib/inventory/cyclonedx20ReadSections.js +599 -0
- package/lib/inventory/cyclonedx20Render.js +766 -0
- package/lib/inventory/cyclonedx20RenderComponents.js +716 -0
- package/lib/inventory/cyclonedx20RenderDefinitions.js +405 -0
- package/lib/inventory/cyclonedx20RenderEvidence.js +726 -0
- package/lib/inventory/cyclonedx20RenderHardware.js +203 -0
- package/lib/inventory/cyclonedx20RenderPatents.js +174 -0
- package/lib/inventory/cyclonedx20RenderRefIds.js +314 -0
- package/lib/inventory/cyclonedx20RenderSections.js +499 -0
- package/lib/inventory/cyclonedx20Tables.js +594 -0
- package/lib/inventory/deps.js +106 -13
- package/lib/inventory/dosai.js +236 -1
- package/lib/inventory/dosaiParsers.js +3 -6
- package/lib/inventory/dotnetRuntime.js +164 -14
- package/lib/inventory/ecosystemFormulationParsers.js +979 -0
- package/lib/inventory/envcontext.js +132 -38
- package/lib/inventory/evidenceUtils.js +2 -1
- package/lib/inventory/formulationParsers.js +95 -13
- package/lib/inventory/hbom.js +45 -6
- package/lib/inventory/hbomLoader.js +166 -0
- package/lib/inventory/mcpConfigParser.js +5 -0
- package/lib/inventory/occurrenceKey.js +90 -0
- package/lib/inventory/pqcMigration.js +426 -0
- package/lib/inventory/rustFormulationParser.js +21 -10
- package/lib/inventory/source.js +65 -6
- package/lib/parsers/huggingfaceManifest.js +9 -1
- package/lib/parsers/huggingfaceUtils.js +18 -0
- package/lib/parsers/kiroPermissions.js +166 -0
- package/lib/server/server.js +36 -34
- package/lib/stages/postgen/postgen.js +41 -1
- package/lib/stages/postgen/specVersionCompat.js +76 -0
- package/lib/validator/bomValidator.js +8 -1
- package/lib/validator/complianceEngine.js +30 -3
- package/lib/validator/complianceRules.js +1416 -4
- package/lib/validator/generated/validate-2.0.mjs +57554 -13851
- package/lib/validator/index.js +48 -7
- package/lib/validator/reporters/json.js +6 -0
- package/package.json +9 -9
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts +6 -2
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/cli/bomAssembly.d.ts +16 -0
- package/types/lib/cli/bomAssembly.d.ts.map +1 -1
- package/types/lib/cli/cliOptions.d.ts +6 -0
- package/types/lib/cli/cliOptions.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/cli/jsBom.d.ts +2 -1
- package/types/lib/cli/jsBom.d.ts.map +1 -1
- package/types/lib/cli/jvmBom.d.ts +15 -0
- package/types/lib/cli/jvmBom.d.ts.map +1 -1
- package/types/lib/cli/managedBom.d.ts.map +1 -1
- package/types/lib/cli/nativeBom.d.ts.map +1 -1
- package/types/lib/core/boundedFile.d.ts +30 -0
- package/types/lib/core/boundedFile.d.ts.map +1 -1
- package/types/lib/core/env.d.ts +10 -0
- package/types/lib/core/env.d.ts.map +1 -1
- package/types/lib/core/fs.d.ts +4 -0
- package/types/lib/core/fs.d.ts.map +1 -1
- package/types/lib/core/globPatterns.d.ts +70 -0
- package/types/lib/core/globPatterns.d.ts.map +1 -0
- package/types/lib/core/paths.d.ts +9 -0
- package/types/lib/core/paths.d.ts.map +1 -1
- package/types/lib/core/processTree.d.ts +16 -5
- package/types/lib/core/processTree.d.ts.map +1 -1
- package/types/lib/core/projectConfig.d.ts +47 -8
- package/types/lib/core/projectConfig.d.ts.map +1 -1
- package/types/lib/core/toolRegistry.d.ts.map +1 -1
- package/types/lib/ecosystems/golem.d.ts.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +248 -8
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
- package/types/lib/ecosystems/jsEvidence.d.ts +14 -1
- package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/kosi.d.ts.map +1 -1
- package/types/lib/ecosystems/npmVersionResolution.d.ts +119 -0
- package/types/lib/ecosystems/npmVersionResolution.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
- package/types/lib/ecosystems/pythonutils.d.ts +1 -1
- package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -1
- package/types/lib/ecosystems/rusi.d.ts.map +1 -1
- package/types/lib/ecosystems/scalasem.d.ts +58 -16
- package/types/lib/ecosystems/scalasem.d.ts.map +1 -1
- package/types/lib/evinser/evinser.d.ts +61 -9
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/evinser/scalasem.d.ts.map +1 -1
- package/types/lib/helpers/agenticToolutils.d.ts +53 -19
- package/types/lib/helpers/agenticToolutils.d.ts.map +1 -1
- package/types/lib/helpers/bomSigner.d.ts +20 -3
- package/types/lib/helpers/bomSigner.d.ts.map +1 -1
- package/types/lib/helpers/jssSigner.d.ts +288 -0
- package/types/lib/helpers/jssSigner.d.ts.map +1 -0
- package/types/lib/helpers/vsixutils.d.ts +303 -19
- package/types/lib/helpers/vsixutils.d.ts.map +1 -1
- package/types/lib/inventory/agentBlueprint.d.ts +70 -0
- package/types/lib/inventory/agentBlueprint.d.ts.map +1 -0
- package/types/lib/inventory/agentToolNames.d.ts +51 -0
- package/types/lib/inventory/agentToolNames.d.ts.map +1 -0
- package/types/lib/inventory/aiCollector.d.ts.map +1 -1
- package/types/lib/inventory/aiInventory.d.ts.map +1 -1
- package/types/lib/inventory/aiProviders.d.ts +85 -0
- package/types/lib/inventory/aiProviders.d.ts.map +1 -0
- package/types/lib/inventory/bomUtils.d.ts.map +1 -1
- package/types/lib/inventory/ciParsers/githubActionsLock.d.ts +101 -0
- package/types/lib/inventory/ciParsers/githubActionsLock.d.ts.map +1 -0
- package/types/lib/inventory/citations.d.ts +5 -0
- package/types/lib/inventory/citations.d.ts.map +1 -1
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/cyclonedx20.d.ts +99 -0
- package/types/lib/inventory/cyclonedx20.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Common.d.ts +102 -0
- package/types/lib/inventory/cyclonedx20Common.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Derived.d.ts +74 -0
- package/types/lib/inventory/cyclonedx20Derived.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Parties.d.ts +91 -0
- package/types/lib/inventory/cyclonedx20Parties.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Read.d.ts +51 -0
- package/types/lib/inventory/cyclonedx20Read.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadCommon.d.ts +69 -0
- package/types/lib/inventory/cyclonedx20ReadCommon.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadComponents.d.ts +77 -0
- package/types/lib/inventory/cyclonedx20ReadComponents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadContext.d.ts +118 -0
- package/types/lib/inventory/cyclonedx20ReadContext.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts +40 -0
- package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadSections.d.ts +45 -0
- package/types/lib/inventory/cyclonedx20ReadSections.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Render.d.ts +53 -0
- package/types/lib/inventory/cyclonedx20Render.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderComponents.d.ts +73 -0
- package/types/lib/inventory/cyclonedx20RenderComponents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts +29 -0
- package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts +110 -0
- package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderHardware.d.ts +42 -0
- package/types/lib/inventory/cyclonedx20RenderHardware.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderPatents.d.ts +26 -0
- package/types/lib/inventory/cyclonedx20RenderPatents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts +55 -0
- package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderSections.d.ts +45 -0
- package/types/lib/inventory/cyclonedx20RenderSections.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Tables.d.ts +134 -0
- package/types/lib/inventory/cyclonedx20Tables.d.ts.map +1 -0
- package/types/lib/inventory/deps.d.ts +35 -2
- package/types/lib/inventory/deps.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +19 -0
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
- package/types/lib/inventory/dotnetRuntime.d.ts +51 -4
- package/types/lib/inventory/dotnetRuntime.d.ts.map +1 -1
- package/types/lib/inventory/ecosystemFormulationParsers.d.ts +73 -0
- package/types/lib/inventory/ecosystemFormulationParsers.d.ts.map +1 -0
- package/types/lib/inventory/envcontext.d.ts +22 -6
- package/types/lib/inventory/envcontext.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
- package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
- package/types/lib/inventory/hbom.d.ts +11 -0
- package/types/lib/inventory/hbom.d.ts.map +1 -1
- package/types/lib/inventory/hbomLoader.d.ts +54 -0
- package/types/lib/inventory/hbomLoader.d.ts.map +1 -1
- package/types/lib/inventory/jvmLocalRepos.d.ts +5 -1
- package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -1
- package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/occurrenceKey.d.ts +52 -0
- package/types/lib/inventory/occurrenceKey.d.ts.map +1 -0
- package/types/lib/inventory/pqcMigration.d.ts +84 -0
- package/types/lib/inventory/pqcMigration.d.ts.map +1 -0
- package/types/lib/inventory/rustFormulationParser.d.ts +7 -2
- package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
- package/types/lib/inventory/scalaCoords.d.ts.map +1 -1
- package/types/lib/inventory/scalaDedupe.d.ts +43 -0
- package/types/lib/inventory/scalaDedupe.d.ts.map +1 -0
- package/types/lib/inventory/source.d.ts +15 -0
- package/types/lib/inventory/source.d.ts.map +1 -1
- package/types/lib/parsers/huggingfaceManifest.d.ts +10 -1
- package/types/lib/parsers/huggingfaceManifest.d.ts.map +1 -1
- package/types/lib/parsers/huggingfaceUtils.d.ts +12 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -1
- package/types/lib/parsers/kiroPermissions.d.ts +62 -0
- package/types/lib/parsers/kiroPermissions.d.ts.map +1 -0
- package/types/lib/parsers/vscodeExtensionId.d.ts +48 -0
- package/types/lib/parsers/vscodeExtensionId.d.ts.map +1 -0
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts +7 -0
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
- package/types/lib/stages/postgen/specVersionCompat.d.ts +25 -0
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts +5 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/complianceEngine.d.ts +4 -4
- package/types/lib/validator/complianceEngine.d.ts.map +1 -1
- package/types/lib/validator/complianceRules.d.ts +14 -2
- package/types/lib/validator/complianceRules.d.ts.map +1 -1
- package/types/lib/validator/index.d.ts +10 -0
- package/types/lib/validator/index.d.ts.map +1 -1
- package/types/lib/validator/reporters/json.d.ts.map +1 -1
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reader converters for CycloneDX 2.0 component evidence
|
|
3
|
+
* (#/$defs/cyclonedx-component-2.0/$defs/componentEvidence and
|
|
4
|
+
* #/$defs/cyclonedx-evidence-2.0) and cryptoProperties
|
|
5
|
+
* (#/$defs/cyclonedx-cryptography-2.0/$defs/cryptoProperties) back to the 1.x
|
|
6
|
+
* shapes. Each frozen spec is the allowlist of the members 1.x carries.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { isDeepStrictEqual } from "node:util";
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
createRenderStats,
|
|
13
|
+
isNonEmptyString,
|
|
14
|
+
isObjectRecord,
|
|
15
|
+
shadowKey,
|
|
16
|
+
} from "./cyclonedx20Common.js";
|
|
17
|
+
import { reverseHash } from "./cyclonedx20ReadCommon.js";
|
|
18
|
+
import {
|
|
19
|
+
addLoss,
|
|
20
|
+
jsonPointer,
|
|
21
|
+
listOf,
|
|
22
|
+
objectOf,
|
|
23
|
+
reverseFields,
|
|
24
|
+
reverseList,
|
|
25
|
+
reverseObject,
|
|
26
|
+
} from "./cyclonedx20ReadContext.js";
|
|
27
|
+
import { convertIdentityEntry } from "./cyclonedx20RenderEvidence.js";
|
|
28
|
+
import {
|
|
29
|
+
ALGORITHM_FAMILY_1X,
|
|
30
|
+
ALGORITHM_PROPERTY_ENUMS_1X,
|
|
31
|
+
ELLIPTIC_CURVE_1X,
|
|
32
|
+
IDENTITY_EVIDENCE_SCHEME_TO_FIELD,
|
|
33
|
+
IDENTITY_FIELDS_1X,
|
|
34
|
+
IDENTITY_TECHNIQUES_1X,
|
|
35
|
+
PROTOCOL_TYPES_1X,
|
|
36
|
+
} from "./cyclonedx20Tables.js";
|
|
37
|
+
|
|
38
|
+
/** A spec rule keeping a value only when the 1.x enum lists it. */
|
|
39
|
+
function enumRule(kind, values) {
|
|
40
|
+
return Object.freeze({
|
|
41
|
+
convert: (ctx, value, pointer) => {
|
|
42
|
+
if (values.has(value)) {
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
addLoss(ctx, pointer, `${kind} '${value}' is not a 1.x value`);
|
|
46
|
+
return undefined;
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** A spec rule keeping the list entries the 1.x enum lists. */
|
|
52
|
+
function enumListRule(kind, values) {
|
|
53
|
+
return Object.freeze({
|
|
54
|
+
convert: (ctx, value, pointer) =>
|
|
55
|
+
reverseList(ctx, value, pointer, (_ctx, entry, entryPointer) => {
|
|
56
|
+
if (values.has(entry)) {
|
|
57
|
+
return entry;
|
|
58
|
+
}
|
|
59
|
+
addLoss(ctx, entryPointer, `${kind} '${entry}' is not a 1.x value`);
|
|
60
|
+
return undefined;
|
|
61
|
+
}),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** The 1.x identity `field` for a 2.0 identity-evidence scheme, if any. */
|
|
66
|
+
function identityField(scheme) {
|
|
67
|
+
if (typeof scheme === "string") {
|
|
68
|
+
return Object.hasOwn(IDENTITY_EVIDENCE_SCHEME_TO_FIELD, scheme)
|
|
69
|
+
? IDENTITY_EVIDENCE_SCHEME_TO_FIELD[scheme]
|
|
70
|
+
: undefined;
|
|
71
|
+
}
|
|
72
|
+
// The renderer writes 1.x fields outside the scheme enum (group, name,
|
|
73
|
+
// version, hash) as custom `{name}` schemes.
|
|
74
|
+
return isObjectRecord(scheme) && IDENTITY_FIELDS_1X.has(scheme.name)
|
|
75
|
+
? scheme.name
|
|
76
|
+
: undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** identificationMethod → 1.x method; `unknown` is the 1.x `other`. */
|
|
80
|
+
function reverseIdentityMethod(ctx, value, pointer) {
|
|
81
|
+
if (!isObjectRecord(value)) {
|
|
82
|
+
addLoss(ctx, pointer, "identity method is not an object");
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
const technique = value.technique === "unknown" ? "other" : value.technique;
|
|
86
|
+
if (!IDENTITY_TECHNIQUES_1X.has(technique)) {
|
|
87
|
+
addLoss(
|
|
88
|
+
ctx,
|
|
89
|
+
jsonPointer(pointer, "technique"),
|
|
90
|
+
"identity method technique is not a 1.x technique; method dropped",
|
|
91
|
+
);
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
const method = reverseFields(ctx, "identificationMethod", value, pointer, {
|
|
95
|
+
technique: true,
|
|
96
|
+
confidence: true,
|
|
97
|
+
value: true,
|
|
98
|
+
});
|
|
99
|
+
method.technique = technique;
|
|
100
|
+
return method;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const IDENTITY_SPEC = Object.freeze({
|
|
104
|
+
scheme: Object.freeze({
|
|
105
|
+
to: "field",
|
|
106
|
+
convert: (_ctx, value) => identityField(value),
|
|
107
|
+
}),
|
|
108
|
+
concludedValue: true,
|
|
109
|
+
confidence: true,
|
|
110
|
+
methods: listOf(reverseIdentityMethod),
|
|
111
|
+
tools: true,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* componentIdentityEvidence → 1.x identity (requires `field`). 1.x has no
|
|
116
|
+
* `assertion`, `timestamp` or method `result`, so they never reach the 1.x
|
|
117
|
+
* entry. When the 1.x entry renders back to exactly this 2.0 entry, those
|
|
118
|
+
* members are cdxgen's own attributed claim, which renderCycloneDx20 derives
|
|
119
|
+
* again from the entry and the BOM (see convertIdentityEntry), and reading
|
|
120
|
+
* them is no loss. Otherwise (a foreign party's assertion, a timestamp of its
|
|
121
|
+
* own) every such member is a loss, and the entry is noted for an identity
|
|
122
|
+
* shadow so a render of the unchanged 1.x entry restores it.
|
|
123
|
+
*/
|
|
124
|
+
function reverseIdentityEvidence(ctx, value, pointer) {
|
|
125
|
+
if (!isObjectRecord(value)) {
|
|
126
|
+
addLoss(ctx, pointer, "identity evidence is not an object");
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
if (identityField(value.scheme) === undefined) {
|
|
130
|
+
addLoss(
|
|
131
|
+
ctx,
|
|
132
|
+
jsonPointer(pointer, "scheme"),
|
|
133
|
+
"identity evidence scheme has no 1.x field; entry dropped",
|
|
134
|
+
);
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
const before = ctx.losses.length;
|
|
138
|
+
const identity = reverseFields(
|
|
139
|
+
ctx,
|
|
140
|
+
"identityEvidence",
|
|
141
|
+
value,
|
|
142
|
+
pointer,
|
|
143
|
+
IDENTITY_SPEC,
|
|
144
|
+
);
|
|
145
|
+
const rendered = convertIdentityEntry(
|
|
146
|
+
identity,
|
|
147
|
+
createRenderStats(undefined, ctx.claims),
|
|
148
|
+
);
|
|
149
|
+
const derived = isDeepStrictEqual(rendered, value);
|
|
150
|
+
if (derived) {
|
|
151
|
+
ctx.losses.length = before;
|
|
152
|
+
}
|
|
153
|
+
if (!ctx.shadowSuspended) {
|
|
154
|
+
ctx.keptIdentities.push({
|
|
155
|
+
key: shadowKey(identity),
|
|
156
|
+
original: value,
|
|
157
|
+
needsShadow: !derived,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
return identity;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Register the identity shadows. An identity shadow is looked up by its 1.x
|
|
165
|
+
* projection alone, whichever component carries it, so a key is registered
|
|
166
|
+
* only when every identity entry read under it needs the same original; a
|
|
167
|
+
* key shared with an entry that renders back by itself, or with a different
|
|
168
|
+
* original, is left to the component shadows.
|
|
169
|
+
*
|
|
170
|
+
* @param {object} ctx Reader context
|
|
171
|
+
*/
|
|
172
|
+
export function flushIdentityShadows(ctx) {
|
|
173
|
+
const byKey = new Map();
|
|
174
|
+
for (const kept of ctx.keptIdentities) {
|
|
175
|
+
const group = byKey.get(kept.key) || [];
|
|
176
|
+
group.push(kept);
|
|
177
|
+
byKey.set(kept.key, group);
|
|
178
|
+
}
|
|
179
|
+
for (const [key, group] of byKey) {
|
|
180
|
+
const [first] = group;
|
|
181
|
+
if (
|
|
182
|
+
group.every(
|
|
183
|
+
(kept) =>
|
|
184
|
+
kept.needsShadow && isDeepStrictEqual(kept.original, first.original),
|
|
185
|
+
)
|
|
186
|
+
) {
|
|
187
|
+
const byKind = (ctx.shadows.identity ||= {});
|
|
188
|
+
byKind[key] = [first.original];
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const OCCURRENCE_SPEC = Object.freeze({
|
|
194
|
+
refId: "bom-ref",
|
|
195
|
+
location: true,
|
|
196
|
+
line: true,
|
|
197
|
+
offset: true,
|
|
198
|
+
symbol: true,
|
|
199
|
+
additionalContext: true,
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
/** occurrence → 1.x occurrence; an occurrenceReference has no 1.x form. */
|
|
203
|
+
function reverseOccurrence(ctx, value, pointer) {
|
|
204
|
+
if (isObjectRecord(value) && typeof value.ref === "string") {
|
|
205
|
+
addLoss(ctx, pointer, "occurrence reference has no 1.x form");
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
return reverseObject(ctx, "occurrence", value, pointer, OCCURRENCE_SPEC);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const FRAME_SPEC = Object.freeze({
|
|
212
|
+
package: true,
|
|
213
|
+
module: true,
|
|
214
|
+
function: true,
|
|
215
|
+
parameters: true,
|
|
216
|
+
line: true,
|
|
217
|
+
column: true,
|
|
218
|
+
fullFilename: true,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
const CALL_STACK_SPEC = Object.freeze({
|
|
222
|
+
frames: listOf((ctx, value, pointer) =>
|
|
223
|
+
reverseObject(ctx, "frame", value, pointer, FRAME_SPEC),
|
|
224
|
+
),
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
/** callStacks → the single 1.x `callstack`; further stacks are losses. */
|
|
228
|
+
function reverseCallStacks(ctx, value, pointer) {
|
|
229
|
+
if (!Array.isArray(value) || !value.length) {
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
for (let index = 1; index < value.length; index++) {
|
|
233
|
+
addLoss(
|
|
234
|
+
ctx,
|
|
235
|
+
jsonPointer(pointer, index),
|
|
236
|
+
"1.x evidence holds one call stack; only the first is kept",
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
return reverseObject(
|
|
240
|
+
ctx,
|
|
241
|
+
"callStack",
|
|
242
|
+
value[0],
|
|
243
|
+
jsonPointer(pointer, 0),
|
|
244
|
+
CALL_STACK_SPEC,
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const LICENSE_EVIDENCE_LICENSE_SPEC = Object.freeze({ id: true, name: true });
|
|
249
|
+
|
|
250
|
+
/** licenseEvidence → 1.x licenseChoice; its refId becomes the bom-ref. */
|
|
251
|
+
function reverseLicenseEvidence(ctx, value, pointer) {
|
|
252
|
+
if (!isObjectRecord(value)) {
|
|
253
|
+
addLoss(ctx, pointer, "license evidence is not an object");
|
|
254
|
+
return undefined;
|
|
255
|
+
}
|
|
256
|
+
const carried = { refId: true };
|
|
257
|
+
let choice;
|
|
258
|
+
if (isObjectRecord(value.license)) {
|
|
259
|
+
carried.license = true;
|
|
260
|
+
const license = reverseFields(
|
|
261
|
+
ctx,
|
|
262
|
+
"licenseEvidence.license",
|
|
263
|
+
value.license,
|
|
264
|
+
jsonPointer(pointer, "license"),
|
|
265
|
+
LICENSE_EVIDENCE_LICENSE_SPEC,
|
|
266
|
+
);
|
|
267
|
+
if (isNonEmptyString(value.refId)) {
|
|
268
|
+
license["bom-ref"] = value.refId;
|
|
269
|
+
}
|
|
270
|
+
choice = { license };
|
|
271
|
+
} else if (isNonEmptyString(value.expression)) {
|
|
272
|
+
carried.expression = true;
|
|
273
|
+
choice = { expression: value.expression };
|
|
274
|
+
if (isNonEmptyString(value.refId)) {
|
|
275
|
+
choice["bom-ref"] = value.refId;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
reverseFields(ctx, "licenseEvidence", value, pointer, carried);
|
|
279
|
+
return choice;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/** copyrightEvidence → 1.x copyright (`text` only). */
|
|
283
|
+
function reverseCopyrightEvidence(ctx, value, pointer) {
|
|
284
|
+
return reverseObject(ctx, "copyrightEvidence", value, pointer, {
|
|
285
|
+
text: true,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const EVIDENCE_SPEC = Object.freeze({
|
|
290
|
+
identity: listOf(reverseIdentityEvidence),
|
|
291
|
+
occurrences: listOf(reverseOccurrence),
|
|
292
|
+
callStacks: Object.freeze({ to: "callstack", convert: reverseCallStacks }),
|
|
293
|
+
licenses: listOf(reverseLicenseEvidence),
|
|
294
|
+
copyright: listOf(reverseCopyrightEvidence),
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* componentEvidence → 1.x evidence.
|
|
299
|
+
*
|
|
300
|
+
* @param {object} ctx Reader context
|
|
301
|
+
* @param {object} value 2.0 componentEvidence
|
|
302
|
+
* @param {string} pointer JSON pointer of `value`
|
|
303
|
+
* @returns {object|undefined} 1.x evidence
|
|
304
|
+
*/
|
|
305
|
+
export function reverseEvidence(ctx, value, pointer) {
|
|
306
|
+
return reverseObject(ctx, "evidence", value, pointer, EVIDENCE_SPEC);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/** A fingerprint: only the standard-hash branch exists in 1.x. */
|
|
310
|
+
function reverseFingerprint(ctx, value, pointer) {
|
|
311
|
+
if (isObjectRecord(value) && value.alg !== undefined) {
|
|
312
|
+
return reverseHash(ctx, value, pointer);
|
|
313
|
+
}
|
|
314
|
+
addLoss(ctx, pointer, "fingerprint is not a standard hash; 1.x has no field");
|
|
315
|
+
return undefined;
|
|
316
|
+
}
|
|
317
|
+
const FINGERPRINT_RULE = Object.freeze({ convert: reverseFingerprint });
|
|
318
|
+
|
|
319
|
+
const RELATED_ASSETS_RULE = listOf((ctx, value, pointer) =>
|
|
320
|
+
reverseObject(ctx, "relatedCryptographicAsset", value, pointer, {
|
|
321
|
+
type: true,
|
|
322
|
+
ref: true,
|
|
323
|
+
}),
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
/** implementationPlatform: a 2.0 list, one value in 1.x. */
|
|
327
|
+
function reverseImplementationPlatform(ctx, value, pointer) {
|
|
328
|
+
const platforms = Array.isArray(value) ? value : [value];
|
|
329
|
+
const allowed = ALGORITHM_PROPERTY_ENUMS_1X.implementationPlatform;
|
|
330
|
+
let kept;
|
|
331
|
+
platforms.forEach((platform, index) => {
|
|
332
|
+
const entryPointer = Array.isArray(value)
|
|
333
|
+
? jsonPointer(pointer, index)
|
|
334
|
+
: pointer;
|
|
335
|
+
if (kept === undefined && allowed.has(platform)) {
|
|
336
|
+
kept = platform;
|
|
337
|
+
} else {
|
|
338
|
+
addLoss(
|
|
339
|
+
ctx,
|
|
340
|
+
entryPointer,
|
|
341
|
+
allowed.has(platform)
|
|
342
|
+
? "1.x holds one implementationPlatform; only the first is kept"
|
|
343
|
+
: `implementationPlatform '${platform}' is not a 1.x value`,
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
return kept;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const ALGORITHM_SPEC = Object.freeze({
|
|
351
|
+
primitive: enumRule("primitive", ALGORITHM_PROPERTY_ENUMS_1X.primitive),
|
|
352
|
+
algorithmFamily: enumRule("algorithmFamily", ALGORITHM_FAMILY_1X),
|
|
353
|
+
parameterSetIdentifier: true,
|
|
354
|
+
ellipticCurve: enumRule("ellipticCurve", ELLIPTIC_CURVE_1X),
|
|
355
|
+
executionEnvironment: enumRule(
|
|
356
|
+
"executionEnvironment",
|
|
357
|
+
ALGORITHM_PROPERTY_ENUMS_1X.executionEnvironment,
|
|
358
|
+
),
|
|
359
|
+
implementationPlatform: Object.freeze({
|
|
360
|
+
convert: reverseImplementationPlatform,
|
|
361
|
+
}),
|
|
362
|
+
certificationLevel: true,
|
|
363
|
+
mode: enumRule("mode", ALGORITHM_PROPERTY_ENUMS_1X.mode),
|
|
364
|
+
padding: enumRule("padding", ALGORITHM_PROPERTY_ENUMS_1X.padding),
|
|
365
|
+
cryptoFunctions: enumListRule(
|
|
366
|
+
"cryptoFunctions",
|
|
367
|
+
ALGORITHM_PROPERTY_ENUMS_1X.cryptoFunctions,
|
|
368
|
+
),
|
|
369
|
+
classicalSecurityLevel: true,
|
|
370
|
+
nistQuantumSecurityLevel: true,
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
const CERTIFICATE_SPEC = Object.freeze({
|
|
374
|
+
serialNumber: true,
|
|
375
|
+
subjectName: true,
|
|
376
|
+
issuerName: true,
|
|
377
|
+
notValidBefore: true,
|
|
378
|
+
notValidAfter: true,
|
|
379
|
+
signatureAlgorithmRef: true,
|
|
380
|
+
subjectPublicKeyRef: true,
|
|
381
|
+
certificateFormat: true,
|
|
382
|
+
certificateExtension: true,
|
|
383
|
+
certificateFileExtension: true,
|
|
384
|
+
fingerprint: FINGERPRINT_RULE,
|
|
385
|
+
certificateState: true,
|
|
386
|
+
creationDate: true,
|
|
387
|
+
activationDate: true,
|
|
388
|
+
deactivationDate: true,
|
|
389
|
+
revocationDate: true,
|
|
390
|
+
destructionDate: true,
|
|
391
|
+
certificateExtensions: true,
|
|
392
|
+
relatedCryptographicAssets: RELATED_ASSETS_RULE,
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
/** securedBy.algorithmRef: a 2.0 list of refIds, one refType in 1.x. */
|
|
396
|
+
function reverseSecuredByRef(ctx, value, pointer) {
|
|
397
|
+
if (typeof value === "string") {
|
|
398
|
+
return value;
|
|
399
|
+
}
|
|
400
|
+
const refs = Array.isArray(value) ? value : [];
|
|
401
|
+
for (let index = 1; index < refs.length; index++) {
|
|
402
|
+
addLoss(
|
|
403
|
+
ctx,
|
|
404
|
+
jsonPointer(pointer, index),
|
|
405
|
+
"1.x securedBy holds one algorithmRef; only the first is kept",
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
return typeof refs[0] === "string" ? refs[0] : undefined;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const RELATED_SPEC = Object.freeze({
|
|
412
|
+
type: true,
|
|
413
|
+
id: true,
|
|
414
|
+
state: true,
|
|
415
|
+
algorithmRef: true,
|
|
416
|
+
creationDate: true,
|
|
417
|
+
activationDate: true,
|
|
418
|
+
updateDate: true,
|
|
419
|
+
expirationDate: true,
|
|
420
|
+
value: true,
|
|
421
|
+
size: true,
|
|
422
|
+
format: true,
|
|
423
|
+
securedBy: objectOf("securedBy", {
|
|
424
|
+
mechanism: true,
|
|
425
|
+
algorithmRef: Object.freeze({ convert: reverseSecuredByRef }),
|
|
426
|
+
}),
|
|
427
|
+
fingerprint: FINGERPRINT_RULE,
|
|
428
|
+
relatedCryptographicAssets: RELATED_ASSETS_RULE,
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
const PROTOCOL_SPEC = Object.freeze({
|
|
432
|
+
type: enumRule("protocolProperties.type", PROTOCOL_TYPES_1X),
|
|
433
|
+
version: true,
|
|
434
|
+
cipherSuites: true,
|
|
435
|
+
ikev2TransformTypes: true,
|
|
436
|
+
cryptoRefArray: true,
|
|
437
|
+
relatedCryptographicAssets: RELATED_ASSETS_RULE,
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
const CRYPTO_SPEC = Object.freeze({
|
|
441
|
+
assetType: true,
|
|
442
|
+
algorithmProperties: objectOf("algorithmProperties", ALGORITHM_SPEC),
|
|
443
|
+
certificateProperties: objectOf("certificateProperties", CERTIFICATE_SPEC),
|
|
444
|
+
relatedCryptoMaterialProperties: objectOf(
|
|
445
|
+
"relatedCryptoMaterialProperties",
|
|
446
|
+
RELATED_SPEC,
|
|
447
|
+
),
|
|
448
|
+
protocolProperties: objectOf("protocolProperties", PROTOCOL_SPEC),
|
|
449
|
+
oid: true,
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* cryptoProperties → 1.x cryptoProperties: list-valued
|
|
454
|
+
* `implementationPlatform` and `securedBy.algorithmRef` become one value,
|
|
455
|
+
* enum values 1.7 does not list are dropped, and 2.0-only members
|
|
456
|
+
* (`secProperties`, `renewal`, `rotation`, `keyUsage`, non-hash
|
|
457
|
+
* fingerprints) are losses.
|
|
458
|
+
*
|
|
459
|
+
* @param {object} ctx Reader context
|
|
460
|
+
* @param {object} value 2.0 cryptoProperties
|
|
461
|
+
* @param {string} pointer JSON pointer of `value`
|
|
462
|
+
* @returns {object|undefined} 1.x cryptoProperties
|
|
463
|
+
*/
|
|
464
|
+
export function reverseCryptoProperties(ctx, value, pointer) {
|
|
465
|
+
return reverseObject(ctx, "cryptoProperties", value, pointer, CRYPTO_SPEC);
|
|
466
|
+
}
|