@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
package/bin/repl.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import process from "node:process";
|
|
@@ -21,6 +21,17 @@ import {
|
|
|
21
21
|
printTable,
|
|
22
22
|
printVulnerabilities,
|
|
23
23
|
} from "../lib/helpers/display.js";
|
|
24
|
+
import {
|
|
25
|
+
formatHbomHardwareClassSummary,
|
|
26
|
+
getHbomSummary,
|
|
27
|
+
isHbomLikeBom,
|
|
28
|
+
} from "../lib/helpers/hbomAnalysis.js";
|
|
29
|
+
import {
|
|
30
|
+
getPropertyValue,
|
|
31
|
+
getSourceDerivedCryptoComponents,
|
|
32
|
+
getUnpackagedExecutableComponents,
|
|
33
|
+
getUnpackagedSharedLibraryComponents,
|
|
34
|
+
} from "../lib/helpers/inventoryStats.js";
|
|
24
35
|
import { readBinary } from "../lib/helpers/protobom.js";
|
|
25
36
|
import {
|
|
26
37
|
getProvenanceComponents,
|
|
@@ -28,7 +39,14 @@ import {
|
|
|
28
39
|
} from "../lib/helpers/provenanceUtils.js";
|
|
29
40
|
import { toCycloneDxLikeBom } from "../lib/helpers/spdxUtils.js";
|
|
30
41
|
import { table } from "../lib/helpers/table.js";
|
|
31
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
getTmpDir,
|
|
44
|
+
isDryRun,
|
|
45
|
+
safeExistsSync,
|
|
46
|
+
safeMkdirSync,
|
|
47
|
+
safeMkdtempSync,
|
|
48
|
+
safeWriteSync,
|
|
49
|
+
} from "../lib/helpers/utils.js";
|
|
32
50
|
import { getBomWithOras } from "../lib/managers/oci.js";
|
|
33
51
|
import { validateBom } from "../lib/validator/bomValidator.js";
|
|
34
52
|
|
|
@@ -55,7 +73,7 @@ const cdxArt = `
|
|
|
55
73
|
|
|
56
74
|
console.log(cdxArt);
|
|
57
75
|
|
|
58
|
-
if (process.env
|
|
76
|
+
if (process.env.CDXGEN_NODE_OPTIONS) {
|
|
59
77
|
process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS || ""} ${process.env.CDXGEN_NODE_OPTIONS}`;
|
|
60
78
|
}
|
|
61
79
|
|
|
@@ -63,6 +81,23 @@ if (process.env?.CDXGEN_NODE_OPTIONS) {
|
|
|
63
81
|
let sbom;
|
|
64
82
|
const getInteractiveBom = () => toCycloneDxLikeBom(sbom);
|
|
65
83
|
|
|
84
|
+
function getContainerRegistryHost(reference) {
|
|
85
|
+
const trimmedReference = `${reference || ""}`.trim().toLowerCase();
|
|
86
|
+
if (!trimmedReference) {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
const slashIndex = trimmedReference.indexOf("/");
|
|
90
|
+
if (slashIndex <= 0) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
return trimmedReference.slice(0, slashIndex).replace(/:\d+$/, "");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function isSupportedSbomRegistryReference(reference) {
|
|
97
|
+
const registryHost = getContainerRegistryHost(reference);
|
|
98
|
+
return registryHost === "ghcr.io" || registryHost === "docker.io";
|
|
99
|
+
}
|
|
100
|
+
|
|
66
101
|
function unescapeAnnotationText(value) {
|
|
67
102
|
return String(value || "")
|
|
68
103
|
.replace(/<br>/g, "\n")
|
|
@@ -143,11 +178,15 @@ function printAuditTable(title, rows) {
|
|
|
143
178
|
);
|
|
144
179
|
}
|
|
145
180
|
|
|
146
|
-
function
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
181
|
+
function printKeyValueTable(title, entries) {
|
|
182
|
+
const rows = [["Field", "Value"]];
|
|
183
|
+
entries.forEach(([field, value]) => {
|
|
184
|
+
if (value === undefined || value === null || value === "") {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
rows.push([field, `${value}`]);
|
|
188
|
+
});
|
|
189
|
+
printAuditTable(title, rows);
|
|
151
190
|
}
|
|
152
191
|
|
|
153
192
|
function isLikelyObom(bom) {
|
|
@@ -158,6 +197,10 @@ function isLikelyObom(bom) {
|
|
|
158
197
|
);
|
|
159
198
|
}
|
|
160
199
|
|
|
200
|
+
function isLikelyHbom(bom) {
|
|
201
|
+
return isHbomLikeBom(bom);
|
|
202
|
+
}
|
|
203
|
+
|
|
161
204
|
function isLikelyCargoBom(bom) {
|
|
162
205
|
const formulation = Array.isArray(bom?.formulation)
|
|
163
206
|
? bom.formulation
|
|
@@ -221,11 +264,94 @@ function getCargoFormulationEntries(bom) {
|
|
|
221
264
|
return matchingEntries;
|
|
222
265
|
}
|
|
223
266
|
|
|
267
|
+
const HBOM_FIRMWARE_PROPERTIES = Object.freeze([
|
|
268
|
+
"cdx:hbom:protocol",
|
|
269
|
+
"cdx:hbom:flags",
|
|
270
|
+
"cdx:hbom:guids",
|
|
271
|
+
"cdx:hbom:instanceIds",
|
|
272
|
+
"cdx:hbom:createdEpoch",
|
|
273
|
+
"cdx:hbom:firmwareDate",
|
|
274
|
+
]);
|
|
275
|
+
|
|
276
|
+
const HBOM_BUS_SECURITY_PROPERTIES = Object.freeze([
|
|
277
|
+
"cdx:hbom:securityLevel",
|
|
278
|
+
"cdx:hbom:iommuProtection",
|
|
279
|
+
"cdx:hbom:policy",
|
|
280
|
+
"cdx:hbom:authorized",
|
|
281
|
+
"cdx:hbom:usbVersion",
|
|
282
|
+
"cdx:hbom:usbClassName",
|
|
283
|
+
"cdx:hbom:usbInterfaceClasses",
|
|
284
|
+
"cdx:hbom:pciClass",
|
|
285
|
+
"cdx:hbom:pciClassCode",
|
|
286
|
+
"cdx:hbom:displayConnectorType",
|
|
287
|
+
"cdx:hbom:contentProtection",
|
|
288
|
+
"cdx:hbom:drmNode",
|
|
289
|
+
]);
|
|
290
|
+
|
|
291
|
+
const HBOM_POWER_PROPERTIES = Object.freeze([
|
|
292
|
+
"cdx:hbom:designCapacityPercent",
|
|
293
|
+
"cdx:hbom:energyNow",
|
|
294
|
+
"cdx:hbom:energyFull",
|
|
295
|
+
"cdx:hbom:energyFullDesign",
|
|
296
|
+
"cdx:hbom:chargeNow",
|
|
297
|
+
"cdx:hbom:chargeFull",
|
|
298
|
+
"cdx:hbom:chargeFullDesign",
|
|
299
|
+
"cdx:hbom:powerNow",
|
|
300
|
+
"cdx:hbom:voltageNow",
|
|
301
|
+
"cdx:hbom:currentNow",
|
|
302
|
+
"cdx:hbom:warningLevel",
|
|
303
|
+
]);
|
|
304
|
+
|
|
305
|
+
function getInteractiveHbomOrWarn(replContext) {
|
|
306
|
+
const interactiveBom = getInteractiveBom();
|
|
307
|
+
if (!interactiveBom) {
|
|
308
|
+
console.log(
|
|
309
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
310
|
+
);
|
|
311
|
+
replContext.displayPrompt();
|
|
312
|
+
return undefined;
|
|
313
|
+
}
|
|
314
|
+
if (!isLikelyHbom(interactiveBom)) {
|
|
315
|
+
console.log(
|
|
316
|
+
"This BOM does not look like an HBOM. Import an HBOM generated with 'cdxgen -t hbom' to use this view.",
|
|
317
|
+
);
|
|
318
|
+
replContext.displayPrompt();
|
|
319
|
+
return undefined;
|
|
320
|
+
}
|
|
321
|
+
return interactiveBom;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function filterHbomComponentsByProperties(
|
|
325
|
+
bom,
|
|
326
|
+
propertyNames,
|
|
327
|
+
hardwareClasses = [],
|
|
328
|
+
) {
|
|
329
|
+
return (bom?.components || []).filter((component) => {
|
|
330
|
+
const hardwareClass = getPropertyValue(component, "cdx:hbom:hardwareClass");
|
|
331
|
+
if (hardwareClasses.includes(hardwareClass)) {
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
return propertyNames.some((propertyName) =>
|
|
335
|
+
Boolean(getPropertyValue(component, propertyName)),
|
|
336
|
+
);
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function getDiagnosticDisplayDetail(diagnostic) {
|
|
341
|
+
return (
|
|
342
|
+
diagnostic.installHint ||
|
|
343
|
+
diagnostic.privilegeHint ||
|
|
344
|
+
diagnostic.message ||
|
|
345
|
+
diagnostic.code ||
|
|
346
|
+
"-"
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
|
|
224
350
|
let historyFile;
|
|
225
351
|
const historyConfigDir = join(homedir(), ".config", ".cdxgen");
|
|
226
|
-
if (!process.env.CDXGEN_REPL_HISTORY && !
|
|
352
|
+
if (!process.env.CDXGEN_REPL_HISTORY && !safeExistsSync(historyConfigDir)) {
|
|
227
353
|
try {
|
|
228
|
-
|
|
354
|
+
safeMkdirSync(historyConfigDir, { recursive: true });
|
|
229
355
|
historyFile = join(historyConfigDir, ".repl_history");
|
|
230
356
|
} catch (_e) {
|
|
231
357
|
// ignore
|
|
@@ -235,9 +361,14 @@ if (!process.env.CDXGEN_REPL_HISTORY && !fs.existsSync(historyConfigDir)) {
|
|
|
235
361
|
}
|
|
236
362
|
|
|
237
363
|
export const importSbom = (sbomOrPath) => {
|
|
238
|
-
|
|
364
|
+
const importTarget = String(sbomOrPath || "").trim();
|
|
365
|
+
if (!importTarget) {
|
|
366
|
+
console.log("⚠ An SBOM path or image reference is required.");
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
if (importTarget.endsWith(".json") && safeExistsSync(importTarget)) {
|
|
239
370
|
try {
|
|
240
|
-
sbom = JSON.parse(
|
|
371
|
+
sbom = JSON.parse(readFileSync(importTarget, "utf-8"));
|
|
241
372
|
let bomType = "SBOM";
|
|
242
373
|
if (isSpdxJsonLd(sbom)) {
|
|
243
374
|
bomType = "SPDX";
|
|
@@ -245,8 +376,13 @@ export const importSbom = (sbomOrPath) => {
|
|
|
245
376
|
if (sbom?.vulnerabilities && Array.isArray(sbom.vulnerabilities)) {
|
|
246
377
|
bomType = "VDR";
|
|
247
378
|
}
|
|
248
|
-
console.log(`✅ ${bomType} imported successfully from ${
|
|
379
|
+
console.log(`✅ ${bomType} imported successfully from ${importTarget}`);
|
|
249
380
|
printSummary(sbom);
|
|
381
|
+
if (isLikelyHbom(sbom)) {
|
|
382
|
+
console.log(
|
|
383
|
+
"💭 HBOM detected. Try .hbomsummary, .hbomevidence, .hbomdiagnostics, or .hbomtips",
|
|
384
|
+
);
|
|
385
|
+
}
|
|
250
386
|
if (isLikelyObom(sbom)) {
|
|
251
387
|
console.log(
|
|
252
388
|
"💭 OBOM detected. Try .osinfocategories, .obomtips, .processes, or .services_snapshot",
|
|
@@ -263,32 +399,33 @@ export const importSbom = (sbomOrPath) => {
|
|
|
263
399
|
);
|
|
264
400
|
}
|
|
265
401
|
} catch (e) {
|
|
266
|
-
console.log(
|
|
402
|
+
console.log(
|
|
403
|
+
`⚠ Unable to import the BOM from ${importTarget} due to ${e}`,
|
|
404
|
+
);
|
|
267
405
|
}
|
|
268
406
|
} else if (
|
|
269
|
-
(
|
|
270
|
-
|
|
407
|
+
(importTarget.endsWith(".cdx") || importTarget.endsWith(".proto")) &&
|
|
408
|
+
safeExistsSync(importTarget)
|
|
271
409
|
) {
|
|
272
|
-
sbom = readBinary(
|
|
410
|
+
sbom = readBinary(importTarget, true);
|
|
273
411
|
printSummary(sbom);
|
|
274
|
-
} else if (
|
|
275
|
-
sbomOrPath.startsWith("ghcr.io") ||
|
|
276
|
-
sbomOrPath.startsWith("docker.io")
|
|
277
|
-
) {
|
|
412
|
+
} else if (isSupportedSbomRegistryReference(importTarget)) {
|
|
278
413
|
try {
|
|
279
|
-
sbom = getBomWithOras(
|
|
414
|
+
sbom = getBomWithOras(importTarget);
|
|
280
415
|
if (sbom) {
|
|
281
416
|
printSummary(sbom);
|
|
282
417
|
} else {
|
|
283
418
|
console.log(
|
|
284
|
-
`cyclonedx sbom attachment was not found within ${
|
|
419
|
+
`cyclonedx sbom attachment was not found within ${importTarget}`,
|
|
285
420
|
);
|
|
286
421
|
}
|
|
287
422
|
} catch (e) {
|
|
288
|
-
console.log(
|
|
423
|
+
console.log(
|
|
424
|
+
`⚠ Unable to import the BOM from ${importTarget} due to ${e}`,
|
|
425
|
+
);
|
|
289
426
|
}
|
|
290
427
|
} else {
|
|
291
|
-
console.log(`⚠ ${
|
|
428
|
+
console.log(`⚠ ${importTarget} is invalid.`);
|
|
292
429
|
}
|
|
293
430
|
};
|
|
294
431
|
// Load any sbom passed from the command line
|
|
@@ -299,12 +436,17 @@ if (process.argv.length > 2) {
|
|
|
299
436
|
console.log(
|
|
300
437
|
"💭 Type .provenance to list components with registry provenance evidence.",
|
|
301
438
|
);
|
|
439
|
+
if (isLikelyHbom(sbom)) {
|
|
440
|
+
console.log(
|
|
441
|
+
"💭 Type .hbomsummary to review the host profile, evidence coverage, hardware-class mix, and collector diagnostics.",
|
|
442
|
+
);
|
|
443
|
+
}
|
|
302
444
|
if (getAuditAnnotations().length) {
|
|
303
445
|
console.log(
|
|
304
446
|
"💭 Type .auditfindings to review cdx-audit and bom-audit annotations.",
|
|
305
447
|
);
|
|
306
448
|
}
|
|
307
|
-
} else if (
|
|
449
|
+
} else if (safeExistsSync("bom.json")) {
|
|
308
450
|
// If the current directory has a bom.json load it
|
|
309
451
|
importSbom("bom.json");
|
|
310
452
|
} else {
|
|
@@ -313,6 +455,9 @@ if (process.argv.length > 2) {
|
|
|
313
455
|
console.log(
|
|
314
456
|
"💭 For OBOM investigations, try .obomtips after importing an OBOM.",
|
|
315
457
|
);
|
|
458
|
+
console.log(
|
|
459
|
+
"💭 For HBOM investigations, try .hbomtips after importing an HBOM.",
|
|
460
|
+
);
|
|
316
461
|
console.log("💭 Type .exit or press ctrl+d to close.");
|
|
317
462
|
}
|
|
318
463
|
|
|
@@ -333,7 +478,7 @@ cdxgenRepl.defineCommand("create", {
|
|
|
333
478
|
help: "create an SBOM for the given path",
|
|
334
479
|
async action(sbomOrPath) {
|
|
335
480
|
this.clearBufferedCommand();
|
|
336
|
-
const tempDir =
|
|
481
|
+
const tempDir = safeMkdtempSync(join(getTmpDir(), "cdxgen-repl-"));
|
|
337
482
|
const bomFile = join(tempDir, "bom.json");
|
|
338
483
|
const bomNSData = await createBom(sbomOrPath, {
|
|
339
484
|
multiProject: true,
|
|
@@ -350,6 +495,11 @@ cdxgenRepl.defineCommand("create", {
|
|
|
350
495
|
console.log(
|
|
351
496
|
"💭 Type .provenance to list components with registry provenance evidence.",
|
|
352
497
|
);
|
|
498
|
+
if (isLikelyHbom(sbom)) {
|
|
499
|
+
console.log(
|
|
500
|
+
"💭 Type .hbomsummary or .hbomdiagnostics for focused hardware inventory and collector-diagnostic summaries.",
|
|
501
|
+
);
|
|
502
|
+
}
|
|
353
503
|
if (getAuditAnnotations().length) {
|
|
354
504
|
console.log(
|
|
355
505
|
"💭 Type .auditfindings to review cdx-audit and bom-audit annotations.",
|
|
@@ -387,6 +537,293 @@ cdxgenRepl.defineCommand("summary", {
|
|
|
387
537
|
this.displayPrompt();
|
|
388
538
|
},
|
|
389
539
|
});
|
|
540
|
+
cdxgenRepl.defineCommand("hbomsummary", {
|
|
541
|
+
help: "summarize HBOM host metadata, evidence coverage, and hardware-class mix",
|
|
542
|
+
action() {
|
|
543
|
+
const interactiveBom = getInteractiveBom();
|
|
544
|
+
if (!interactiveBom) {
|
|
545
|
+
console.log(
|
|
546
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
547
|
+
);
|
|
548
|
+
this.displayPrompt();
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
if (!isLikelyHbom(interactiveBom)) {
|
|
552
|
+
console.log(
|
|
553
|
+
"This BOM does not look like an HBOM. Import an HBOM generated with 'cdxgen -t hbom' to use this view.",
|
|
554
|
+
);
|
|
555
|
+
this.displayPrompt();
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
const hbomSummary = getHbomSummary(interactiveBom);
|
|
559
|
+
printKeyValueTable("HBOM summary", [
|
|
560
|
+
["Host", hbomSummary.metadataName],
|
|
561
|
+
["Component type", hbomSummary.metadataType],
|
|
562
|
+
["Manufacturer", hbomSummary.manufacturer],
|
|
563
|
+
["Platform", hbomSummary.platform],
|
|
564
|
+
["Architecture", hbomSummary.architecture],
|
|
565
|
+
["Collector profile", hbomSummary.collectorProfile],
|
|
566
|
+
["Identifier policy", hbomSummary.identifierPolicy],
|
|
567
|
+
["Component count", hbomSummary.componentCount],
|
|
568
|
+
["Hardware class count", hbomSummary.hardwareClassCount],
|
|
569
|
+
[
|
|
570
|
+
"Top hardware classes",
|
|
571
|
+
formatHbomHardwareClassSummary(hbomSummary.hardwareClassCounts),
|
|
572
|
+
],
|
|
573
|
+
["Command evidence count", hbomSummary.evidenceCommandCount],
|
|
574
|
+
["Observed file count", hbomSummary.evidenceFileCount],
|
|
575
|
+
]);
|
|
576
|
+
this.displayPrompt();
|
|
577
|
+
},
|
|
578
|
+
});
|
|
579
|
+
cdxgenRepl.defineCommand("hbomclasses", {
|
|
580
|
+
help: "show HBOM component counts by hardware class",
|
|
581
|
+
action() {
|
|
582
|
+
const interactiveBom = getInteractiveBom();
|
|
583
|
+
if (!interactiveBom) {
|
|
584
|
+
console.log(
|
|
585
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
586
|
+
);
|
|
587
|
+
this.displayPrompt();
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
if (!isLikelyHbom(interactiveBom)) {
|
|
591
|
+
console.log(
|
|
592
|
+
"This BOM does not look like an HBOM. Import an HBOM generated with 'cdxgen -t hbom' to use this view.",
|
|
593
|
+
);
|
|
594
|
+
this.displayPrompt();
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
const hbomSummary = getHbomSummary(interactiveBom);
|
|
598
|
+
if (!hbomSummary.hardwareClassCounts.length) {
|
|
599
|
+
console.log(
|
|
600
|
+
"No HBOM hardware classes were found on the loaded BOM. Check whether the document includes cdx:hbom:hardwareClass properties.",
|
|
601
|
+
);
|
|
602
|
+
this.displayPrompt();
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
printAuditTable("HBOM hardware classes", [
|
|
606
|
+
["Hardware class", "Count"],
|
|
607
|
+
...hbomSummary.hardwareClassCounts.map(({ hardwareClass, count }) => [
|
|
608
|
+
hardwareClass,
|
|
609
|
+
`${count}`,
|
|
610
|
+
]),
|
|
611
|
+
]);
|
|
612
|
+
this.displayPrompt();
|
|
613
|
+
},
|
|
614
|
+
});
|
|
615
|
+
cdxgenRepl.defineCommand("hbomevidence", {
|
|
616
|
+
help: "show HBOM collector profile plus command and observed-file evidence",
|
|
617
|
+
action() {
|
|
618
|
+
const interactiveBom = getInteractiveBom();
|
|
619
|
+
if (!interactiveBom) {
|
|
620
|
+
console.log(
|
|
621
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
622
|
+
);
|
|
623
|
+
this.displayPrompt();
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
if (!isLikelyHbom(interactiveBom)) {
|
|
627
|
+
console.log(
|
|
628
|
+
"This BOM does not look like an HBOM. Import an HBOM generated with 'cdxgen -t hbom' to use this view.",
|
|
629
|
+
);
|
|
630
|
+
this.displayPrompt();
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
const hbomSummary = getHbomSummary(interactiveBom);
|
|
634
|
+
printKeyValueTable("HBOM evidence overview", [
|
|
635
|
+
["Collector profile", hbomSummary.collectorProfile],
|
|
636
|
+
["Command evidence count", hbomSummary.evidenceCommandCount],
|
|
637
|
+
["Observed file count", hbomSummary.evidenceFileCount],
|
|
638
|
+
]);
|
|
639
|
+
if (hbomSummary.evidenceCommands.length) {
|
|
640
|
+
printAuditTable("HBOM command evidence", [
|
|
641
|
+
["Command #", "Evidence"],
|
|
642
|
+
...hbomSummary.evidenceCommands.map((command, index) => [
|
|
643
|
+
`${index + 1}`,
|
|
644
|
+
command,
|
|
645
|
+
]),
|
|
646
|
+
]);
|
|
647
|
+
}
|
|
648
|
+
if (hbomSummary.evidenceFiles.length) {
|
|
649
|
+
printAuditTable("HBOM observed files", [
|
|
650
|
+
["File #", "Path"],
|
|
651
|
+
...hbomSummary.evidenceFiles.map((filePath, index) => [
|
|
652
|
+
`${index + 1}`,
|
|
653
|
+
filePath,
|
|
654
|
+
]),
|
|
655
|
+
]);
|
|
656
|
+
}
|
|
657
|
+
this.displayPrompt();
|
|
658
|
+
},
|
|
659
|
+
});
|
|
660
|
+
cdxgenRepl.defineCommand("hbomdiagnostics", {
|
|
661
|
+
help: "show parsed HBOM command diagnostics, issue counts, and install or privilege guidance",
|
|
662
|
+
action() {
|
|
663
|
+
const interactiveBom = getInteractiveHbomOrWarn(this);
|
|
664
|
+
if (!interactiveBom) {
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
const hbomSummary = getHbomSummary(interactiveBom);
|
|
668
|
+
if (!hbomSummary.commandDiagnosticCount) {
|
|
669
|
+
console.log(
|
|
670
|
+
"No HBOM command diagnostics were found. This usually means the collector completed without recording missing-command or permission-denied enrichments.",
|
|
671
|
+
);
|
|
672
|
+
this.displayPrompt();
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
printKeyValueTable("HBOM diagnostic overview", [
|
|
676
|
+
["Diagnostic count", hbomSummary.commandDiagnosticCount],
|
|
677
|
+
["Actionable diagnostics", hbomSummary.actionableDiagnosticCount],
|
|
678
|
+
["Missing commands", hbomSummary.missingCommandCount],
|
|
679
|
+
["Permission denied", hbomSummary.permissionDeniedCount],
|
|
680
|
+
["Partial support", hbomSummary.partialSupportCount],
|
|
681
|
+
["Timeouts", hbomSummary.timeoutCount],
|
|
682
|
+
["Other command errors", hbomSummary.commandErrorCount],
|
|
683
|
+
["Diagnostic issues", hbomSummary.diagnosticIssues.join(", ")],
|
|
684
|
+
["Missing command IDs", hbomSummary.missingCommandIds.join(", ")],
|
|
685
|
+
["Permission-denied IDs", hbomSummary.permissionDeniedIds.join(", ")],
|
|
686
|
+
["Install hint count", hbomSummary.installHintCount],
|
|
687
|
+
["Privilege hint count", hbomSummary.privilegeHintCount],
|
|
688
|
+
[
|
|
689
|
+
"Requires privileged rerun",
|
|
690
|
+
hbomSummary.requiresPrivilegedEnrichment ? "yes" : "no",
|
|
691
|
+
],
|
|
692
|
+
]);
|
|
693
|
+
printAuditTable("HBOM command diagnostics", [
|
|
694
|
+
["Issue", "Diagnostic ID", "Command", "Hint / Message"],
|
|
695
|
+
...hbomSummary.commandDiagnostics.map((diagnostic) => [
|
|
696
|
+
diagnostic.issue || "unknown",
|
|
697
|
+
diagnostic.id || "-",
|
|
698
|
+
diagnostic.command || "-",
|
|
699
|
+
getDiagnosticDisplayDetail(diagnostic),
|
|
700
|
+
]),
|
|
701
|
+
]);
|
|
702
|
+
this.displayPrompt();
|
|
703
|
+
},
|
|
704
|
+
});
|
|
705
|
+
cdxgenRepl.defineCommand("hbomfirmware", {
|
|
706
|
+
help: "show firmware, board, TPM, and update-managed HBOM components plus host firmware provenance",
|
|
707
|
+
action() {
|
|
708
|
+
const interactiveBom = getInteractiveHbomOrWarn(this);
|
|
709
|
+
if (!interactiveBom) {
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
const metadataComponent = interactiveBom.metadata?.component;
|
|
713
|
+
const firmwareComponents = filterHbomComponentsByProperties(
|
|
714
|
+
interactiveBom,
|
|
715
|
+
HBOM_FIRMWARE_PROPERTIES,
|
|
716
|
+
["firmware", "board", "tpm"],
|
|
717
|
+
);
|
|
718
|
+
const metadataEntries = [
|
|
719
|
+
[
|
|
720
|
+
"Board vendor",
|
|
721
|
+
getPropertyValue(metadataComponent, "cdx:hbom:boardVendor"),
|
|
722
|
+
],
|
|
723
|
+
["Board name", getPropertyValue(metadataComponent, "cdx:hbom:boardName")],
|
|
724
|
+
[
|
|
725
|
+
"BIOS vendor",
|
|
726
|
+
getPropertyValue(metadataComponent, "cdx:hbom:biosVendor"),
|
|
727
|
+
],
|
|
728
|
+
[
|
|
729
|
+
"BIOS version",
|
|
730
|
+
getPropertyValue(metadataComponent, "cdx:hbom:biosVersion"),
|
|
731
|
+
],
|
|
732
|
+
[
|
|
733
|
+
"Firmware date",
|
|
734
|
+
getPropertyValue(metadataComponent, "cdx:hbom:firmwareDate"),
|
|
735
|
+
],
|
|
736
|
+
[
|
|
737
|
+
"Device-tree revision",
|
|
738
|
+
getPropertyValue(metadataComponent, "cdx:hbom:deviceTreeRevision"),
|
|
739
|
+
],
|
|
740
|
+
];
|
|
741
|
+
const hasMetadataProvenance = metadataEntries.some(([, value]) =>
|
|
742
|
+
Boolean(value),
|
|
743
|
+
);
|
|
744
|
+
if (!firmwareComponents.length && !hasMetadataProvenance) {
|
|
745
|
+
console.log(
|
|
746
|
+
"No focused firmware or board provenance pivots were found. Import an HBOM from a host that exposes board, TPM, or firmware-management metadata to use this view.",
|
|
747
|
+
);
|
|
748
|
+
this.displayPrompt();
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
if (hasMetadataProvenance) {
|
|
752
|
+
printKeyValueTable("HBOM host firmware provenance", metadataEntries);
|
|
753
|
+
}
|
|
754
|
+
if (firmwareComponents.length) {
|
|
755
|
+
printTable(
|
|
756
|
+
{ components: firmwareComponents, dependencies: [] },
|
|
757
|
+
undefined,
|
|
758
|
+
undefined,
|
|
759
|
+
`Found ${firmwareComponents.length} firmware, board, TPM, or update-managed component(s).`,
|
|
760
|
+
);
|
|
761
|
+
}
|
|
762
|
+
this.displayPrompt();
|
|
763
|
+
},
|
|
764
|
+
});
|
|
765
|
+
cdxgenRepl.defineCommand("hbombuses", {
|
|
766
|
+
help: "show bus, connector, USB, PCI, and external-expansion HBOM components with security or topology metadata",
|
|
767
|
+
action() {
|
|
768
|
+
const interactiveBom = getInteractiveHbomOrWarn(this);
|
|
769
|
+
if (!interactiveBom) {
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
const busComponents = filterHbomComponentsByProperties(
|
|
773
|
+
interactiveBom,
|
|
774
|
+
HBOM_BUS_SECURITY_PROPERTIES,
|
|
775
|
+
[
|
|
776
|
+
"bus",
|
|
777
|
+
"usb-device",
|
|
778
|
+
"pci-device",
|
|
779
|
+
"display-adapter",
|
|
780
|
+
"display-connector",
|
|
781
|
+
],
|
|
782
|
+
);
|
|
783
|
+
if (!busComponents.length) {
|
|
784
|
+
console.log(
|
|
785
|
+
"No bus or connector components with focused security or topology metadata were found.",
|
|
786
|
+
);
|
|
787
|
+
this.displayPrompt();
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
printTable(
|
|
791
|
+
{ components: busComponents, dependencies: [] },
|
|
792
|
+
undefined,
|
|
793
|
+
undefined,
|
|
794
|
+
`Found ${busComponents.length} bus, USB, PCI, or display-link component(s) with bus-security or topology pivots.`,
|
|
795
|
+
);
|
|
796
|
+
this.displayPrompt();
|
|
797
|
+
},
|
|
798
|
+
});
|
|
799
|
+
cdxgenRepl.defineCommand("hbompower", {
|
|
800
|
+
help: "show HBOM power and battery components with detailed design-capacity and runtime telemetry",
|
|
801
|
+
action() {
|
|
802
|
+
const interactiveBom = getInteractiveHbomOrWarn(this);
|
|
803
|
+
if (!interactiveBom) {
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
const powerComponents = filterHbomComponentsByProperties(
|
|
807
|
+
interactiveBom,
|
|
808
|
+
HBOM_POWER_PROPERTIES,
|
|
809
|
+
["power"],
|
|
810
|
+
);
|
|
811
|
+
if (!powerComponents.length) {
|
|
812
|
+
console.log(
|
|
813
|
+
"No focused power or battery telemetry components were found on the loaded HBOM.",
|
|
814
|
+
);
|
|
815
|
+
this.displayPrompt();
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
printTable(
|
|
819
|
+
{ components: powerComponents, dependencies: [] },
|
|
820
|
+
undefined,
|
|
821
|
+
undefined,
|
|
822
|
+
`Found ${powerComponents.length} power or battery component(s) with detailed runtime telemetry.`,
|
|
823
|
+
);
|
|
824
|
+
this.displayPrompt();
|
|
825
|
+
},
|
|
826
|
+
});
|
|
390
827
|
cdxgenRepl.defineCommand("exit", {
|
|
391
828
|
help: "exit",
|
|
392
829
|
action() {
|
|
@@ -447,7 +884,7 @@ cdxgenRepl.defineCommand("search", {
|
|
|
447
884
|
console.log(e);
|
|
448
885
|
}
|
|
449
886
|
} else {
|
|
450
|
-
console.log(
|
|
887
|
+
console.log('⚠ Specify the search string. Eg: .search "search string"');
|
|
451
888
|
}
|
|
452
889
|
} else {
|
|
453
890
|
console.log(
|
|
@@ -596,6 +1033,90 @@ cdxgenRepl.defineCommand("cryptos", {
|
|
|
596
1033
|
this.displayPrompt();
|
|
597
1034
|
},
|
|
598
1035
|
});
|
|
1036
|
+
cdxgenRepl.defineCommand("sourcecryptos", {
|
|
1037
|
+
help: "show source-derived cryptographic assets detected from JS AST analysis",
|
|
1038
|
+
action() {
|
|
1039
|
+
const interactiveBom = getInteractiveBom();
|
|
1040
|
+
if (!interactiveBom?.components) {
|
|
1041
|
+
console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
|
|
1042
|
+
this.displayPrompt();
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
const sourceCryptoComponents = getSourceDerivedCryptoComponents(
|
|
1046
|
+
interactiveBom.components,
|
|
1047
|
+
);
|
|
1048
|
+
if (!sourceCryptoComponents.length) {
|
|
1049
|
+
console.log(
|
|
1050
|
+
"No source-derived crypto assets found. Generate a CBOM or SBOM with source crypto analysis to use this view.",
|
|
1051
|
+
);
|
|
1052
|
+
this.displayPrompt();
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
printTable(
|
|
1056
|
+
{ components: sourceCryptoComponents, dependencies: [] },
|
|
1057
|
+
["cryptographic-asset"],
|
|
1058
|
+
undefined,
|
|
1059
|
+
`Found ${sourceCryptoComponents.length} source-derived cryptographic asset component(s).`,
|
|
1060
|
+
);
|
|
1061
|
+
this.displayPrompt();
|
|
1062
|
+
},
|
|
1063
|
+
});
|
|
1064
|
+
cdxgenRepl.defineCommand("unpackagedbins", {
|
|
1065
|
+
help: "show executable file components that were not matched to OS package ownership",
|
|
1066
|
+
action() {
|
|
1067
|
+
const interactiveBom = getInteractiveBom();
|
|
1068
|
+
if (!interactiveBom?.components) {
|
|
1069
|
+
console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
|
|
1070
|
+
this.displayPrompt();
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
const unpackagedExecutables = getUnpackagedExecutableComponents(
|
|
1074
|
+
interactiveBom.components,
|
|
1075
|
+
);
|
|
1076
|
+
if (!unpackagedExecutables.length) {
|
|
1077
|
+
console.log(
|
|
1078
|
+
"No unpackaged executable file components found. Import a container or rootfs BOM with native file inventory to use this view.",
|
|
1079
|
+
);
|
|
1080
|
+
this.displayPrompt();
|
|
1081
|
+
return;
|
|
1082
|
+
}
|
|
1083
|
+
printTable(
|
|
1084
|
+
{ components: unpackagedExecutables, dependencies: [] },
|
|
1085
|
+
["file"],
|
|
1086
|
+
undefined,
|
|
1087
|
+
`Found ${unpackagedExecutables.length} executable file component(s) that were not traced to OS package ownership.`,
|
|
1088
|
+
);
|
|
1089
|
+
this.displayPrompt();
|
|
1090
|
+
},
|
|
1091
|
+
});
|
|
1092
|
+
cdxgenRepl.defineCommand("unpackagedlibs", {
|
|
1093
|
+
help: "show shared library file components that were not matched to OS package ownership",
|
|
1094
|
+
action() {
|
|
1095
|
+
const interactiveBom = getInteractiveBom();
|
|
1096
|
+
if (!interactiveBom?.components) {
|
|
1097
|
+
console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
|
|
1098
|
+
this.displayPrompt();
|
|
1099
|
+
return;
|
|
1100
|
+
}
|
|
1101
|
+
const unpackagedSharedLibraries = getUnpackagedSharedLibraryComponents(
|
|
1102
|
+
interactiveBom.components,
|
|
1103
|
+
);
|
|
1104
|
+
if (!unpackagedSharedLibraries.length) {
|
|
1105
|
+
console.log(
|
|
1106
|
+
"No unpackaged shared library file components found. Import a container or rootfs BOM with native file inventory to use this view.",
|
|
1107
|
+
);
|
|
1108
|
+
this.displayPrompt();
|
|
1109
|
+
return;
|
|
1110
|
+
}
|
|
1111
|
+
printTable(
|
|
1112
|
+
{ components: unpackagedSharedLibraries, dependencies: [] },
|
|
1113
|
+
["file"],
|
|
1114
|
+
undefined,
|
|
1115
|
+
`Found ${unpackagedSharedLibraries.length} shared library file component(s) that were not traced to OS package ownership.`,
|
|
1116
|
+
);
|
|
1117
|
+
this.displayPrompt();
|
|
1118
|
+
},
|
|
1119
|
+
});
|
|
599
1120
|
cdxgenRepl.defineCommand("frameworks", {
|
|
600
1121
|
help: "print the components of type framework as a table",
|
|
601
1122
|
action() {
|
|
@@ -660,7 +1181,14 @@ cdxgenRepl.defineCommand("save", {
|
|
|
660
1181
|
if (!saveToFile) {
|
|
661
1182
|
saveToFile = "bom.json";
|
|
662
1183
|
}
|
|
663
|
-
|
|
1184
|
+
if (isDryRun) {
|
|
1185
|
+
console.log(
|
|
1186
|
+
`⚠ Dry run mode blocks saving the BOM to ${saveToFile}. Disable --dry-run or CDXGEN_DRY_RUN to persist it.`,
|
|
1187
|
+
);
|
|
1188
|
+
this.displayPrompt();
|
|
1189
|
+
return;
|
|
1190
|
+
}
|
|
1191
|
+
safeWriteSync(saveToFile, JSON.stringify(sbom, null, 2));
|
|
664
1192
|
console.log(`BOM saved successfully to ${saveToFile}`);
|
|
665
1193
|
} else {
|
|
666
1194
|
console.log(
|
|
@@ -1049,6 +1577,25 @@ cdxgenRepl.defineCommand("obomtips", {
|
|
|
1049
1577
|
this.displayPrompt();
|
|
1050
1578
|
},
|
|
1051
1579
|
});
|
|
1580
|
+
cdxgenRepl.defineCommand("hbomtips", {
|
|
1581
|
+
help: "show analyst tips and useful commands for HBOM investigations",
|
|
1582
|
+
action() {
|
|
1583
|
+
console.log("HBOM analyst quick guide:");
|
|
1584
|
+
console.log("1. .hbomsummary");
|
|
1585
|
+
console.log("2. .hbomclasses");
|
|
1586
|
+
console.log("3. .hbomevidence");
|
|
1587
|
+
console.log("4. .hbomdiagnostics");
|
|
1588
|
+
console.log("5. .hbomfirmware / .hbombuses / .hbompower");
|
|
1589
|
+
console.log(
|
|
1590
|
+
"6. .auditfindings to review hbom-security, hbom-performance, and hbom-compliance findings",
|
|
1591
|
+
);
|
|
1592
|
+
console.log("7. .search <hardwareClass or device name>");
|
|
1593
|
+
console.log(
|
|
1594
|
+
'Tip: .query components[properties[name="cdx:hbom:hardwareClass" and value="storage"]] filters directly by hardware class.',
|
|
1595
|
+
);
|
|
1596
|
+
this.displayPrompt();
|
|
1597
|
+
},
|
|
1598
|
+
});
|
|
1052
1599
|
cdxgenRepl.defineCommand("licenses", {
|
|
1053
1600
|
help: "visualize license distribution",
|
|
1054
1601
|
async action() {
|
|
@@ -1249,6 +1796,7 @@ cdxgenRepl.defineCommand("tagcloud", {
|
|
|
1249
1796
|
"docker_volumes",
|
|
1250
1797
|
"etc_hosts",
|
|
1251
1798
|
"firefox_addons",
|
|
1799
|
+
"gatekeeper",
|
|
1252
1800
|
"vscode_extensions",
|
|
1253
1801
|
"homebrew_packages",
|
|
1254
1802
|
"installed_applications",
|
|
@@ -1265,8 +1813,10 @@ cdxgenRepl.defineCommand("tagcloud", {
|
|
|
1265
1813
|
"portage_packages",
|
|
1266
1814
|
"process_events",
|
|
1267
1815
|
"processes",
|
|
1816
|
+
"secureboot_certificates",
|
|
1268
1817
|
"privilege_transitions",
|
|
1269
1818
|
"privileged_listening_ports",
|
|
1819
|
+
"npm_packages",
|
|
1270
1820
|
"python_packages",
|
|
1271
1821
|
"rpm_packages",
|
|
1272
1822
|
"scheduled_tasks",
|
|
@@ -1291,6 +1841,7 @@ cdxgenRepl.defineCommand("tagcloud", {
|
|
|
1291
1841
|
"npm_packages",
|
|
1292
1842
|
"opera_extensions",
|
|
1293
1843
|
"pipes_snapshot",
|
|
1844
|
+
"process_open_handles_snapshot",
|
|
1294
1845
|
"process_open_sockets",
|
|
1295
1846
|
"safari_extensions",
|
|
1296
1847
|
"scheduled_tasks",
|