@cyclonedx/cdxgen 12.3.3 → 12.4.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 +64 -22
- package/bin/audit.js +21 -7
- package/bin/cdxgen.js +238 -116
- package/bin/convert.js +28 -13
- package/bin/hbom.js +490 -0
- package/bin/repl.js +580 -29
- package/bin/validate.js +34 -4
- package/bin/verify.js +40 -5
- package/data/README.md +298 -25
- package/data/component-tags.json +6 -0
- package/data/crypto-oid.json +16 -0
- package/data/predictive-audit-allowlist.json +11 -0
- package/data/queries-darwin.json +12 -1
- package/data/queries-win.json +7 -1
- package/data/queries.json +39 -2
- package/data/rules/ai-agent-governance.yaml +16 -0
- package/data/rules/asar-archives.yaml +150 -0
- package/data/rules/chrome-extensions.yaml +8 -0
- package/data/rules/ci-permissions.yaml +42 -18
- package/data/rules/container-risk.yaml +14 -7
- package/data/rules/dependency-sources.yaml +11 -0
- package/data/rules/hbom-compliance.yaml +325 -0
- package/data/rules/hbom-performance.yaml +307 -0
- package/data/rules/hbom-security.yaml +248 -0
- package/data/rules/host-topology.yaml +165 -0
- package/data/rules/mcp-servers.yaml +18 -3
- package/data/rules/obom-runtime.yaml +907 -22
- package/data/rules/package-integrity.yaml +14 -0
- package/data/rules/rootfs-hardening.yaml +179 -0
- package/data/rules/vscode-extensions.yaml +9 -0
- package/lib/audit/index.js +209 -8
- package/lib/audit/index.poku.js +332 -0
- package/lib/audit/reporters.js +222 -0
- package/lib/audit/targets.js +146 -1
- package/lib/audit/targets.poku.js +186 -0
- package/lib/cli/asar.poku.js +328 -0
- package/lib/cli/index.js +506 -88
- package/lib/cli/index.poku.js +1352 -212
- package/lib/evinser/evinser.js +14 -9
- package/lib/helpers/analyzer.js +1406 -29
- package/lib/helpers/analyzer.poku.js +342 -0
- package/lib/helpers/analyzerScope.js +712 -0
- package/lib/helpers/asarutils.js +1556 -0
- package/lib/helpers/asarutils.poku.js +443 -0
- package/lib/helpers/auditCategories.js +12 -0
- package/lib/helpers/auditCategories.poku.js +32 -0
- package/lib/helpers/cbomutils.js +271 -1
- package/lib/helpers/cbomutils.poku.js +248 -5
- package/lib/helpers/display.js +291 -1
- package/lib/helpers/display.poku.js +149 -0
- package/lib/helpers/evidenceUtils.js +58 -0
- package/lib/helpers/evidenceUtils.poku.js +54 -0
- package/lib/helpers/exportUtils.js +9 -0
- package/lib/helpers/gtfobins.js +142 -8
- package/lib/helpers/gtfobins.poku.js +24 -1
- package/lib/helpers/hbom.js +710 -0
- package/lib/helpers/hbom.poku.js +496 -0
- package/lib/helpers/hbomAnalysis.js +268 -0
- package/lib/helpers/hbomAnalysis.poku.js +249 -0
- package/lib/helpers/hbomLoader.js +35 -0
- package/lib/helpers/hostTopology.js +803 -0
- package/lib/helpers/hostTopology.poku.js +363 -0
- package/lib/helpers/inventoryStats.js +69 -0
- package/lib/helpers/inventoryStats.poku.js +86 -0
- package/lib/helpers/lolbas.js +19 -1
- package/lib/helpers/lolbas.poku.js +23 -0
- package/lib/helpers/osqueryTransform.js +47 -0
- package/lib/helpers/osqueryTransform.poku.js +47 -0
- package/lib/helpers/plugins.js +349 -0
- package/lib/helpers/plugins.poku.js +57 -0
- package/lib/helpers/protobom.js +156 -45
- package/lib/helpers/protobom.poku.js +140 -5
- package/lib/helpers/remote/dependency-track.js +36 -3
- package/lib/helpers/remote/dependency-track.poku.js +44 -0
- package/lib/helpers/source.js +24 -0
- package/lib/helpers/source.poku.js +32 -0
- package/lib/helpers/utils.js +1438 -93
- package/lib/helpers/utils.poku.js +846 -4
- package/lib/managers/binary.e2e.poku.js +367 -0
- package/lib/managers/binary.js +2293 -353
- package/lib/managers/binary.poku.js +1699 -1
- package/lib/managers/docker.js +201 -79
- package/lib/managers/docker.poku.js +337 -12
- package/lib/server/server.js +2 -27
- package/lib/stages/postgen/annotator.js +38 -0
- package/lib/stages/postgen/annotator.poku.js +107 -1
- package/lib/stages/postgen/auditBom.js +121 -18
- package/lib/stages/postgen/auditBom.poku.js +1366 -31
- package/lib/stages/postgen/hostTopologyAudit.poku.js +186 -0
- package/lib/stages/postgen/postgen.js +192 -1
- package/lib/stages/postgen/postgen.poku.js +321 -0
- package/lib/stages/postgen/ruleEngine.js +116 -0
- package/lib/stages/pregen/envAudit.js +14 -3
- package/package.json +23 -21
- package/types/bin/hbom.d.ts +3 -0
- package/types/bin/hbom.d.ts.map +1 -0
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts +44 -0
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/audit/reporters.d.ts +16 -0
- package/types/lib/audit/reporters.d.ts.map +1 -1
- package/types/lib/audit/targets.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts +16 -0
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/evinser/evinser.d.ts +4 -0
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/helpers/analyzer.d.ts +33 -0
- package/types/lib/helpers/analyzer.d.ts.map +1 -1
- package/types/lib/helpers/analyzerScope.d.ts +11 -0
- package/types/lib/helpers/analyzerScope.d.ts.map +1 -0
- package/types/lib/helpers/asarutils.d.ts +34 -0
- package/types/lib/helpers/asarutils.d.ts.map +1 -0
- package/types/lib/helpers/auditCategories.d.ts +5 -0
- package/types/lib/helpers/auditCategories.d.ts.map +1 -1
- package/types/lib/helpers/cbomutils.d.ts +3 -2
- package/types/lib/helpers/cbomutils.d.ts.map +1 -1
- package/types/lib/helpers/display.d.ts.map +1 -1
- package/types/lib/helpers/evidenceUtils.d.ts +8 -0
- package/types/lib/helpers/evidenceUtils.d.ts.map +1 -0
- package/types/lib/helpers/exportUtils.d.ts.map +1 -1
- package/types/lib/helpers/gtfobins.d.ts +8 -0
- package/types/lib/helpers/gtfobins.d.ts.map +1 -1
- package/types/lib/helpers/hbom.d.ts +49 -0
- package/types/lib/helpers/hbom.d.ts.map +1 -0
- package/types/lib/helpers/hbomAnalysis.d.ts +62 -0
- package/types/lib/helpers/hbomAnalysis.d.ts.map +1 -0
- package/types/lib/helpers/hbomLoader.d.ts +7 -0
- package/types/lib/helpers/hbomLoader.d.ts.map +1 -0
- package/types/lib/helpers/hostTopology.d.ts +12 -0
- package/types/lib/helpers/hostTopology.d.ts.map +1 -0
- package/types/lib/helpers/inventoryStats.d.ts +11 -0
- package/types/lib/helpers/inventoryStats.d.ts.map +1 -0
- package/types/lib/helpers/lolbas.d.ts.map +1 -1
- package/types/lib/helpers/osqueryTransform.d.ts +3 -0
- package/types/lib/helpers/osqueryTransform.d.ts.map +1 -1
- package/types/lib/helpers/plugins.d.ts +58 -0
- package/types/lib/helpers/plugins.d.ts.map +1 -0
- package/types/lib/helpers/protobom.d.ts +3 -4
- package/types/lib/helpers/protobom.d.ts.map +1 -1
- package/types/lib/helpers/remote/dependency-track.d.ts +10 -3
- package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -1
- package/types/lib/helpers/source.d.ts.map +1 -1
- package/types/lib/helpers/utils.d.ts +45 -8
- package/types/lib/helpers/utils.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts +5 -0
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/server/server.d.ts +2 -1
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
- package/types/lib/stages/postgen/auditBom.d.ts +26 -1
- package/types/lib/stages/postgen/auditBom.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts +2 -1
- 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/pregen/envAudit.d.ts.map +1 -1
- package/data/spdx-model-v3.0.1.jsonld +0 -15999
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
|
|
4
|
+
import { assert, describe, it } from "poku";
|
|
5
|
+
|
|
6
|
+
import { evaluateRule, loadRules } from "./ruleEngine.js";
|
|
7
|
+
|
|
8
|
+
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
9
|
+
const RULES_DIR = join(__dirname, "..", "..", "..", "data", "rules");
|
|
10
|
+
|
|
11
|
+
function makeProperty(name, value) {
|
|
12
|
+
return { name, value };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function makeHostBom(
|
|
16
|
+
components = [],
|
|
17
|
+
metadataProperties = [],
|
|
18
|
+
bomProperties = [],
|
|
19
|
+
) {
|
|
20
|
+
return {
|
|
21
|
+
bomFormat: "CycloneDX",
|
|
22
|
+
specVersion: "1.7",
|
|
23
|
+
serialNumber: "urn:uuid:test-host-view",
|
|
24
|
+
metadata: {
|
|
25
|
+
tools: {
|
|
26
|
+
components: [
|
|
27
|
+
{
|
|
28
|
+
type: "application",
|
|
29
|
+
name: "cdxgen",
|
|
30
|
+
version: "12.4.0",
|
|
31
|
+
"bom-ref": "pkg:npm/%40cyclonedx/cdxgen@12.4.0",
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
component: {
|
|
36
|
+
name: "test-host",
|
|
37
|
+
type: "device",
|
|
38
|
+
"bom-ref": "urn:uuid:test-host",
|
|
39
|
+
properties: metadataProperties.map(([k, v]) => makeProperty(k, v)),
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
components,
|
|
43
|
+
properties: bomProperties.map(([k, v]) => makeProperty(k, v)),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function makeHbomComponent(name, hardwareClass, properties = []) {
|
|
48
|
+
return {
|
|
49
|
+
type: "device",
|
|
50
|
+
name,
|
|
51
|
+
"bom-ref": `urn:uuid:${hardwareClass}:${name}`,
|
|
52
|
+
properties: [
|
|
53
|
+
makeProperty("cdx:hbom:hardwareClass", hardwareClass),
|
|
54
|
+
...properties.map(([k, v]) => makeProperty(k, v)),
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function makeOsqueryComponent(name, queryCategory, properties = []) {
|
|
60
|
+
return {
|
|
61
|
+
type: "data",
|
|
62
|
+
name,
|
|
63
|
+
"bom-ref": `osquery:${queryCategory}:${name}`,
|
|
64
|
+
properties: [
|
|
65
|
+
makeProperty("cdx:osquery:category", queryCategory),
|
|
66
|
+
...properties.map(([k, v]) => makeProperty(k, v)),
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
describe("host-topology audit rules", () => {
|
|
72
|
+
it("detects weak wireless security when live runtime addresses confirm the link is active (HMX-002)", async () => {
|
|
73
|
+
const rules = await loadRules(RULES_DIR);
|
|
74
|
+
const rule = rules.find((candidate) => candidate.id === "HMX-002");
|
|
75
|
+
assert.ok(rule, "HMX-002 should be present");
|
|
76
|
+
|
|
77
|
+
const bom = makeHostBom(
|
|
78
|
+
[
|
|
79
|
+
makeHbomComponent("wlp2s0", "wireless-adapter", [
|
|
80
|
+
["cdx:hbom:securityMode", "open"],
|
|
81
|
+
["cdx:hostview:interface_addresses:count", "1"],
|
|
82
|
+
["cdx:hostview:linkedRuntimeCategory", "interface_addresses"],
|
|
83
|
+
]),
|
|
84
|
+
makeOsqueryComponent("192.168.1.55", "interface_addresses", [
|
|
85
|
+
["interface", "wlp2s0"],
|
|
86
|
+
["address", "192.168.1.55"],
|
|
87
|
+
]),
|
|
88
|
+
],
|
|
89
|
+
[["cdx:hbom:platform", "linux"]],
|
|
90
|
+
[
|
|
91
|
+
["cdx:hostview:mode", "hbom-obom-merged"],
|
|
92
|
+
["cdx:hostview:topologyLinkCount", "1"],
|
|
93
|
+
],
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
const findings = await evaluateRule(rule, bom);
|
|
97
|
+
assert.strictEqual(findings.length, 1);
|
|
98
|
+
assert.strictEqual(findings[0].ruleId, "HMX-002");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("detects merged host inventories that still have zero strict topology links (HMX-003)", async () => {
|
|
102
|
+
const rules = await loadRules(RULES_DIR);
|
|
103
|
+
const rule = rules.find((candidate) => candidate.id === "HMX-003");
|
|
104
|
+
assert.ok(rule, "HMX-003 should be present");
|
|
105
|
+
|
|
106
|
+
const bom = makeHostBom(
|
|
107
|
+
[makeHbomComponent("enp1s0", "network-interface")],
|
|
108
|
+
[
|
|
109
|
+
["cdx:hbom:platform", "linux"],
|
|
110
|
+
["cdx:hostview:mode", "hbom-obom-merged"],
|
|
111
|
+
["cdx:hostview:hardwareComponentCount", "1"],
|
|
112
|
+
["cdx:hostview:runtimeComponentCount", "2"],
|
|
113
|
+
["cdx:hostview:topologyLinkCount", "0"],
|
|
114
|
+
],
|
|
115
|
+
[
|
|
116
|
+
["cdx:hostview:mode", "hbom-obom-merged"],
|
|
117
|
+
["cdx:hostview:hardwareComponentCount", "1"],
|
|
118
|
+
["cdx:hostview:runtimeComponentCount", "2"],
|
|
119
|
+
["cdx:hostview:topologyLinkCount", "0"],
|
|
120
|
+
],
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
const findings = await evaluateRule(rule, bom);
|
|
124
|
+
assert.strictEqual(findings.length, 1);
|
|
125
|
+
assert.strictEqual(findings[0].ruleId, "HMX-003");
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("detects degraded storage when explicit runtime mount evidence shows the device is in use (HMX-004)", async () => {
|
|
129
|
+
const rules = await loadRules(RULES_DIR);
|
|
130
|
+
const rule = rules.find((candidate) => candidate.id === "HMX-004");
|
|
131
|
+
assert.ok(rule, "HMX-004 should be present");
|
|
132
|
+
|
|
133
|
+
const bom = makeHostBom(
|
|
134
|
+
[
|
|
135
|
+
makeHbomComponent("nvme0", "storage", [
|
|
136
|
+
["cdx:hbom:smartStatus", "Failing"],
|
|
137
|
+
["cdx:hbom:wearPercentageUsed", "92"],
|
|
138
|
+
["cdx:hostview:mount_hardening:count", "1"],
|
|
139
|
+
["cdx:hostview:runtime-storage:count", "1"],
|
|
140
|
+
]),
|
|
141
|
+
makeOsqueryComponent("/home", "mount_hardening", [
|
|
142
|
+
["device", "/dev/nvme0n1"],
|
|
143
|
+
["path", "/home"],
|
|
144
|
+
]),
|
|
145
|
+
],
|
|
146
|
+
[["cdx:hbom:platform", "linux"]],
|
|
147
|
+
[
|
|
148
|
+
["cdx:hostview:mode", "hbom-obom-merged"],
|
|
149
|
+
["cdx:hostview:topologyLinkCount", "2"],
|
|
150
|
+
],
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
const findings = await evaluateRule(rule, bom);
|
|
154
|
+
assert.strictEqual(findings.length, 1);
|
|
155
|
+
assert.strictEqual(findings[0].ruleId, "HMX-004");
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it("detects revoked secure boot trust anchors only after an explicit HBOM trust link exists (HMX-005)", async () => {
|
|
159
|
+
const rules = await loadRules(RULES_DIR);
|
|
160
|
+
const rule = rules.find((candidate) => candidate.id === "HMX-005");
|
|
161
|
+
assert.ok(rule, "HMX-005 should be present");
|
|
162
|
+
|
|
163
|
+
const bom = makeHostBom(
|
|
164
|
+
[
|
|
165
|
+
makeOsqueryComponent("dbx-entry", "secureboot_certificates", [
|
|
166
|
+
["revoked", "1"],
|
|
167
|
+
["sha1", "db-cert-1"],
|
|
168
|
+
["subject", "CN=Legacy Bootloader"],
|
|
169
|
+
]),
|
|
170
|
+
],
|
|
171
|
+
[
|
|
172
|
+
["cdx:hbom:platform", "linux"],
|
|
173
|
+
["cdx:hostview:secureboot_certificates:count", "1"],
|
|
174
|
+
],
|
|
175
|
+
[
|
|
176
|
+
["cdx:hostview:mode", "hbom-obom-merged"],
|
|
177
|
+
["cdx:hostview:secureboot_certificates:count", "1"],
|
|
178
|
+
["cdx:hostview:topologyLinkCount", "1"],
|
|
179
|
+
],
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
const findings = await evaluateRule(rule, bom);
|
|
183
|
+
assert.strictEqual(findings.length, 1);
|
|
184
|
+
assert.strictEqual(findings[0].ruleId, "HMX-005");
|
|
185
|
+
});
|
|
186
|
+
});
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from "../../helpers/aiInventory.js";
|
|
12
12
|
import { mergeDependencies, mergeServices } from "../../helpers/depsUtils.js";
|
|
13
13
|
import { addFormulationSection } from "../../helpers/formulationParsers.js";
|
|
14
|
+
import { getContainerFileInventoryStats } from "../../helpers/inventoryStats.js";
|
|
14
15
|
import { thoughtLog } from "../../helpers/logger.js";
|
|
15
16
|
import { buildReleaseNotesFromGit } from "../../helpers/source.js";
|
|
16
17
|
import {
|
|
@@ -78,6 +79,8 @@ function applyFormulation(bomJson, options, filePath, formulationList) {
|
|
|
78
79
|
}
|
|
79
80
|
const context = formulationList?.length ? { formulationList } : {};
|
|
80
81
|
setActivityContext({
|
|
82
|
+
bomMutation: "formulation",
|
|
83
|
+
capability: "bom-mutation",
|
|
81
84
|
projectType: "Formulation",
|
|
82
85
|
sourcePath: filePath || options.filePath || process.cwd(),
|
|
83
86
|
});
|
|
@@ -141,6 +144,22 @@ const SIGNED_URL_PARAM_NAMES = new Set([
|
|
|
141
144
|
"x-amz-signature",
|
|
142
145
|
"x-goog-signature",
|
|
143
146
|
]);
|
|
147
|
+
const COMPONENT_1_6_ONLY_FIELDS = new Set([
|
|
148
|
+
"authors",
|
|
149
|
+
"manufacturer",
|
|
150
|
+
"omniborId",
|
|
151
|
+
"swhid",
|
|
152
|
+
"tags",
|
|
153
|
+
]);
|
|
154
|
+
const COMPONENT_1_7_ONLY_FIELDS = new Set([
|
|
155
|
+
"isExternal",
|
|
156
|
+
"patentAssertions",
|
|
157
|
+
"versionRange",
|
|
158
|
+
]);
|
|
159
|
+
const SERVICE_1_6_ONLY_FIELDS = new Set(["tags"]);
|
|
160
|
+
const SERVICE_1_7_ONLY_FIELDS = new Set(["patentAssertions"]);
|
|
161
|
+
const METADATA_1_6_ONLY_FIELDS = new Set(["manufacturer"]);
|
|
162
|
+
const METADATA_1_7_ONLY_FIELDS = new Set(["distributionConstraints"]);
|
|
144
163
|
|
|
145
164
|
function normalizeSpecVersion(specVersion) {
|
|
146
165
|
return Number.parseFloat(String(specVersion || 0));
|
|
@@ -292,11 +311,171 @@ function validateTlpClassification(bomJson, options) {
|
|
|
292
311
|
return bomJson;
|
|
293
312
|
}
|
|
294
313
|
|
|
314
|
+
function applyContainerInventoryMetadata(bomJson) {
|
|
315
|
+
if (!bomJson?.metadata) {
|
|
316
|
+
return bomJson;
|
|
317
|
+
}
|
|
318
|
+
const { unpackagedExecutableCount, unpackagedSharedLibraryCount } =
|
|
319
|
+
getContainerFileInventoryStats(bomJson.components);
|
|
320
|
+
const metadataProperties = Array.isArray(bomJson.metadata.properties)
|
|
321
|
+
? [...bomJson.metadata.properties]
|
|
322
|
+
: [];
|
|
323
|
+
const propertyNamesToReplace = new Set([
|
|
324
|
+
"cdx:container:unpackagedExecutableCount",
|
|
325
|
+
"cdx:container:unpackagedSharedLibraryCount",
|
|
326
|
+
]);
|
|
327
|
+
const retainedProperties = metadataProperties.filter(
|
|
328
|
+
(property) => !propertyNamesToReplace.has(property?.name),
|
|
329
|
+
);
|
|
330
|
+
if (
|
|
331
|
+
unpackagedExecutableCount ||
|
|
332
|
+
metadataProperties.some(
|
|
333
|
+
(property) =>
|
|
334
|
+
property?.name === "cdx:container:unpackagedExecutableCount",
|
|
335
|
+
)
|
|
336
|
+
) {
|
|
337
|
+
retainedProperties.push({
|
|
338
|
+
name: "cdx:container:unpackagedExecutableCount",
|
|
339
|
+
value: String(unpackagedExecutableCount),
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
if (
|
|
343
|
+
unpackagedSharedLibraryCount ||
|
|
344
|
+
metadataProperties.some(
|
|
345
|
+
(property) =>
|
|
346
|
+
property?.name === "cdx:container:unpackagedSharedLibraryCount",
|
|
347
|
+
)
|
|
348
|
+
) {
|
|
349
|
+
retainedProperties.push({
|
|
350
|
+
name: "cdx:container:unpackagedSharedLibraryCount",
|
|
351
|
+
value: String(unpackagedSharedLibraryCount),
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
if (retainedProperties.length) {
|
|
355
|
+
bomJson.metadata.properties = retainedProperties;
|
|
356
|
+
}
|
|
357
|
+
return bomJson;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function deleteFields(subject, fields) {
|
|
361
|
+
if (!subject || typeof subject !== "object") {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
for (const fieldName of fields) {
|
|
365
|
+
delete subject[fieldName];
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function normalizeComponentForSpecVersion(subject, specVersion) {
|
|
370
|
+
if (specVersion < 1.6) {
|
|
371
|
+
deleteFields(subject, COMPONENT_1_6_ONLY_FIELDS);
|
|
372
|
+
}
|
|
373
|
+
if (specVersion < 1.7) {
|
|
374
|
+
deleteFields(subject, COMPONENT_1_7_ONLY_FIELDS);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function normalizeServiceForSpecVersion(subject, specVersion) {
|
|
379
|
+
if (specVersion < 1.6) {
|
|
380
|
+
deleteFields(subject, SERVICE_1_6_ONLY_FIELDS);
|
|
381
|
+
}
|
|
382
|
+
if (specVersion < 1.7) {
|
|
383
|
+
deleteFields(subject, SERVICE_1_7_ONLY_FIELDS);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function normalizeMetadataForSpecVersion(subject, specVersion) {
|
|
388
|
+
if (specVersion < 1.6) {
|
|
389
|
+
deleteFields(subject, METADATA_1_6_ONLY_FIELDS);
|
|
390
|
+
}
|
|
391
|
+
if (specVersion < 1.7) {
|
|
392
|
+
deleteFields(subject, METADATA_1_7_ONLY_FIELDS);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function downgradeSubjectForSpecVersion(subject, specVersion, parentKey) {
|
|
397
|
+
if (!subject || typeof subject !== "object") {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
if (Array.isArray(subject)) {
|
|
401
|
+
subject.forEach((entry) => {
|
|
402
|
+
downgradeSubjectForSpecVersion(entry, specVersion, parentKey);
|
|
403
|
+
});
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
if (parentKey === "metadata") {
|
|
407
|
+
normalizeMetadataForSpecVersion(subject, specVersion);
|
|
408
|
+
}
|
|
409
|
+
if (parentKey === "component" || parentKey === "components") {
|
|
410
|
+
normalizeComponentForSpecVersion(subject, specVersion);
|
|
411
|
+
}
|
|
412
|
+
if (parentKey === "service" || parentKey === "services") {
|
|
413
|
+
normalizeServiceForSpecVersion(subject, specVersion);
|
|
414
|
+
}
|
|
415
|
+
if (specVersion < 1.6) {
|
|
416
|
+
if (subject.cryptoProperties) {
|
|
417
|
+
delete subject.cryptoProperties;
|
|
418
|
+
}
|
|
419
|
+
if (
|
|
420
|
+
subject?.evidence?.occurrences &&
|
|
421
|
+
Array.isArray(subject.evidence.occurrences)
|
|
422
|
+
) {
|
|
423
|
+
subject.evidence.occurrences.forEach((occurrence) => {
|
|
424
|
+
delete occurrence.line;
|
|
425
|
+
delete occurrence.offset;
|
|
426
|
+
delete occurrence.symbol;
|
|
427
|
+
delete occurrence.additionalContext;
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
if (
|
|
431
|
+
subject?.evidence?.identity &&
|
|
432
|
+
Array.isArray(subject.evidence.identity)
|
|
433
|
+
) {
|
|
434
|
+
subject.evidence.identity = subject.evidence.identity[0];
|
|
435
|
+
if (subject.evidence.identity?.concludedValue) {
|
|
436
|
+
delete subject.evidence.identity.concludedValue;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
} else if (
|
|
440
|
+
specVersion < 1.7 &&
|
|
441
|
+
subject.cryptoProperties?.assetType === "certificate" &&
|
|
442
|
+
subject.cryptoProperties.certificateProperties
|
|
443
|
+
) {
|
|
444
|
+
const certificateProperties =
|
|
445
|
+
subject.cryptoProperties.certificateProperties;
|
|
446
|
+
if (
|
|
447
|
+
!certificateProperties.certificateExtension &&
|
|
448
|
+
certificateProperties.certificateFileExtension
|
|
449
|
+
) {
|
|
450
|
+
certificateProperties.certificateExtension =
|
|
451
|
+
certificateProperties.certificateFileExtension;
|
|
452
|
+
}
|
|
453
|
+
delete certificateProperties.serialNumber;
|
|
454
|
+
delete certificateProperties.certificateFileExtension;
|
|
455
|
+
delete certificateProperties.fingerprint;
|
|
456
|
+
}
|
|
457
|
+
Object.entries(subject).forEach(([key, value]) => {
|
|
458
|
+
downgradeSubjectForSpecVersion(value, specVersion, key);
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
function applySpecVersionCompatibility(bomJson, options) {
|
|
463
|
+
const specVersion = normalizeSpecVersion(
|
|
464
|
+
options?.specVersion || bomJson?.specVersion || 1.7,
|
|
465
|
+
);
|
|
466
|
+
if (specVersion >= 1.7) {
|
|
467
|
+
return bomJson;
|
|
468
|
+
}
|
|
469
|
+
downgradeSubjectForSpecVersion(bomJson, specVersion);
|
|
470
|
+
return bomJson;
|
|
471
|
+
}
|
|
472
|
+
|
|
295
473
|
/**
|
|
296
474
|
* Filter and enhance BOM post generation.
|
|
297
475
|
*
|
|
298
476
|
* @param {Object} bomNSData BOM with namespaces object
|
|
299
477
|
* @param {Object} options CLI options
|
|
478
|
+
* @param {string} [filePath] Source path used for formulation and metadata context
|
|
300
479
|
*
|
|
301
480
|
* @returns {Object} Modified bomNSData
|
|
302
481
|
*/
|
|
@@ -312,6 +491,7 @@ export function postProcess(bomNSData, options, filePath) {
|
|
|
312
491
|
bomNSData.bomJson = filterBom(jsonPayload, options);
|
|
313
492
|
bomNSData.bomJson = applyStandards(bomNSData.bomJson, options);
|
|
314
493
|
bomNSData.bomJson = applyMetadata(bomNSData.bomJson, options);
|
|
494
|
+
bomNSData.bomJson = applyContainerInventoryMetadata(bomNSData.bomJson);
|
|
315
495
|
bomNSData.bomJson = applyFormulation(
|
|
316
496
|
bomNSData.bomJson,
|
|
317
497
|
options,
|
|
@@ -319,10 +499,21 @@ export function postProcess(bomNSData, options, filePath) {
|
|
|
319
499
|
bomNSData.formulationList,
|
|
320
500
|
);
|
|
321
501
|
bomNSData.bomJson = applyReleaseNotes(bomNSData.bomJson, options, filePath);
|
|
502
|
+
bomNSData.bomJson = applySpecVersionCompatibility(bomNSData.bomJson, options);
|
|
322
503
|
bomNSData.bomJson = validateTlpClassification(bomNSData.bomJson, options);
|
|
323
504
|
// Support for automatic annotations
|
|
324
505
|
if (options.specVersion >= 1.6) {
|
|
325
|
-
|
|
506
|
+
setActivityContext({
|
|
507
|
+
bomMutation: "annotations",
|
|
508
|
+
capability: "bom-mutation",
|
|
509
|
+
projectType: "Annotations",
|
|
510
|
+
sourcePath: filePath || options.filePath || process.cwd(),
|
|
511
|
+
});
|
|
512
|
+
try {
|
|
513
|
+
bomNSData.bomJson = annotate(bomNSData.bomJson, options);
|
|
514
|
+
} finally {
|
|
515
|
+
resetActivityContext();
|
|
516
|
+
}
|
|
326
517
|
}
|
|
327
518
|
cleanupEnv(options);
|
|
328
519
|
cleanupTmpDir();
|