@cdxgen/cdxgen 0.0.1 → 13.0.1
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 +921 -87
- package/bin/audit.js +239 -0
- package/bin/cdxgen.js +2335 -0
- package/bin/convert.js +220 -0
- package/bin/evinse.js +353 -0
- package/bin/hbom.js +504 -0
- package/bin/repl.js +2224 -0
- package/bin/sign.js +195 -0
- package/bin/tracebom.js +303 -0
- package/bin/validate.js +268 -0
- package/bin/verify.js +189 -0
- package/data/README.md +307 -0
- package/data/bom-1.4.schema.json +1605 -0
- package/data/bom-1.5.schema.json +3660 -0
- package/data/bom-1.6.schema.json +5511 -0
- package/data/bom-1.7.schema.json +6700 -0
- package/data/cbomosdb-queries.json +68 -0
- package/data/component-tags.json +339 -0
- package/data/container-knowledge-index.json +125 -0
- package/data/cosdb-queries.json +17 -0
- package/data/crypto-oid.json +1998 -0
- package/data/cryptography-defs.json +3793 -0
- package/data/cryptography-defs.schema.json +576 -0
- package/data/cyclonedx-2.0-bundled.schema.json +7182 -0
- package/data/frameworks-list.json +219 -0
- package/data/glibc-stdlib.json +117 -0
- package/data/gtfobins-index.json +6296 -0
- package/data/helpers/init.gradle +71 -0
- package/data/jsf-0.82.schema.json +211 -0
- package/data/known-licenses.json +82 -0
- package/data/lic-mapping.json +338 -0
- package/data/license-aliases.json +6624 -0
- package/data/license-db.json +39059 -0
- package/data/license-deprecations.json +302 -0
- package/data/lolbas-index.json +150 -0
- package/data/predictive-audit-allowlist.json +11 -0
- package/data/pypi-pkg-aliases.json +1199 -0
- package/data/python-stdlib.json +308 -0
- package/data/queries-darwin.json +193 -0
- package/data/queries-win.json +257 -0
- package/data/queries.json +268 -0
- package/data/ruby-known-modules.json +281 -0
- package/data/rules/ai-agent-governance.yaml +323 -0
- package/data/rules/ai-bom.yaml +268 -0
- package/data/rules/ai-oversight.yaml +186 -0
- package/data/rules/ai-provenance.yaml +92 -0
- package/data/rules/asar-archives.yaml +150 -0
- package/data/rules/cbom-security.yaml +165 -0
- package/data/rules/chrome-extensions.yaml +248 -0
- package/data/rules/ci-permissions.yaml +802 -0
- package/data/rules/container-risk.yaml +353 -0
- package/data/rules/dependency-sources.yaml +236 -0
- package/data/rules/golem-go.yaml +229 -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 +388 -0
- package/data/rules/obom-runtime.yaml +1776 -0
- package/data/rules/package-integrity.yaml +364 -0
- package/data/rules/rootfs-hardening.yaml +179 -0
- package/data/rules/vscode-extensions.yaml +237 -0
- package/data/spdx-export.schema.json +6794 -0
- package/data/spdx-license-list.json +7449 -0
- package/data/spdx-licenses.json +759 -0
- package/data/spdx.schema.json +819 -0
- package/data/templates/README.md +3 -0
- package/data/templates/asvs-4.0.3.cdx.json +2943 -0
- package/data/templates/asvs-5.0.cdx.json +3046 -0
- package/data/templates/bsimm-v13.cdx.json +1008 -0
- package/data/templates/masvs-2.0.0.cdx.json +225 -0
- package/data/templates/nist-ssdf-1.1.cdx.json +828 -0
- package/data/templates/pcissc-secure-slc-1.1.cdx.json +1027 -0
- package/data/templates/scvs-1.0.0.cdx.json +813 -0
- package/data/templates/ssaf-DRAFT-2023-11.cdx.json +127 -0
- package/data/vendor-alias.json +41967 -0
- package/data/wrapdb-releases.json +4227 -0
- package/index.cjs +15 -0
- package/lib/audit/index.js +2800 -0
- package/lib/audit/progress.js +114 -0
- package/lib/audit/reporters.js +937 -0
- package/lib/audit/scoring.js +560 -0
- package/lib/audit/targets.js +798 -0
- package/lib/cli/bomAssembly.js +1882 -0
- package/lib/cli/cliOptions.js +543 -0
- package/lib/cli/index.js +2759 -0
- package/lib/cli/jsBom.js +2087 -0
- package/lib/cli/jvmBom.js +1858 -0
- package/lib/cli/managedBom.js +2083 -0
- package/lib/cli/nativeBom.js +2125 -0
- package/lib/core/activity.js +1087 -0
- package/lib/core/env.js +719 -0
- package/lib/core/fs.js +1058 -0
- package/lib/core/httpClient.js +730 -0
- package/lib/core/logger.js +280 -0
- package/lib/core/parallel.js +323 -0
- package/lib/core/paths.js +70 -0
- package/lib/core/projectConfig.js +122 -0
- package/lib/core/propertySanitizer.js +174 -0
- package/lib/core/spdx.js +5 -0
- package/lib/core/state.js +59 -0
- package/lib/core/text.js +207 -0
- package/lib/core/ui.js +920 -0
- package/lib/core/urls.js +84 -0
- package/lib/ecosystems/asarutils.js +1636 -0
- package/lib/ecosystems/bunutils.js +402 -0
- package/lib/ecosystems/caxa.js +77 -0
- package/lib/ecosystems/chromextutils.js +1174 -0
- package/lib/ecosystems/cmakeResolver.js +587 -0
- package/lib/ecosystems/cppEvidence.js +305 -0
- package/lib/ecosystems/denoutils.js +1094 -0
- package/lib/ecosystems/dotnetutils.js +132 -0
- package/lib/ecosystems/ecosystems.js +2772 -0
- package/lib/ecosystems/golem.js +1807 -0
- package/lib/ecosystems/gradleutils.js +1048 -0
- package/lib/ecosystems/jsEvidence.js +317 -0
- package/lib/ecosystems/npmutils.js +586 -0
- package/lib/ecosystems/parsers-bazel.js +875 -0
- package/lib/ecosystems/parsers-dotnet.js +1430 -0
- package/lib/ecosystems/parsers-gleam.js +302 -0
- package/lib/ecosystems/parsers-go.js +818 -0
- package/lib/ecosystems/parsers-js.js +4222 -0
- package/lib/ecosystems/parsers-jvm.js +948 -0
- package/lib/ecosystems/parsers-misc.js +3191 -0
- package/lib/ecosystems/parsers-python.js +2070 -0
- package/lib/ecosystems/parsers-rust.js +1294 -0
- package/lib/ecosystems/parsers-zig.js +861 -0
- package/lib/ecosystems/pep770.js +341 -0
- package/lib/ecosystems/pylockutils.js +427 -0
- package/lib/ecosystems/pythonutils.js +1281 -0
- package/lib/ecosystems/registryProvenance.js +1003 -0
- package/lib/ecosystems/remote/huggingface.js +1343 -0
- package/lib/ecosystems/rubyutils.js +1629 -0
- package/lib/ecosystems/rusi.js +820 -0
- package/lib/ecosystems/sbtutils.js +972 -0
- package/lib/ecosystems/tea.js +607 -0
- package/lib/ecosystems/utils.js +583 -0
- package/lib/ecosystems/zigResolver.js +410 -0
- package/lib/evinser/db.js +145 -0
- package/lib/evinser/evinser.js +2362 -0
- package/lib/evinser/scalasem.js +65 -0
- package/lib/evinser/swiftsem.js +767 -0
- package/lib/helpers/annotationFormatter.js +84 -0
- package/lib/helpers/bomSigner.js +312 -0
- package/lib/helpers/exportUtils.js +160 -0
- package/lib/helpers/remote/dependency-track.js +117 -0
- package/lib/helpers/versutils.js +202 -0
- package/lib/helpers/vsixutils.js +1069 -0
- package/lib/inventory/agentFormulationParser.js +322 -0
- package/lib/inventory/aiCollector.js +2140 -0
- package/lib/inventory/aiInventory.js +414 -0
- package/lib/inventory/aiModelVariants.js +121 -0
- package/lib/inventory/aiOversightCollector.js +661 -0
- package/lib/inventory/aiProvenanceCollector.js +822 -0
- package/lib/inventory/analyzer.js +6089 -0
- package/lib/inventory/analyzerScope.js +807 -0
- package/lib/inventory/astWorker.js +20 -0
- package/lib/inventory/atomUtils.js +1092 -0
- package/lib/inventory/auditCategories.js +192 -0
- package/lib/inventory/bomUtils.js +369 -0
- package/lib/inventory/cacheCommands.js +182 -0
- package/lib/inventory/cacheDir.js +104 -0
- package/lib/inventory/cbomutils.js +590 -0
- package/lib/inventory/cdxrs.js +434 -0
- package/lib/inventory/ciParsers/azurePipelines.js +295 -0
- package/lib/inventory/ciParsers/circleCi.js +286 -0
- package/lib/inventory/ciParsers/common.js +24 -0
- package/lib/inventory/ciParsers/githubActions.js +2434 -0
- package/lib/inventory/ciParsers/gitlabCi.js +213 -0
- package/lib/inventory/ciParsers/jenkins.js +180 -0
- package/lib/inventory/citations.js +234 -0
- package/lib/inventory/communityAiConfigParser.js +756 -0
- package/lib/inventory/containerRisk.js +204 -0
- package/lib/inventory/cryptoAlgorithmFamily.js +258 -0
- package/lib/inventory/deps.js +807 -0
- package/lib/inventory/depsUtils.js +588 -0
- package/lib/inventory/display.js +2128 -0
- package/lib/inventory/dosai.js +601 -0
- package/lib/inventory/dosaiParsers.js +154 -0
- package/lib/inventory/dynamic.js +145 -0
- package/lib/inventory/envcontext.js +1793 -0
- package/lib/inventory/evidenceUtils.js +774 -0
- package/lib/inventory/fetchBatch.js +779 -0
- package/lib/inventory/fetchRate.js +255 -0
- package/lib/inventory/forgeEnricher.js +300 -0
- package/lib/inventory/formulationParsers.js +422 -0
- package/lib/inventory/gtfobins.js +339 -0
- package/lib/inventory/hbom.js +719 -0
- package/lib/inventory/hbomAnalysis.js +310 -0
- package/lib/inventory/hbomLoader.js +35 -0
- package/lib/inventory/hostTopology.js +835 -0
- package/lib/inventory/inventoryStats.js +100 -0
- package/lib/inventory/jsonLike.js +121 -0
- package/lib/inventory/licenseEnhancer.js +918 -0
- package/lib/inventory/lolbas.js +285 -0
- package/lib/inventory/mcp.js +253 -0
- package/lib/inventory/mcpConfigParser.js +683 -0
- package/lib/inventory/mcpDiscovery.js +112 -0
- package/lib/inventory/mcpPinning.js +209 -0
- package/lib/inventory/osPackageResolver.js +493 -0
- package/lib/inventory/osinfo.js +383 -0
- package/lib/inventory/osqueryTransform.js +274 -0
- package/lib/inventory/plugins.js +466 -0
- package/lib/inventory/protobom.js +231 -0
- package/lib/inventory/protobomLoader.js +43 -0
- package/lib/inventory/provenanceUtils.js +224 -0
- package/lib/inventory/purl.js +749 -0
- package/lib/inventory/rustFormulationParser.js +339 -0
- package/lib/inventory/sbomDocument.js +340 -0
- package/lib/inventory/source.js +1488 -0
- package/lib/inventory/spdx.js +361 -0
- package/lib/inventory/spdxExpression.js +512 -0
- package/lib/inventory/spdxUtils.js +107 -0
- package/lib/inventory/table.js +267 -0
- package/lib/inventory/traceRunner.js +439 -0
- package/lib/inventory/unicodeScan.js +147 -0
- package/lib/managers/binary.js +3459 -0
- package/lib/managers/containerutils.js +125 -0
- package/lib/managers/docker.js +2145 -0
- package/lib/managers/dockerConnection.js +162 -0
- package/lib/managers/oci.js +704 -0
- package/lib/managers/piptree.js +267 -0
- package/lib/parsers/cmakeCache.js +199 -0
- package/lib/parsers/gguf.js +492 -0
- package/lib/parsers/gitAiNotes.js +233 -0
- package/lib/parsers/gitmodules.js +239 -0
- package/lib/parsers/htmlExtract.js +610 -0
- package/lib/parsers/huggingfaceManifest.js +551 -0
- package/lib/parsers/huggingfaceUtils.js +506 -0
- package/lib/parsers/iri.js +618 -0
- package/lib/parsers/npmrc.js +99 -0
- package/lib/parsers/ollama.js +101 -0
- package/lib/parsers/xml.js +841 -0
- package/lib/server/openapi.yaml +433 -0
- package/lib/server/server.js +616 -0
- package/lib/stages/postgen/annotator.js +977 -0
- package/lib/stages/postgen/auditBom.js +468 -0
- package/lib/stages/postgen/postgen.js +1239 -0
- package/lib/stages/postgen/ruleEngine.js +731 -0
- package/lib/stages/postgen/sortBom.js +195 -0
- package/lib/stages/postgen/spdxConverter.js +796 -0
- package/lib/stages/postgen/specVersionCompat.js +703 -0
- package/lib/stages/pregen/envAudit.js +388 -0
- package/lib/stages/pregen/pregen.js +637 -0
- package/lib/third-party/README.md +9 -0
- package/lib/third-party/arborist/CHANGELOG.md +1109 -0
- package/lib/third-party/arborist/LICENSE.md +20 -0
- package/lib/third-party/arborist/README.md +315 -0
- package/lib/third-party/arborist/lib/arborist/index.js +258 -0
- package/lib/third-party/arborist/lib/arborist/load-actual.js +605 -0
- package/lib/third-party/arborist/lib/arborist/load-virtual.js +300 -0
- package/lib/third-party/arborist/lib/bin-links.js +120 -0
- package/lib/third-party/arborist/lib/calc-dep-flags.js +130 -0
- package/lib/third-party/arborist/lib/case-insensitive-map.js +51 -0
- package/lib/third-party/arborist/lib/consistent-resolve.js +42 -0
- package/lib/third-party/arborist/lib/debug.js +50 -0
- package/lib/third-party/arborist/lib/dep-valid.js +190 -0
- package/lib/third-party/arborist/lib/edge.js +417 -0
- package/lib/third-party/arborist/lib/from-path.js +36 -0
- package/lib/third-party/arborist/lib/gather-dep-set.js +43 -0
- package/lib/third-party/arborist/lib/index.js +22 -0
- package/lib/third-party/arborist/lib/inventory.js +138 -0
- package/lib/third-party/arborist/lib/link.js +169 -0
- package/lib/third-party/arborist/lib/node.js +1673 -0
- package/lib/third-party/arborist/lib/npm-extension.js +45 -0
- package/lib/third-party/arborist/lib/override-resolves.js +11 -0
- package/lib/third-party/arborist/lib/override-set.js +319 -0
- package/lib/third-party/arborist/lib/package-extensions.js +289 -0
- package/lib/third-party/arborist/lib/printable.js +210 -0
- package/lib/third-party/arborist/lib/proc-log.js +30 -0
- package/lib/third-party/arborist/lib/realpath.js +100 -0
- package/lib/third-party/arborist/lib/relpath.js +4 -0
- package/lib/third-party/arborist/lib/shrinkwrap.js +1291 -0
- package/lib/third-party/arborist/lib/spec-from-lock.js +34 -0
- package/lib/third-party/arborist/lib/tree-check.js +165 -0
- package/lib/third-party/arborist/lib/validate-npm-package-name.js +107 -0
- package/lib/third-party/arborist/lib/version-from-tgz.js +51 -0
- package/lib/third-party/arborist/lib/yarn-lock.js +397 -0
- package/lib/validator/bomValidator.js +985 -0
- package/lib/validator/complianceEngine.js +241 -0
- package/lib/validator/complianceRules.js +1680 -0
- package/lib/validator/generated/runtime.mjs +17 -0
- package/lib/validator/generated/validate-1.6.mjs +21258 -0
- package/lib/validator/generated/validate-1.7.mjs +24803 -0
- package/lib/validator/generated/validate-2.0.mjs +22931 -0
- package/lib/validator/index.js +246 -0
- package/lib/validator/reporters/annotations.js +142 -0
- package/lib/validator/reporters/console.js +160 -0
- package/lib/validator/reporters/index.js +41 -0
- package/lib/validator/reporters/json.js +37 -0
- package/lib/validator/reporters/sarif.js +184 -0
- package/package.json +209 -26
- package/types/bin/audit.d.ts +3 -0
- package/types/bin/audit.d.ts.map +1 -0
- package/types/bin/cdxgen.d.ts +3 -0
- package/types/bin/cdxgen.d.ts.map +1 -0
- package/types/bin/convert.d.ts +3 -0
- package/types/bin/convert.d.ts.map +1 -0
- package/types/bin/evinse.d.ts +3 -0
- package/types/bin/evinse.d.ts.map +1 -0
- package/types/bin/hbom.d.ts +3 -0
- package/types/bin/hbom.d.ts.map +1 -0
- package/types/bin/repl.d.ts +3 -0
- package/types/bin/repl.d.ts.map +1 -0
- package/types/bin/sign.d.ts +3 -0
- package/types/bin/sign.d.ts.map +1 -0
- package/types/bin/tracebom.d.ts +3 -0
- package/types/bin/tracebom.d.ts.map +1 -0
- package/types/bin/validate.d.ts +14 -0
- package/types/bin/validate.d.ts.map +1 -0
- package/types/bin/verify.d.ts +3 -0
- package/types/bin/verify.d.ts.map +1 -0
- package/types/lib/audit/index.d.ts +153 -0
- package/types/lib/audit/index.d.ts.map +1 -0
- package/types/lib/audit/progress.d.ts +31 -0
- package/types/lib/audit/progress.d.ts.map +1 -0
- package/types/lib/audit/reporters.d.ts +62 -0
- package/types/lib/audit/reporters.d.ts.map +1 -0
- package/types/lib/audit/scoring.d.ts +36 -0
- package/types/lib/audit/scoring.d.ts.map +1 -0
- package/types/lib/audit/targets.d.ts +77 -0
- package/types/lib/audit/targets.d.ts.map +1 -0
- package/types/lib/cli/bomAssembly.d.ts +329 -0
- package/types/lib/cli/bomAssembly.d.ts.map +1 -0
- package/types/lib/cli/cliOptions.d.ts +156 -0
- package/types/lib/cli/cliOptions.d.ts.map +1 -0
- package/types/lib/cli/index.d.ts +107 -0
- package/types/lib/cli/index.d.ts.map +1 -0
- package/types/lib/cli/jsBom.d.ts +94 -0
- package/types/lib/cli/jsBom.d.ts.map +1 -0
- package/types/lib/cli/jvmBom.d.ts +54 -0
- package/types/lib/cli/jvmBom.d.ts.map +1 -0
- package/types/lib/cli/managedBom.d.ts +105 -0
- package/types/lib/cli/managedBom.d.ts.map +1 -0
- package/types/lib/cli/nativeBom.d.ts +143 -0
- package/types/lib/cli/nativeBom.d.ts.map +1 -0
- package/types/lib/core/activity.d.ts +178 -0
- package/types/lib/core/activity.d.ts.map +1 -0
- package/types/lib/core/env.d.ts +192 -0
- package/types/lib/core/env.d.ts.map +1 -0
- package/types/lib/core/fs.d.ts +158 -0
- package/types/lib/core/fs.d.ts.map +1 -0
- package/types/lib/core/httpClient.d.ts +149 -0
- package/types/lib/core/httpClient.d.ts.map +1 -0
- package/types/lib/core/logger.d.ts +50 -0
- package/types/lib/core/logger.d.ts.map +1 -0
- package/types/lib/core/parallel.d.ts +95 -0
- package/types/lib/core/parallel.d.ts.map +1 -0
- package/types/lib/core/paths.d.ts +36 -0
- package/types/lib/core/paths.d.ts.map +1 -0
- package/types/lib/core/projectConfig.d.ts +23 -0
- package/types/lib/core/projectConfig.d.ts.map +1 -0
- package/types/lib/core/propertySanitizer.d.ts +23 -0
- package/types/lib/core/propertySanitizer.d.ts.map +1 -0
- package/types/lib/core/spdx.d.ts +5 -0
- package/types/lib/core/spdx.d.ts.map +1 -0
- package/types/lib/core/state.d.ts +20 -0
- package/types/lib/core/state.d.ts.map +1 -0
- package/types/lib/core/text.d.ts +78 -0
- package/types/lib/core/text.d.ts.map +1 -0
- package/types/lib/core/ui.d.ts +87 -0
- package/types/lib/core/ui.d.ts.map +1 -0
- package/types/lib/core/urls.d.ts +43 -0
- package/types/lib/core/urls.d.ts.map +1 -0
- package/types/lib/ecosystems/asarutils.d.ts +71 -0
- package/types/lib/ecosystems/asarutils.d.ts.map +1 -0
- package/types/lib/ecosystems/bunutils.d.ts +38 -0
- package/types/lib/ecosystems/bunutils.d.ts.map +1 -0
- package/types/lib/ecosystems/caxa.d.ts +8 -0
- package/types/lib/ecosystems/caxa.d.ts.map +1 -0
- package/types/lib/ecosystems/chromextutils.d.ts +97 -0
- package/types/lib/ecosystems/chromextutils.d.ts.map +1 -0
- package/types/lib/ecosystems/cmakeResolver.d.ts +176 -0
- package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -0
- package/types/lib/ecosystems/cppEvidence.d.ts +35 -0
- package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -0
- package/types/lib/ecosystems/denoutils.d.ts +76 -0
- package/types/lib/ecosystems/denoutils.d.ts.map +1 -0
- package/types/lib/ecosystems/dotnetutils.d.ts +45 -0
- package/types/lib/ecosystems/dotnetutils.d.ts.map +1 -0
- package/types/lib/ecosystems/ecosystems.d.ts +279 -0
- package/types/lib/ecosystems/ecosystems.d.ts.map +1 -0
- package/types/lib/ecosystems/golem.d.ts +60 -0
- package/types/lib/ecosystems/golem.d.ts.map +1 -0
- package/types/lib/ecosystems/gradleutils.d.ts +139 -0
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -0
- package/types/lib/ecosystems/jsEvidence.d.ts +17 -0
- package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -0
- package/types/lib/ecosystems/npmutils.d.ts +183 -0
- package/types/lib/ecosystems/npmutils.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-bazel.d.ts +36 -0
- package/types/lib/ecosystems/parsers-bazel.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-dotnet.d.ts +116 -0
- package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-gleam.d.ts +33 -0
- package/types/lib/ecosystems/parsers-gleam.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-go.d.ts +92 -0
- package/types/lib/ecosystems/parsers-go.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-js.d.ts +242 -0
- package/types/lib/ecosystems/parsers-js.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-jvm.d.ts +100 -0
- package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-misc.d.ts +450 -0
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-python.d.ts +145 -0
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-rust.d.ts +56 -0
- package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-zig.d.ts +83 -0
- package/types/lib/ecosystems/parsers-zig.d.ts.map +1 -0
- package/types/lib/ecosystems/pep770.d.ts +38 -0
- package/types/lib/ecosystems/pep770.d.ts.map +1 -0
- package/types/lib/ecosystems/pylockutils.d.ts +68 -0
- package/types/lib/ecosystems/pylockutils.d.ts.map +1 -0
- package/types/lib/ecosystems/pythonutils.d.ts +70 -0
- package/types/lib/ecosystems/pythonutils.d.ts.map +1 -0
- package/types/lib/ecosystems/registryProvenance.d.ts +26 -0
- package/types/lib/ecosystems/registryProvenance.d.ts.map +1 -0
- package/types/lib/ecosystems/remote/huggingface.d.ts +31 -0
- package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -0
- package/types/lib/ecosystems/rubyutils.d.ts +182 -0
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -0
- package/types/lib/ecosystems/rusi.d.ts +40 -0
- package/types/lib/ecosystems/rusi.d.ts.map +1 -0
- package/types/lib/ecosystems/sbtutils.d.ts +179 -0
- package/types/lib/ecosystems/sbtutils.d.ts.map +1 -0
- package/types/lib/ecosystems/tea.d.ts +180 -0
- package/types/lib/ecosystems/tea.d.ts.map +1 -0
- package/types/lib/ecosystems/utils.d.ts +41 -0
- package/types/lib/ecosystems/utils.d.ts.map +1 -0
- package/types/lib/ecosystems/zigResolver.d.ts +70 -0
- package/types/lib/ecosystems/zigResolver.d.ts.map +1 -0
- package/types/lib/evinser/db.d.ts +17 -0
- package/types/lib/evinser/db.d.ts.map +1 -0
- package/types/lib/evinser/evinser.d.ts +354 -0
- package/types/lib/evinser/evinser.d.ts.map +1 -0
- package/types/lib/evinser/scalasem.d.ts +15 -0
- package/types/lib/evinser/scalasem.d.ts.map +1 -0
- package/types/lib/evinser/swiftsem.d.ts +103 -0
- package/types/lib/evinser/swiftsem.d.ts.map +1 -0
- package/types/lib/helpers/annotationFormatter.d.ts +23 -0
- package/types/lib/helpers/annotationFormatter.d.ts.map +1 -0
- package/types/lib/helpers/bomSigner.d.ts +28 -0
- package/types/lib/helpers/bomSigner.d.ts.map +1 -0
- package/types/lib/helpers/exportUtils.d.ts +52 -0
- package/types/lib/helpers/exportUtils.d.ts.map +1 -0
- package/types/lib/helpers/remote/dependency-track.d.ts +23 -0
- package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -0
- package/types/lib/helpers/versutils.d.ts +8 -0
- package/types/lib/helpers/versutils.d.ts.map +1 -0
- package/types/lib/helpers/vsixutils.d.ts +130 -0
- package/types/lib/helpers/vsixutils.d.ts.map +1 -0
- package/types/lib/inventory/agentFormulationParser.d.ts +21 -0
- package/types/lib/inventory/agentFormulationParser.d.ts.map +1 -0
- package/types/lib/inventory/aiCollector.d.ts +61 -0
- package/types/lib/inventory/aiCollector.d.ts.map +1 -0
- package/types/lib/inventory/aiInventory.d.ts +103 -0
- package/types/lib/inventory/aiInventory.d.ts.map +1 -0
- package/types/lib/inventory/aiModelVariants.d.ts +31 -0
- package/types/lib/inventory/aiModelVariants.d.ts.map +1 -0
- package/types/lib/inventory/aiOversightCollector.d.ts +28 -0
- package/types/lib/inventory/aiOversightCollector.d.ts.map +1 -0
- package/types/lib/inventory/aiProvenanceCollector.d.ts +13 -0
- package/types/lib/inventory/aiProvenanceCollector.d.ts.map +1 -0
- package/types/lib/inventory/analyzer.d.ts +157 -0
- package/types/lib/inventory/analyzer.d.ts.map +1 -0
- package/types/lib/inventory/analyzerScope.d.ts +106 -0
- package/types/lib/inventory/analyzerScope.d.ts.map +1 -0
- package/types/lib/inventory/astWorker.d.ts +9 -0
- package/types/lib/inventory/astWorker.d.ts.map +1 -0
- package/types/lib/inventory/atomUtils.d.ts +159 -0
- package/types/lib/inventory/atomUtils.d.ts.map +1 -0
- package/types/lib/inventory/auditCategories.d.ts +80 -0
- package/types/lib/inventory/auditCategories.d.ts.map +1 -0
- package/types/lib/inventory/bomUtils.d.ts +145 -0
- package/types/lib/inventory/bomUtils.d.ts.map +1 -0
- package/types/lib/inventory/cacheCommands.d.ts +28 -0
- package/types/lib/inventory/cacheCommands.d.ts.map +1 -0
- package/types/lib/inventory/cacheDir.d.ts +55 -0
- package/types/lib/inventory/cacheDir.d.ts.map +1 -0
- package/types/lib/inventory/cbomutils.d.ts +37 -0
- package/types/lib/inventory/cbomutils.d.ts.map +1 -0
- package/types/lib/inventory/cdxrs.d.ts +90 -0
- package/types/lib/inventory/cdxrs.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/azurePipelines.d.ts +27 -0
- package/types/lib/inventory/ciParsers/azurePipelines.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/circleCi.d.ts +27 -0
- package/types/lib/inventory/ciParsers/circleCi.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/common.d.ts +11 -0
- package/types/lib/inventory/ciParsers/common.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/githubActions.d.ts +38 -0
- package/types/lib/inventory/ciParsers/githubActions.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/gitlabCi.d.ts +26 -0
- package/types/lib/inventory/ciParsers/gitlabCi.d.ts.map +1 -0
- package/types/lib/inventory/ciParsers/jenkins.d.ts +26 -0
- package/types/lib/inventory/ciParsers/jenkins.d.ts.map +1 -0
- package/types/lib/inventory/citations.d.ts +90 -0
- package/types/lib/inventory/citations.d.ts.map +1 -0
- package/types/lib/inventory/communityAiConfigParser.d.ts +14 -0
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -0
- package/types/lib/inventory/containerRisk.d.ts +20 -0
- package/types/lib/inventory/containerRisk.d.ts.map +1 -0
- package/types/lib/inventory/cryptoAlgorithmFamily.d.ts +37 -0
- package/types/lib/inventory/cryptoAlgorithmFamily.d.ts.map +1 -0
- package/types/lib/inventory/deps.d.ts +140 -0
- package/types/lib/inventory/deps.d.ts.map +1 -0
- package/types/lib/inventory/depsUtils.d.ts +74 -0
- package/types/lib/inventory/depsUtils.d.ts.map +1 -0
- package/types/lib/inventory/display.d.ts +227 -0
- package/types/lib/inventory/display.d.ts.map +1 -0
- package/types/lib/inventory/dosai.d.ts +130 -0
- package/types/lib/inventory/dosai.d.ts.map +1 -0
- package/types/lib/inventory/dosaiParsers.d.ts +59 -0
- package/types/lib/inventory/dosaiParsers.d.ts.map +1 -0
- package/types/lib/inventory/dynamic.d.ts +25 -0
- package/types/lib/inventory/dynamic.d.ts.map +1 -0
- package/types/lib/inventory/envcontext.d.ts +377 -0
- package/types/lib/inventory/envcontext.d.ts.map +1 -0
- package/types/lib/inventory/evidenceUtils.d.ts +74 -0
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -0
- package/types/lib/inventory/fetchBatch.d.ts +127 -0
- package/types/lib/inventory/fetchBatch.d.ts.map +1 -0
- package/types/lib/inventory/fetchRate.d.ts +118 -0
- package/types/lib/inventory/fetchRate.d.ts.map +1 -0
- package/types/lib/inventory/forgeEnricher.d.ts +31 -0
- package/types/lib/inventory/forgeEnricher.d.ts.map +1 -0
- package/types/lib/inventory/formulationParsers.d.ts +50 -0
- package/types/lib/inventory/formulationParsers.d.ts.map +1 -0
- package/types/lib/inventory/gtfobins.d.ts +27 -0
- package/types/lib/inventory/gtfobins.d.ts.map +1 -0
- package/types/lib/inventory/hbom.d.ts +58 -0
- package/types/lib/inventory/hbom.d.ts.map +1 -0
- package/types/lib/inventory/hbomAnalysis.d.ts +56 -0
- package/types/lib/inventory/hbomAnalysis.d.ts.map +1 -0
- package/types/lib/inventory/hbomLoader.d.ts +7 -0
- package/types/lib/inventory/hbomLoader.d.ts.map +1 -0
- package/types/lib/inventory/hostTopology.d.ts +47 -0
- package/types/lib/inventory/hostTopology.d.ts.map +1 -0
- package/types/lib/inventory/inventoryStats.d.ts +42 -0
- package/types/lib/inventory/inventoryStats.d.ts.map +1 -0
- package/types/lib/inventory/jsonLike.d.ts +23 -0
- package/types/lib/inventory/jsonLike.d.ts.map +1 -0
- package/types/lib/inventory/licenseEnhancer.d.ts +70 -0
- package/types/lib/inventory/licenseEnhancer.d.ts.map +1 -0
- package/types/lib/inventory/lolbas.d.ts +16 -0
- package/types/lib/inventory/lolbas.d.ts.map +1 -0
- package/types/lib/inventory/mcp.d.ts +29 -0
- package/types/lib/inventory/mcp.d.ts.map +1 -0
- package/types/lib/inventory/mcpConfigParser.d.ts +20 -0
- package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -0
- package/types/lib/inventory/mcpDiscovery.d.ts +33 -0
- package/types/lib/inventory/mcpDiscovery.d.ts.map +1 -0
- package/types/lib/inventory/mcpPinning.d.ts +11 -0
- package/types/lib/inventory/mcpPinning.d.ts.map +1 -0
- package/types/lib/inventory/osPackageResolver.d.ts +49 -0
- package/types/lib/inventory/osPackageResolver.d.ts.map +1 -0
- package/types/lib/inventory/osinfo.d.ts +201 -0
- package/types/lib/inventory/osinfo.d.ts.map +1 -0
- package/types/lib/inventory/osqueryTransform.d.ts +84 -0
- package/types/lib/inventory/osqueryTransform.d.ts.map +1 -0
- package/types/lib/inventory/plugins.d.ts +58 -0
- package/types/lib/inventory/plugins.d.ts.map +1 -0
- package/types/lib/inventory/protobom.d.ts +71 -0
- package/types/lib/inventory/protobom.d.ts.map +1 -0
- package/types/lib/inventory/protobomLoader.d.ts +17 -0
- package/types/lib/inventory/protobomLoader.d.ts.map +1 -0
- package/types/lib/inventory/provenanceUtils.d.ts +98 -0
- package/types/lib/inventory/provenanceUtils.d.ts.map +1 -0
- package/types/lib/inventory/purl.d.ts +313 -0
- package/types/lib/inventory/purl.d.ts.map +1 -0
- package/types/lib/inventory/rustFormulationParser.d.ts +17 -0
- package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -0
- package/types/lib/inventory/sbomDocument.d.ts +59 -0
- package/types/lib/inventory/sbomDocument.d.ts.map +1 -0
- package/types/lib/inventory/source.d.ts +163 -0
- package/types/lib/inventory/source.d.ts.map +1 -0
- package/types/lib/inventory/spdx.d.ts +66 -0
- package/types/lib/inventory/spdx.d.ts.map +1 -0
- package/types/lib/inventory/spdxExpression.d.ts +58 -0
- package/types/lib/inventory/spdxExpression.d.ts.map +1 -0
- package/types/lib/inventory/spdxUtils.d.ts +12 -0
- package/types/lib/inventory/spdxUtils.d.ts.map +1 -0
- package/types/lib/inventory/table.d.ts +22 -0
- package/types/lib/inventory/table.d.ts.map +1 -0
- package/types/lib/inventory/traceRunner.d.ts +80 -0
- package/types/lib/inventory/traceRunner.d.ts.map +1 -0
- package/types/lib/inventory/unicodeScan.d.ts +46 -0
- package/types/lib/inventory/unicodeScan.d.ts.map +1 -0
- package/types/lib/managers/binary.d.ts +147 -0
- package/types/lib/managers/binary.d.ts.map +1 -0
- package/types/lib/managers/containerutils.d.ts +30 -0
- package/types/lib/managers/containerutils.d.ts.map +1 -0
- package/types/lib/managers/docker.d.ts +157 -0
- package/types/lib/managers/docker.d.ts.map +1 -0
- package/types/lib/managers/dockerConnection.d.ts +42 -0
- package/types/lib/managers/dockerConnection.d.ts.map +1 -0
- package/types/lib/managers/oci.d.ts +21 -0
- package/types/lib/managers/oci.d.ts.map +1 -0
- package/types/lib/managers/piptree.d.ts +13 -0
- package/types/lib/managers/piptree.d.ts.map +1 -0
- package/types/lib/parsers/cmakeCache.d.ts +70 -0
- package/types/lib/parsers/cmakeCache.d.ts.map +1 -0
- package/types/lib/parsers/gguf.d.ts +39 -0
- package/types/lib/parsers/gguf.d.ts.map +1 -0
- package/types/lib/parsers/gitAiNotes.d.ts +15 -0
- package/types/lib/parsers/gitAiNotes.d.ts.map +1 -0
- package/types/lib/parsers/gitmodules.d.ts +88 -0
- package/types/lib/parsers/gitmodules.d.ts.map +1 -0
- package/types/lib/parsers/htmlExtract.d.ts +34 -0
- package/types/lib/parsers/htmlExtract.d.ts.map +1 -0
- package/types/lib/parsers/huggingfaceManifest.d.ts +153 -0
- package/types/lib/parsers/huggingfaceManifest.d.ts.map +1 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts +155 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -0
- package/types/lib/parsers/iri.d.ts +68 -0
- package/types/lib/parsers/iri.d.ts.map +1 -0
- package/types/lib/parsers/npmrc.d.ts +33 -0
- package/types/lib/parsers/npmrc.d.ts.map +1 -0
- package/types/lib/parsers/ollama.d.ts +22 -0
- package/types/lib/parsers/ollama.d.ts.map +1 -0
- package/types/lib/parsers/xml.d.ts +47 -0
- package/types/lib/parsers/xml.d.ts.map +1 -0
- package/types/lib/server/server.d.ts +51 -0
- package/types/lib/server/server.d.ts.map +1 -0
- package/types/lib/stages/postgen/annotator.d.ts +36 -0
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -0
- package/types/lib/stages/postgen/auditBom.d.ts +92 -0
- package/types/lib/stages/postgen/auditBom.d.ts.map +1 -0
- package/types/lib/stages/postgen/postgen.d.ts +59 -0
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -0
- package/types/lib/stages/postgen/ruleEngine.d.ts +18 -0
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -0
- package/types/lib/stages/postgen/sortBom.d.ts +34 -0
- package/types/lib/stages/postgen/sortBom.d.ts.map +1 -0
- package/types/lib/stages/postgen/spdxConverter.d.ts +11 -0
- package/types/lib/stages/postgen/spdxConverter.d.ts.map +1 -0
- package/types/lib/stages/postgen/specVersionCompat.d.ts +71 -0
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -0
- package/types/lib/stages/pregen/envAudit.d.ts +14 -0
- package/types/lib/stages/pregen/envAudit.d.ts.map +1 -0
- package/types/lib/stages/pregen/pregen.d.ts +59 -0
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/arborist/index.d.ts +47 -0
- package/types/lib/third-party/arborist/lib/arborist/index.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts +4 -0
- package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts +4 -0
- package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/bin-links.d.ts +18 -0
- package/types/lib/third-party/arborist/lib/bin-links.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/calc-dep-flags.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/calc-dep-flags.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts +9 -0
- package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/consistent-resolve.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/consistent-resolve.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/debug.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/debug.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/dep-valid.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/dep-valid.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/edge.d.ts +46 -0
- package/types/lib/third-party/arborist/lib/edge.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/from-path.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/from-path.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/index.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/index.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/inventory.d.ts +14 -0
- package/types/lib/third-party/arborist/lib/inventory.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/link.d.ts +18 -0
- package/types/lib/third-party/arborist/lib/link.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/node.d.ts +112 -0
- package/types/lib/third-party/arborist/lib/node.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/npm-extension.d.ts +18 -0
- package/types/lib/third-party/arborist/lib/npm-extension.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/override-resolves.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/override-resolves.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/override-set.d.ts +27 -0
- package/types/lib/third-party/arborist/lib/override-set.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/package-extensions.d.ts +36 -0
- package/types/lib/third-party/arborist/lib/package-extensions.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/printable.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/printable.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/proc-log.d.ts +20 -0
- package/types/lib/third-party/arborist/lib/proc-log.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/realpath.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/realpath.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/relpath.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/relpath.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts +54 -0
- package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/spec-from-lock.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/spec-from-lock.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/tree-check.d.ts +3 -0
- package/types/lib/third-party/arborist/lib/tree-check.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/validate-npm-package-name.d.ts +13 -0
- package/types/lib/third-party/arborist/lib/validate-npm-package-name.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts +6 -0
- package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts.map +1 -0
- package/types/lib/third-party/arborist/lib/yarn-lock.d.ts +35 -0
- package/types/lib/third-party/arborist/lib/yarn-lock.d.ts.map +1 -0
- package/types/lib/validator/bomValidator.d.ts +40 -0
- package/types/lib/validator/bomValidator.d.ts.map +1 -0
- package/types/lib/validator/complianceEngine.d.ts +72 -0
- package/types/lib/validator/complianceEngine.d.ts.map +1 -0
- package/types/lib/validator/complianceRules.d.ts +61 -0
- package/types/lib/validator/complianceRules.d.ts.map +1 -0
- package/types/lib/validator/index.d.ts +101 -0
- package/types/lib/validator/index.d.ts.map +1 -0
- package/types/lib/validator/reporters/annotations.d.ts +37 -0
- package/types/lib/validator/reporters/annotations.d.ts.map +1 -0
- package/types/lib/validator/reporters/console.d.ts +34 -0
- package/types/lib/validator/reporters/console.d.ts.map +1 -0
- package/types/lib/validator/reporters/index.d.ts +30 -0
- package/types/lib/validator/reporters/index.d.ts.map +1 -0
- package/types/lib/validator/reporters/json.d.ts +11 -0
- package/types/lib/validator/reporters/json.d.ts.map +1 -0
- package/types/lib/validator/reporters/sarif.d.ts +22 -0
- package/types/lib/validator/reporters/sarif.d.ts.map +1 -0
- package/mod.d.ts +0 -7
- package/mod.js +0 -22
package/bin/repl.js
ADDED
|
@@ -0,0 +1,2224 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import process from "node:process";
|
|
7
|
+
import repl from "node:repl";
|
|
8
|
+
|
|
9
|
+
import jsonata from "jsonata";
|
|
10
|
+
|
|
11
|
+
import { createBom } from "../lib/cli/index.js";
|
|
12
|
+
import { readEnvironmentVariable } from "../lib/core/activity.js";
|
|
13
|
+
import {
|
|
14
|
+
getTmpDir,
|
|
15
|
+
isDryRun,
|
|
16
|
+
safeExistsSync,
|
|
17
|
+
safeMkdirSync,
|
|
18
|
+
safeMkdtempSync,
|
|
19
|
+
safeWriteSync,
|
|
20
|
+
} from "../lib/ecosystems/utils.js";
|
|
21
|
+
import { isSpdxJsonLd } from "../lib/inventory/bomUtils.js";
|
|
22
|
+
import {
|
|
23
|
+
printAiBomDatasets,
|
|
24
|
+
printAiBomInsights,
|
|
25
|
+
printAiBomPedigree,
|
|
26
|
+
printAiBomVariants,
|
|
27
|
+
printCallStack,
|
|
28
|
+
printDependencyTree,
|
|
29
|
+
printFormulation,
|
|
30
|
+
printOccurrences,
|
|
31
|
+
printOSTable,
|
|
32
|
+
printServices,
|
|
33
|
+
printSummary,
|
|
34
|
+
printTable,
|
|
35
|
+
printVulnerabilities,
|
|
36
|
+
} from "../lib/inventory/display.js";
|
|
37
|
+
import {
|
|
38
|
+
formatHbomHardwareClassSummary,
|
|
39
|
+
getHbomSummary,
|
|
40
|
+
isHbomLikeBom,
|
|
41
|
+
} from "../lib/inventory/hbomAnalysis.js";
|
|
42
|
+
import {
|
|
43
|
+
getPropertyValue,
|
|
44
|
+
getSourceDerivedCryptoComponents,
|
|
45
|
+
getUnpackagedExecutableComponents,
|
|
46
|
+
getUnpackagedSharedLibraryComponents,
|
|
47
|
+
} from "../lib/inventory/inventoryStats.js";
|
|
48
|
+
import {
|
|
49
|
+
importProtobomModule,
|
|
50
|
+
isProtoBomPath,
|
|
51
|
+
} from "../lib/inventory/protobomLoader.js";
|
|
52
|
+
import {
|
|
53
|
+
getProvenanceComponents,
|
|
54
|
+
getTrustedComponents,
|
|
55
|
+
} from "../lib/inventory/provenanceUtils.js";
|
|
56
|
+
import { toCycloneDxLikeBom } from "../lib/inventory/spdxUtils.js";
|
|
57
|
+
import { table } from "../lib/inventory/table.js";
|
|
58
|
+
import { getBomWithOras } from "../lib/managers/oci.js";
|
|
59
|
+
import { validateBom } from "../lib/validator/bomValidator.js";
|
|
60
|
+
|
|
61
|
+
const options = {
|
|
62
|
+
useColors: true,
|
|
63
|
+
breakEvalOnSigint: true,
|
|
64
|
+
preview: true,
|
|
65
|
+
prompt: "cdx ↝ ",
|
|
66
|
+
ignoreUndefined: true,
|
|
67
|
+
useGlobal: true,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// Use canonical terminal settings to support custom readlines
|
|
71
|
+
process.env.NODE_NO_READLINE = 1;
|
|
72
|
+
|
|
73
|
+
const cdxArt = `
|
|
74
|
+
██████╗██████╗ ██╗ ██╗
|
|
75
|
+
██╔════╝██╔══██╗╚██╗██╔╝
|
|
76
|
+
██║ ██║ ██║ ╚███╔╝
|
|
77
|
+
██║ ██║ ██║ ██╔██╗
|
|
78
|
+
╚██████╗██████╔╝██╔╝ ██╗
|
|
79
|
+
╚═════╝╚═════╝ ╚═╝ ╚═╝
|
|
80
|
+
`;
|
|
81
|
+
|
|
82
|
+
console.log(cdxArt);
|
|
83
|
+
|
|
84
|
+
if (readEnvironmentVariable("CDXGEN_NODE_OPTIONS")) {
|
|
85
|
+
process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS || ""} ${process.env.CDXGEN_NODE_OPTIONS}`;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// The current sbom is stored here
|
|
89
|
+
let sbom;
|
|
90
|
+
const getInteractiveBom = () => toCycloneDxLikeBom(sbom);
|
|
91
|
+
|
|
92
|
+
function getContainerRegistryHost(reference) {
|
|
93
|
+
const trimmedReference = `${reference || ""}`.trim().toLowerCase();
|
|
94
|
+
if (!trimmedReference) {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
const slashIndex = trimmedReference.indexOf("/");
|
|
98
|
+
if (slashIndex <= 0) {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
return trimmedReference.slice(0, slashIndex).replace(/:\d+$/, "");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function isSupportedSbomRegistryReference(reference) {
|
|
105
|
+
const registryHost = getContainerRegistryHost(reference);
|
|
106
|
+
return registryHost === "ghcr.io" || registryHost === "docker.io";
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function unescapeAnnotationText(value) {
|
|
110
|
+
return String(value || "")
|
|
111
|
+
.replace(/<br>/g, "\n")
|
|
112
|
+
.replace(/</g, "<")
|
|
113
|
+
.replace(/>/g, ">")
|
|
114
|
+
.replace(/&/g, "&")
|
|
115
|
+
.replace(/\\([\\`*_{}\[\]()#+!|])/g, "$1")
|
|
116
|
+
.trim();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function parseAnnotationProperties(text) {
|
|
120
|
+
const properties = {};
|
|
121
|
+
const lines = String(text || "").split(/\r?\n/);
|
|
122
|
+
let foundHeader = false;
|
|
123
|
+
for (const line of lines) {
|
|
124
|
+
if (!line.startsWith("|")) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const cells = line
|
|
128
|
+
.split("|")
|
|
129
|
+
.slice(1, -1)
|
|
130
|
+
.map((cell) => cell.trim());
|
|
131
|
+
if (cells.length < 2) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (cells[0] === "Property" && cells[1] === "Value") {
|
|
135
|
+
foundHeader = true;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (
|
|
139
|
+
foundHeader &&
|
|
140
|
+
/^-+$/.test(cells[0].replace(/\s/g, "")) &&
|
|
141
|
+
/^-+$/.test(cells[1].replace(/\s/g, ""))
|
|
142
|
+
) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (!foundHeader) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
properties[unescapeAnnotationText(cells[0])] = unescapeAnnotationText(
|
|
149
|
+
cells[1],
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
return properties;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function getAuditAnnotations() {
|
|
156
|
+
return (sbom?.annotations || [])
|
|
157
|
+
.map((annotation) => {
|
|
158
|
+
const properties = parseAnnotationProperties(annotation?.text);
|
|
159
|
+
return {
|
|
160
|
+
firstLine: unescapeAnnotationText(
|
|
161
|
+
String(annotation?.text || "").split(/\r?\n/, 1)[0],
|
|
162
|
+
),
|
|
163
|
+
properties,
|
|
164
|
+
raw: annotation,
|
|
165
|
+
};
|
|
166
|
+
})
|
|
167
|
+
.filter(
|
|
168
|
+
(annotation) =>
|
|
169
|
+
Object.keys(annotation.properties).some((key) =>
|
|
170
|
+
key.startsWith("cdx:audit:"),
|
|
171
|
+
) || annotation.firstLine.includes("cdx:audit:"),
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function printAuditTable(title, rows) {
|
|
176
|
+
if (rows.length <= 1) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
console.log(
|
|
180
|
+
table(rows, {
|
|
181
|
+
header: {
|
|
182
|
+
alignment: "center",
|
|
183
|
+
content: title,
|
|
184
|
+
},
|
|
185
|
+
}),
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function printKeyValueTable(title, entries) {
|
|
190
|
+
const rows = [["Field", "Value"]];
|
|
191
|
+
entries.forEach(([field, value]) => {
|
|
192
|
+
if (value === undefined || value === null || value === "") {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
rows.push([field, `${value}`]);
|
|
196
|
+
});
|
|
197
|
+
printAuditTable(title, rows);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function isLikelyObom(bom) {
|
|
201
|
+
return Boolean(
|
|
202
|
+
bom?.components?.some((comp) =>
|
|
203
|
+
comp?.properties?.some((prop) => prop?.name === "cdx:osquery:category"),
|
|
204
|
+
),
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function isLikelyHbom(bom) {
|
|
209
|
+
return isHbomLikeBom(bom);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function isLikelyCargoBom(bom) {
|
|
213
|
+
const formulation = Array.isArray(bom?.formulation)
|
|
214
|
+
? bom.formulation
|
|
215
|
+
: bom?.formulation
|
|
216
|
+
? [bom.formulation]
|
|
217
|
+
: [];
|
|
218
|
+
return Boolean(
|
|
219
|
+
bom?.components?.some((component) =>
|
|
220
|
+
component?.purl?.startsWith("pkg:cargo/"),
|
|
221
|
+
) ||
|
|
222
|
+
formulation.some((entry) =>
|
|
223
|
+
entry?.components?.some(
|
|
224
|
+
(component) =>
|
|
225
|
+
getPropertyValue(component, "cdx:rust:buildTool") === "cargo",
|
|
226
|
+
),
|
|
227
|
+
),
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function hasGolemProperties(component) {
|
|
232
|
+
return Boolean(
|
|
233
|
+
component?.properties?.some((property) =>
|
|
234
|
+
property?.name?.startsWith("cdx:golem:"),
|
|
235
|
+
),
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function isLikelyGolemBom(bom) {
|
|
240
|
+
return Boolean(
|
|
241
|
+
hasGolemProperties(bom?.metadata?.component) ||
|
|
242
|
+
bom?.components?.some((component) => hasGolemProperties(component)),
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function getGolemComponents(bom) {
|
|
247
|
+
return (bom?.components || []).filter((component) =>
|
|
248
|
+
hasGolemProperties(component),
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function getGolemHotspotComponents(bom) {
|
|
253
|
+
return getGolemComponents(bom).filter(
|
|
254
|
+
(component) =>
|
|
255
|
+
Boolean(
|
|
256
|
+
getPropertyValue(component, "cdx:golem:securitySignalSeverity"),
|
|
257
|
+
) ||
|
|
258
|
+
getPropertyValue(component, "cdx:golem:localReplacement") === "true" ||
|
|
259
|
+
getPropertyValue(component, "cdx:golem:privateModuleCandidate") ===
|
|
260
|
+
"true" ||
|
|
261
|
+
getPropertyValue(component, "cdx:golem:vendored") === "true",
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function getGolemCoverageComponents(bom) {
|
|
266
|
+
return getGolemComponents(bom).filter(
|
|
267
|
+
(component) =>
|
|
268
|
+
Boolean(getPropertyValue(component, "cdx:golem:usageScopes")) ||
|
|
269
|
+
Boolean(
|
|
270
|
+
getPropertyValue(component, "cdx:golem:occurrenceEvidenceKinds"),
|
|
271
|
+
) ||
|
|
272
|
+
component?.evidence?.occurrences?.length ||
|
|
273
|
+
component?.evidence?.callstack?.frames?.length,
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function getCargoHotspotComponents(bom) {
|
|
278
|
+
return (bom?.components || []).filter(
|
|
279
|
+
(component) =>
|
|
280
|
+
component?.purl?.startsWith("pkg:cargo/") &&
|
|
281
|
+
(getPropertyValue(component, "cdx:cargo:yanked") === "true" ||
|
|
282
|
+
Boolean(getPropertyValue(component, "cdx:cargo:git")) ||
|
|
283
|
+
Boolean(getPropertyValue(component, "cdx:cargo:path")) ||
|
|
284
|
+
getPropertyValue(component, "cdx:cargo:dependencyKind") === "build" ||
|
|
285
|
+
getPropertyValue(component, "cdx:cargo:workspaceDependencyResolved") ===
|
|
286
|
+
"true" ||
|
|
287
|
+
Boolean(getPropertyValue(component, "cdx:cargo:target"))),
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function getCargoWorkflowComponents(bom) {
|
|
292
|
+
return (bom?.components || []).filter(
|
|
293
|
+
(component) =>
|
|
294
|
+
getPropertyValue(component, "cdx:github:action:ecosystem") === "cargo" ||
|
|
295
|
+
getPropertyValue(component, "cdx:github:step:usesCargo") === "true",
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function getCargoFormulationEntries(bom) {
|
|
300
|
+
const formulation = Array.isArray(bom?.formulation)
|
|
301
|
+
? bom.formulation
|
|
302
|
+
: bom?.formulation
|
|
303
|
+
? [bom.formulation]
|
|
304
|
+
: [];
|
|
305
|
+
const matchingEntries = [];
|
|
306
|
+
for (const formulationEntry of formulation) {
|
|
307
|
+
const cargoComponents = (formulationEntry?.components || []).filter(
|
|
308
|
+
(component) =>
|
|
309
|
+
getPropertyValue(component, "cdx:rust:buildTool") === "cargo",
|
|
310
|
+
);
|
|
311
|
+
if (cargoComponents.length) {
|
|
312
|
+
matchingEntries.push({
|
|
313
|
+
...formulationEntry,
|
|
314
|
+
components: cargoComponents,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return matchingEntries;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const HBOM_FIRMWARE_PROPERTIES = Object.freeze([
|
|
322
|
+
"cdx:hbom:protocol",
|
|
323
|
+
"cdx:hbom:flags",
|
|
324
|
+
"cdx:hbom:guids",
|
|
325
|
+
"cdx:hbom:instanceIds",
|
|
326
|
+
"cdx:hbom:createdEpoch",
|
|
327
|
+
"cdx:hbom:firmwareDate",
|
|
328
|
+
]);
|
|
329
|
+
|
|
330
|
+
const HBOM_BUS_SECURITY_PROPERTIES = Object.freeze([
|
|
331
|
+
"cdx:hbom:securityLevel",
|
|
332
|
+
"cdx:hbom:iommuProtection",
|
|
333
|
+
"cdx:hbom:policy",
|
|
334
|
+
"cdx:hbom:authorized",
|
|
335
|
+
"cdx:hbom:usbVersion",
|
|
336
|
+
"cdx:hbom:usbClassName",
|
|
337
|
+
"cdx:hbom:usbInterfaceClasses",
|
|
338
|
+
"cdx:hbom:pciClass",
|
|
339
|
+
"cdx:hbom:pciClassCode",
|
|
340
|
+
"cdx:hbom:displayConnectorType",
|
|
341
|
+
"cdx:hbom:contentProtection",
|
|
342
|
+
"cdx:hbom:drmNode",
|
|
343
|
+
]);
|
|
344
|
+
|
|
345
|
+
const HBOM_POWER_PROPERTIES = Object.freeze([
|
|
346
|
+
"cdx:hbom:designCapacityPercent",
|
|
347
|
+
"cdx:hbom:energyNow",
|
|
348
|
+
"cdx:hbom:energyFull",
|
|
349
|
+
"cdx:hbom:energyFullDesign",
|
|
350
|
+
"cdx:hbom:chargeNow",
|
|
351
|
+
"cdx:hbom:chargeFull",
|
|
352
|
+
"cdx:hbom:chargeFullDesign",
|
|
353
|
+
"cdx:hbom:powerNow",
|
|
354
|
+
"cdx:hbom:voltageNow",
|
|
355
|
+
"cdx:hbom:currentNow",
|
|
356
|
+
"cdx:hbom:warningLevel",
|
|
357
|
+
]);
|
|
358
|
+
|
|
359
|
+
function getInteractiveHbomOrWarn(replContext) {
|
|
360
|
+
const interactiveBom = getInteractiveBom();
|
|
361
|
+
if (!interactiveBom) {
|
|
362
|
+
console.log(
|
|
363
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
364
|
+
);
|
|
365
|
+
replContext.displayPrompt();
|
|
366
|
+
return undefined;
|
|
367
|
+
}
|
|
368
|
+
if (!isLikelyHbom(interactiveBom)) {
|
|
369
|
+
console.log(
|
|
370
|
+
"This BOM does not look like an HBOM. Import an HBOM generated with 'cdxgen -t hbom' to use this view.",
|
|
371
|
+
);
|
|
372
|
+
replContext.displayPrompt();
|
|
373
|
+
return undefined;
|
|
374
|
+
}
|
|
375
|
+
return interactiveBom;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function filterHbomComponentsByProperties(
|
|
379
|
+
bom,
|
|
380
|
+
propertyNames,
|
|
381
|
+
hardwareClasses = [],
|
|
382
|
+
) {
|
|
383
|
+
return (bom?.components || []).filter((component) => {
|
|
384
|
+
const hardwareClass = getPropertyValue(component, "cdx:hbom:hardwareClass");
|
|
385
|
+
if (hardwareClasses.includes(hardwareClass)) {
|
|
386
|
+
return true;
|
|
387
|
+
}
|
|
388
|
+
return propertyNames.some((propertyName) =>
|
|
389
|
+
Boolean(getPropertyValue(component, propertyName)),
|
|
390
|
+
);
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function getDiagnosticDisplayDetail(diagnostic) {
|
|
395
|
+
return (
|
|
396
|
+
diagnostic.installHint ||
|
|
397
|
+
diagnostic.privilegeHint ||
|
|
398
|
+
diagnostic.message ||
|
|
399
|
+
diagnostic.code ||
|
|
400
|
+
"-"
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
let historyFile;
|
|
405
|
+
const historyConfigDir = join(homedir(), ".config", ".cdxgen");
|
|
406
|
+
if (
|
|
407
|
+
!readEnvironmentVariable("CDXGEN_REPL_HISTORY") &&
|
|
408
|
+
!safeExistsSync(historyConfigDir)
|
|
409
|
+
) {
|
|
410
|
+
try {
|
|
411
|
+
safeMkdirSync(historyConfigDir, { recursive: true });
|
|
412
|
+
historyFile = join(historyConfigDir, ".repl_history");
|
|
413
|
+
} catch (_e) {
|
|
414
|
+
// ignore
|
|
415
|
+
}
|
|
416
|
+
} else {
|
|
417
|
+
historyFile = join(historyConfigDir, ".repl_history");
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
export const importSbom = async (sbomOrPath) => {
|
|
421
|
+
const importTarget = String(sbomOrPath || "").trim();
|
|
422
|
+
if (!importTarget) {
|
|
423
|
+
console.log("⚠ An SBOM path or image reference is required.");
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
if (importTarget.endsWith(".json") && safeExistsSync(importTarget)) {
|
|
427
|
+
try {
|
|
428
|
+
sbom = JSON.parse(readFileSync(importTarget, "utf-8"));
|
|
429
|
+
let bomType = "SBOM";
|
|
430
|
+
if (isSpdxJsonLd(sbom)) {
|
|
431
|
+
bomType = "SPDX";
|
|
432
|
+
}
|
|
433
|
+
if (sbom?.vulnerabilities && Array.isArray(sbom.vulnerabilities)) {
|
|
434
|
+
bomType = "VDR";
|
|
435
|
+
}
|
|
436
|
+
console.log(`✅ ${bomType} imported successfully from ${importTarget}`);
|
|
437
|
+
printSummary(sbom);
|
|
438
|
+
if (isLikelyHbom(sbom)) {
|
|
439
|
+
console.log(
|
|
440
|
+
"💭 HBOM detected. Try .hbomsummary, .hbomevidence, .hbomdiagnostics, or .hbomtips",
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
if (isLikelyObom(sbom)) {
|
|
444
|
+
console.log(
|
|
445
|
+
"💭 OBOM detected. Try .osinfocategories, .obomtips, .processes, or .services_snapshot",
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
if (isLikelyCargoBom(sbom)) {
|
|
449
|
+
console.log(
|
|
450
|
+
"💭 Cargo signals detected. Try .cargohotspots or .cargoworkflows.",
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
if (isLikelyGolemBom(sbom)) {
|
|
454
|
+
console.log(
|
|
455
|
+
"💭 Go Evinse/Golem signals detected. Try .golemsummary, .golemhotspots, .golemcoverage, or .golemtips.",
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
if (getAuditAnnotations().length) {
|
|
459
|
+
console.log(
|
|
460
|
+
"💭 Audit annotations detected. Try .auditfindings, .auditactions, or .dispatchedges.",
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
} catch (e) {
|
|
464
|
+
console.log(
|
|
465
|
+
`⚠ Unable to import the BOM from ${importTarget} due to ${e}`,
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
} else if (isProtoBomPath(importTarget) && safeExistsSync(importTarget)) {
|
|
469
|
+
const { readBinary } = await importProtobomModule(
|
|
470
|
+
"cdxi",
|
|
471
|
+
"protobuf BOM input",
|
|
472
|
+
);
|
|
473
|
+
sbom = readBinary(importTarget, true);
|
|
474
|
+
printSummary(sbom);
|
|
475
|
+
} else if (isSupportedSbomRegistryReference(importTarget)) {
|
|
476
|
+
try {
|
|
477
|
+
sbom = await getBomWithOras(importTarget);
|
|
478
|
+
if (sbom) {
|
|
479
|
+
printSummary(sbom);
|
|
480
|
+
} else {
|
|
481
|
+
console.log(
|
|
482
|
+
`cyclonedx sbom attachment was not found within ${importTarget}`,
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
} catch (e) {
|
|
486
|
+
console.log(
|
|
487
|
+
`⚠ Unable to import the BOM from ${importTarget} due to ${e}`,
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
} else {
|
|
491
|
+
console.log(`⚠ ${importTarget} is invalid.`);
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
// Load any sbom passed from the command line
|
|
495
|
+
if (process.argv.length > 2) {
|
|
496
|
+
await importSbom(process.argv[process.argv.length - 1]);
|
|
497
|
+
console.log("💭 Type .print to view the BOM as a table");
|
|
498
|
+
console.log("💭 Type .trusted to list components with trusted publishing.");
|
|
499
|
+
console.log(
|
|
500
|
+
"💭 Type .provenance to list components with registry provenance evidence.",
|
|
501
|
+
);
|
|
502
|
+
if (isLikelyHbom(sbom)) {
|
|
503
|
+
console.log(
|
|
504
|
+
"💭 Type .hbomsummary to review the host profile, evidence coverage, hardware-class mix, and collector diagnostics.",
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
if (getAuditAnnotations().length) {
|
|
508
|
+
console.log(
|
|
509
|
+
"💭 Type .auditfindings to review cdx-audit and bom-audit annotations.",
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
if (isLikelyGolemBom(sbom)) {
|
|
513
|
+
console.log(
|
|
514
|
+
"💭 Type .golemsummary to review Go Evinse/Golem metadata and evidence coverage.",
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
} else if (safeExistsSync("bom.json")) {
|
|
518
|
+
// If the current directory has a bom.json load it
|
|
519
|
+
await importSbom("bom.json");
|
|
520
|
+
} else {
|
|
521
|
+
console.log("💭 Use .create <path> to create an SBOM for the given path.");
|
|
522
|
+
console.log("💭 Use .import <json> to import an existing BOM.");
|
|
523
|
+
console.log(
|
|
524
|
+
"💭 For OBOM investigations, try .obomtips after importing an OBOM.",
|
|
525
|
+
);
|
|
526
|
+
console.log(
|
|
527
|
+
"💭 For HBOM investigations, try .hbomtips after importing an HBOM.",
|
|
528
|
+
);
|
|
529
|
+
console.log("💭 Type .exit or press ctrl+d to close.");
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
const cdxgenRepl = repl.start(options);
|
|
533
|
+
if (historyFile) {
|
|
534
|
+
cdxgenRepl.setupHistory(
|
|
535
|
+
readEnvironmentVariable("CDXGEN_REPL_HISTORY") || historyFile,
|
|
536
|
+
(err) => {
|
|
537
|
+
if (err) {
|
|
538
|
+
console.log(
|
|
539
|
+
"⚠ REPL history would not be persisted for this session. Set the environment variable CDXGEN_REPL_HISTORY to specify a custom history file",
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
cdxgenRepl.defineCommand("create", {
|
|
546
|
+
help: "create an SBOM for the given path",
|
|
547
|
+
async action(sbomOrPath) {
|
|
548
|
+
this.clearBufferedCommand();
|
|
549
|
+
const tempDir = safeMkdtempSync(join(getTmpDir(), "cdxgen-repl-"));
|
|
550
|
+
const bomFile = join(tempDir, "bom.json");
|
|
551
|
+
const bomNSData = await createBom(sbomOrPath, {
|
|
552
|
+
multiProject: true,
|
|
553
|
+
installDeps: true,
|
|
554
|
+
output: bomFile,
|
|
555
|
+
});
|
|
556
|
+
if (bomNSData) {
|
|
557
|
+
sbom = bomNSData.bomJson;
|
|
558
|
+
console.log("✅ BOM imported successfully.");
|
|
559
|
+
console.log("💭 Type .print to view the BOM as a table");
|
|
560
|
+
console.log(
|
|
561
|
+
"💭 Type .trusted to list components with trusted publishing.",
|
|
562
|
+
);
|
|
563
|
+
console.log(
|
|
564
|
+
"💭 Type .provenance to list components with registry provenance evidence.",
|
|
565
|
+
);
|
|
566
|
+
if (
|
|
567
|
+
sbom?.components?.some(
|
|
568
|
+
(component) =>
|
|
569
|
+
component?.type === "machine-learning-model" ||
|
|
570
|
+
component?.modelCard ||
|
|
571
|
+
component?.pedigree,
|
|
572
|
+
)
|
|
573
|
+
) {
|
|
574
|
+
console.log(
|
|
575
|
+
"💭 Type .aibom, .aipedigree, .aivariants, or .aidatasets for focused AI-BOM views.",
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
if (isLikelyHbom(sbom)) {
|
|
579
|
+
console.log(
|
|
580
|
+
"💭 Type .hbomsummary or .hbomdiagnostics for focused hardware inventory and collector-diagnostic summaries.",
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
if (getAuditAnnotations().length) {
|
|
584
|
+
console.log(
|
|
585
|
+
"💭 Type .auditfindings to review cdx-audit and bom-audit annotations.",
|
|
586
|
+
);
|
|
587
|
+
}
|
|
588
|
+
if (isLikelyCargoBom(sbom)) {
|
|
589
|
+
console.log(
|
|
590
|
+
"💭 Type .cargohotspots or .cargoworkflows for Cargo-specific pivots.",
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
if (isLikelyGolemBom(sbom)) {
|
|
594
|
+
console.log(
|
|
595
|
+
"💭 Type .golemsummary, .golemhotspots, or .golemcoverage for Go Evinse/Golem pivots.",
|
|
596
|
+
);
|
|
597
|
+
}
|
|
598
|
+
} else {
|
|
599
|
+
console.log("BOM was not generated successfully");
|
|
600
|
+
}
|
|
601
|
+
this.displayPrompt();
|
|
602
|
+
},
|
|
603
|
+
});
|
|
604
|
+
cdxgenRepl.defineCommand("import", {
|
|
605
|
+
help: "import an existing BOM",
|
|
606
|
+
async action(sbomOrPath) {
|
|
607
|
+
this.clearBufferedCommand();
|
|
608
|
+
await importSbom(sbomOrPath);
|
|
609
|
+
this.displayPrompt();
|
|
610
|
+
},
|
|
611
|
+
});
|
|
612
|
+
cdxgenRepl.defineCommand("summary", {
|
|
613
|
+
help: "summarize an existing BOM",
|
|
614
|
+
action() {
|
|
615
|
+
if (sbom) {
|
|
616
|
+
printSummary(sbom);
|
|
617
|
+
} else {
|
|
618
|
+
console.log(
|
|
619
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
620
|
+
);
|
|
621
|
+
}
|
|
622
|
+
this.displayPrompt();
|
|
623
|
+
},
|
|
624
|
+
});
|
|
625
|
+
cdxgenRepl.defineCommand("aibom", {
|
|
626
|
+
help: "show an operator-friendly AI-BOM summary with pedigree and quantization context",
|
|
627
|
+
action() {
|
|
628
|
+
const interactiveBom = getInteractiveBom();
|
|
629
|
+
if (!interactiveBom) {
|
|
630
|
+
console.log(
|
|
631
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
632
|
+
);
|
|
633
|
+
this.displayPrompt();
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
printAiBomInsights(interactiveBom);
|
|
637
|
+
this.displayPrompt();
|
|
638
|
+
},
|
|
639
|
+
});
|
|
640
|
+
cdxgenRepl.defineCommand("aipedigree", {
|
|
641
|
+
help: "show AI model ancestry, pedigree notes, and related variants",
|
|
642
|
+
action() {
|
|
643
|
+
const interactiveBom = getInteractiveBom();
|
|
644
|
+
if (!interactiveBom) {
|
|
645
|
+
console.log(
|
|
646
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
647
|
+
);
|
|
648
|
+
this.displayPrompt();
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
printAiBomPedigree(interactiveBom);
|
|
652
|
+
this.displayPrompt();
|
|
653
|
+
},
|
|
654
|
+
});
|
|
655
|
+
cdxgenRepl.defineCommand("aivariants", {
|
|
656
|
+
help: "show detected fine-tuned, distilled, quantized, unlocked, and abliterated models",
|
|
657
|
+
action() {
|
|
658
|
+
const interactiveBom = getInteractiveBom();
|
|
659
|
+
if (!interactiveBom) {
|
|
660
|
+
console.log(
|
|
661
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
662
|
+
);
|
|
663
|
+
this.displayPrompt();
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
printAiBomVariants(interactiveBom);
|
|
667
|
+
this.displayPrompt();
|
|
668
|
+
},
|
|
669
|
+
});
|
|
670
|
+
cdxgenRepl.defineCommand("aidatasets", {
|
|
671
|
+
help: "show model card dataset usage for AI models",
|
|
672
|
+
action() {
|
|
673
|
+
const interactiveBom = getInteractiveBom();
|
|
674
|
+
if (!interactiveBom) {
|
|
675
|
+
console.log(
|
|
676
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
677
|
+
);
|
|
678
|
+
this.displayPrompt();
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
printAiBomDatasets(interactiveBom);
|
|
682
|
+
this.displayPrompt();
|
|
683
|
+
},
|
|
684
|
+
});
|
|
685
|
+
cdxgenRepl.defineCommand("hbomsummary", {
|
|
686
|
+
help: "summarize HBOM host metadata, evidence coverage, and hardware-class mix",
|
|
687
|
+
action() {
|
|
688
|
+
const interactiveBom = getInteractiveBom();
|
|
689
|
+
if (!interactiveBom) {
|
|
690
|
+
console.log(
|
|
691
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
692
|
+
);
|
|
693
|
+
this.displayPrompt();
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
if (!isLikelyHbom(interactiveBom)) {
|
|
697
|
+
console.log(
|
|
698
|
+
"This BOM does not look like an HBOM. Import an HBOM generated with 'cdxgen -t hbom' to use this view.",
|
|
699
|
+
);
|
|
700
|
+
this.displayPrompt();
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
const hbomSummary = getHbomSummary(interactiveBom);
|
|
704
|
+
printKeyValueTable("HBOM summary", [
|
|
705
|
+
["Host", hbomSummary.metadataName],
|
|
706
|
+
["Component type", hbomSummary.metadataType],
|
|
707
|
+
["Manufacturer", hbomSummary.manufacturer],
|
|
708
|
+
["Platform", hbomSummary.platform],
|
|
709
|
+
["Architecture", hbomSummary.architecture],
|
|
710
|
+
["Collector profile", hbomSummary.collectorProfile],
|
|
711
|
+
["Identifier policy", hbomSummary.identifierPolicy],
|
|
712
|
+
["Component count", hbomSummary.componentCount],
|
|
713
|
+
["Hardware class count", hbomSummary.hardwareClassCount],
|
|
714
|
+
[
|
|
715
|
+
"Top hardware classes",
|
|
716
|
+
formatHbomHardwareClassSummary(hbomSummary.hardwareClassCounts),
|
|
717
|
+
],
|
|
718
|
+
["Command evidence count", hbomSummary.evidenceCommandCount],
|
|
719
|
+
["Observed file count", hbomSummary.evidenceFileCount],
|
|
720
|
+
]);
|
|
721
|
+
this.displayPrompt();
|
|
722
|
+
},
|
|
723
|
+
});
|
|
724
|
+
cdxgenRepl.defineCommand("hbomclasses", {
|
|
725
|
+
help: "show HBOM component counts by hardware class",
|
|
726
|
+
action() {
|
|
727
|
+
const interactiveBom = getInteractiveBom();
|
|
728
|
+
if (!interactiveBom) {
|
|
729
|
+
console.log(
|
|
730
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
731
|
+
);
|
|
732
|
+
this.displayPrompt();
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
if (!isLikelyHbom(interactiveBom)) {
|
|
736
|
+
console.log(
|
|
737
|
+
"This BOM does not look like an HBOM. Import an HBOM generated with 'cdxgen -t hbom' to use this view.",
|
|
738
|
+
);
|
|
739
|
+
this.displayPrompt();
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
const hbomSummary = getHbomSummary(interactiveBom);
|
|
743
|
+
if (!hbomSummary.hardwareClassCounts.length) {
|
|
744
|
+
console.log(
|
|
745
|
+
"No HBOM hardware classes were found on the loaded BOM. Check whether the document includes cdx:hbom:hardwareClass properties.",
|
|
746
|
+
);
|
|
747
|
+
this.displayPrompt();
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
printAuditTable("HBOM hardware classes", [
|
|
751
|
+
["Hardware class", "Count"],
|
|
752
|
+
...hbomSummary.hardwareClassCounts.map(({ hardwareClass, count }) => [
|
|
753
|
+
hardwareClass,
|
|
754
|
+
`${count}`,
|
|
755
|
+
]),
|
|
756
|
+
]);
|
|
757
|
+
this.displayPrompt();
|
|
758
|
+
},
|
|
759
|
+
});
|
|
760
|
+
cdxgenRepl.defineCommand("hbomevidence", {
|
|
761
|
+
help: "show HBOM collector profile plus command and observed-file evidence",
|
|
762
|
+
action() {
|
|
763
|
+
const interactiveBom = getInteractiveBom();
|
|
764
|
+
if (!interactiveBom) {
|
|
765
|
+
console.log(
|
|
766
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
767
|
+
);
|
|
768
|
+
this.displayPrompt();
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
if (!isLikelyHbom(interactiveBom)) {
|
|
772
|
+
console.log(
|
|
773
|
+
"This BOM does not look like an HBOM. Import an HBOM generated with 'cdxgen -t hbom' to use this view.",
|
|
774
|
+
);
|
|
775
|
+
this.displayPrompt();
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
const hbomSummary = getHbomSummary(interactiveBom);
|
|
779
|
+
printKeyValueTable("HBOM evidence overview", [
|
|
780
|
+
["Collector profile", hbomSummary.collectorProfile],
|
|
781
|
+
["Command evidence count", hbomSummary.evidenceCommandCount],
|
|
782
|
+
["Observed file count", hbomSummary.evidenceFileCount],
|
|
783
|
+
]);
|
|
784
|
+
if (hbomSummary.evidenceCommands.length) {
|
|
785
|
+
printAuditTable("HBOM command evidence", [
|
|
786
|
+
["Command #", "Evidence"],
|
|
787
|
+
...hbomSummary.evidenceCommands.map((command, index) => [
|
|
788
|
+
`${index + 1}`,
|
|
789
|
+
command,
|
|
790
|
+
]),
|
|
791
|
+
]);
|
|
792
|
+
}
|
|
793
|
+
if (hbomSummary.evidenceFiles.length) {
|
|
794
|
+
printAuditTable("HBOM observed files", [
|
|
795
|
+
["File #", "Path"],
|
|
796
|
+
...hbomSummary.evidenceFiles.map((filePath, index) => [
|
|
797
|
+
`${index + 1}`,
|
|
798
|
+
filePath,
|
|
799
|
+
]),
|
|
800
|
+
]);
|
|
801
|
+
}
|
|
802
|
+
this.displayPrompt();
|
|
803
|
+
},
|
|
804
|
+
});
|
|
805
|
+
cdxgenRepl.defineCommand("instrumented", {
|
|
806
|
+
help: "show dynamically instrumented libraries and verification evidence",
|
|
807
|
+
action() {
|
|
808
|
+
const interactiveBom = getInteractiveBom();
|
|
809
|
+
if (!interactiveBom) {
|
|
810
|
+
console.log(
|
|
811
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
812
|
+
);
|
|
813
|
+
this.displayPrompt();
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
816
|
+
const instrumentedList = (interactiveBom.components || []).filter((c) =>
|
|
817
|
+
c.evidence?.identity?.some((id) =>
|
|
818
|
+
id.methods?.some((m) => m.technique === "instrumentation"),
|
|
819
|
+
),
|
|
820
|
+
);
|
|
821
|
+
if (!instrumentedList.length) {
|
|
822
|
+
console.log(
|
|
823
|
+
"No dynamically instrumented components found in the loaded BOM.",
|
|
824
|
+
);
|
|
825
|
+
this.displayPrompt();
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
const rows = [["Name", "Version", "Path", "Confidence"]];
|
|
829
|
+
for (const comp of instrumentedList) {
|
|
830
|
+
const pathProp =
|
|
831
|
+
comp.properties?.find((p) => p.name === "cdx:file_path")?.value || "";
|
|
832
|
+
const confidence = comp.evidence?.identity?.[0]?.confidence || "";
|
|
833
|
+
rows.push([
|
|
834
|
+
comp.name,
|
|
835
|
+
comp.version || "unknown",
|
|
836
|
+
pathProp,
|
|
837
|
+
String(confidence),
|
|
838
|
+
]);
|
|
839
|
+
}
|
|
840
|
+
console.log(
|
|
841
|
+
table(rows, {
|
|
842
|
+
header: {
|
|
843
|
+
alignment: "center",
|
|
844
|
+
content: "Dynamically Instrumented Components",
|
|
845
|
+
},
|
|
846
|
+
}),
|
|
847
|
+
);
|
|
848
|
+
this.displayPrompt();
|
|
849
|
+
},
|
|
850
|
+
});
|
|
851
|
+
cdxgenRepl.defineCommand("hbomdiagnostics", {
|
|
852
|
+
help: "show parsed HBOM command diagnostics, issue counts, and install or privilege guidance",
|
|
853
|
+
action() {
|
|
854
|
+
const interactiveBom = getInteractiveHbomOrWarn(this);
|
|
855
|
+
if (!interactiveBom) {
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
const hbomSummary = getHbomSummary(interactiveBom);
|
|
859
|
+
if (!hbomSummary.commandDiagnosticCount) {
|
|
860
|
+
console.log(
|
|
861
|
+
"No HBOM command diagnostics were found. This usually means the collector completed without recording missing-command or permission-denied enrichments.",
|
|
862
|
+
);
|
|
863
|
+
this.displayPrompt();
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
printKeyValueTable("HBOM diagnostic overview", [
|
|
867
|
+
["Diagnostic count", hbomSummary.commandDiagnosticCount],
|
|
868
|
+
["Actionable diagnostics", hbomSummary.actionableDiagnosticCount],
|
|
869
|
+
["Missing commands", hbomSummary.missingCommandCount],
|
|
870
|
+
["Permission denied", hbomSummary.permissionDeniedCount],
|
|
871
|
+
["Partial support", hbomSummary.partialSupportCount],
|
|
872
|
+
["Timeouts", hbomSummary.timeoutCount],
|
|
873
|
+
["Other command errors", hbomSummary.commandErrorCount],
|
|
874
|
+
["Diagnostic issues", hbomSummary.diagnosticIssues.join(", ")],
|
|
875
|
+
["Missing command IDs", hbomSummary.missingCommandIds.join(", ")],
|
|
876
|
+
["Permission-denied IDs", hbomSummary.permissionDeniedIds.join(", ")],
|
|
877
|
+
["Install hint count", hbomSummary.installHintCount],
|
|
878
|
+
["Privilege hint count", hbomSummary.privilegeHintCount],
|
|
879
|
+
[
|
|
880
|
+
"Requires privileged rerun",
|
|
881
|
+
hbomSummary.requiresPrivilegedEnrichment ? "yes" : "no",
|
|
882
|
+
],
|
|
883
|
+
]);
|
|
884
|
+
printAuditTable("HBOM command diagnostics", [
|
|
885
|
+
["Issue", "Diagnostic ID", "Command", "Hint / Message"],
|
|
886
|
+
...hbomSummary.commandDiagnostics.map((diagnostic) => [
|
|
887
|
+
diagnostic.issue || "unknown",
|
|
888
|
+
diagnostic.id || "-",
|
|
889
|
+
diagnostic.command || "-",
|
|
890
|
+
getDiagnosticDisplayDetail(diagnostic),
|
|
891
|
+
]),
|
|
892
|
+
]);
|
|
893
|
+
this.displayPrompt();
|
|
894
|
+
},
|
|
895
|
+
});
|
|
896
|
+
cdxgenRepl.defineCommand("hbomfirmware", {
|
|
897
|
+
help: "show firmware, board, TPM, and update-managed HBOM components plus host firmware provenance",
|
|
898
|
+
action() {
|
|
899
|
+
const interactiveBom = getInteractiveHbomOrWarn(this);
|
|
900
|
+
if (!interactiveBom) {
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
const metadataComponent = interactiveBom.metadata?.component;
|
|
904
|
+
const firmwareComponents = filterHbomComponentsByProperties(
|
|
905
|
+
interactiveBom,
|
|
906
|
+
HBOM_FIRMWARE_PROPERTIES,
|
|
907
|
+
["firmware", "board", "tpm"],
|
|
908
|
+
);
|
|
909
|
+
const metadataEntries = [
|
|
910
|
+
[
|
|
911
|
+
"Board vendor",
|
|
912
|
+
getPropertyValue(metadataComponent, "cdx:hbom:boardVendor"),
|
|
913
|
+
],
|
|
914
|
+
["Board name", getPropertyValue(metadataComponent, "cdx:hbom:boardName")],
|
|
915
|
+
[
|
|
916
|
+
"BIOS vendor",
|
|
917
|
+
getPropertyValue(metadataComponent, "cdx:hbom:biosVendor"),
|
|
918
|
+
],
|
|
919
|
+
[
|
|
920
|
+
"BIOS version",
|
|
921
|
+
getPropertyValue(metadataComponent, "cdx:hbom:biosVersion"),
|
|
922
|
+
],
|
|
923
|
+
[
|
|
924
|
+
"Firmware date",
|
|
925
|
+
getPropertyValue(metadataComponent, "cdx:hbom:firmwareDate"),
|
|
926
|
+
],
|
|
927
|
+
[
|
|
928
|
+
"Device-tree revision",
|
|
929
|
+
getPropertyValue(metadataComponent, "cdx:hbom:deviceTreeRevision"),
|
|
930
|
+
],
|
|
931
|
+
];
|
|
932
|
+
const hasMetadataProvenance = metadataEntries.some(([, value]) =>
|
|
933
|
+
Boolean(value),
|
|
934
|
+
);
|
|
935
|
+
if (!firmwareComponents.length && !hasMetadataProvenance) {
|
|
936
|
+
console.log(
|
|
937
|
+
"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.",
|
|
938
|
+
);
|
|
939
|
+
this.displayPrompt();
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
942
|
+
if (hasMetadataProvenance) {
|
|
943
|
+
printKeyValueTable("HBOM host firmware provenance", metadataEntries);
|
|
944
|
+
}
|
|
945
|
+
if (firmwareComponents.length) {
|
|
946
|
+
printTable(
|
|
947
|
+
{ components: firmwareComponents, dependencies: [] },
|
|
948
|
+
undefined,
|
|
949
|
+
undefined,
|
|
950
|
+
`Found ${firmwareComponents.length} firmware, board, TPM, or update-managed component(s).`,
|
|
951
|
+
);
|
|
952
|
+
}
|
|
953
|
+
this.displayPrompt();
|
|
954
|
+
},
|
|
955
|
+
});
|
|
956
|
+
cdxgenRepl.defineCommand("hbombuses", {
|
|
957
|
+
help: "show bus, connector, USB, PCI, and external-expansion HBOM components with security or topology metadata",
|
|
958
|
+
action() {
|
|
959
|
+
const interactiveBom = getInteractiveHbomOrWarn(this);
|
|
960
|
+
if (!interactiveBom) {
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
const busComponents = filterHbomComponentsByProperties(
|
|
964
|
+
interactiveBom,
|
|
965
|
+
HBOM_BUS_SECURITY_PROPERTIES,
|
|
966
|
+
[
|
|
967
|
+
"bus",
|
|
968
|
+
"usb-device",
|
|
969
|
+
"pci-device",
|
|
970
|
+
"display-adapter",
|
|
971
|
+
"display-connector",
|
|
972
|
+
],
|
|
973
|
+
);
|
|
974
|
+
if (!busComponents.length) {
|
|
975
|
+
console.log(
|
|
976
|
+
"No bus or connector components with focused security or topology metadata were found.",
|
|
977
|
+
);
|
|
978
|
+
this.displayPrompt();
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
printTable(
|
|
982
|
+
{ components: busComponents, dependencies: [] },
|
|
983
|
+
undefined,
|
|
984
|
+
undefined,
|
|
985
|
+
`Found ${busComponents.length} bus, USB, PCI, or display-link component(s) with bus-security or topology pivots.`,
|
|
986
|
+
);
|
|
987
|
+
this.displayPrompt();
|
|
988
|
+
},
|
|
989
|
+
});
|
|
990
|
+
cdxgenRepl.defineCommand("hbompower", {
|
|
991
|
+
help: "show HBOM power and battery components with detailed design-capacity and runtime telemetry",
|
|
992
|
+
action() {
|
|
993
|
+
const interactiveBom = getInteractiveHbomOrWarn(this);
|
|
994
|
+
if (!interactiveBom) {
|
|
995
|
+
return;
|
|
996
|
+
}
|
|
997
|
+
const powerComponents = filterHbomComponentsByProperties(
|
|
998
|
+
interactiveBom,
|
|
999
|
+
HBOM_POWER_PROPERTIES,
|
|
1000
|
+
["power"],
|
|
1001
|
+
);
|
|
1002
|
+
if (!powerComponents.length) {
|
|
1003
|
+
console.log(
|
|
1004
|
+
"No focused power or battery telemetry components were found on the loaded HBOM.",
|
|
1005
|
+
);
|
|
1006
|
+
this.displayPrompt();
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
1009
|
+
printTable(
|
|
1010
|
+
{ components: powerComponents, dependencies: [] },
|
|
1011
|
+
undefined,
|
|
1012
|
+
undefined,
|
|
1013
|
+
`Found ${powerComponents.length} power or battery component(s) with detailed runtime telemetry.`,
|
|
1014
|
+
);
|
|
1015
|
+
this.displayPrompt();
|
|
1016
|
+
},
|
|
1017
|
+
});
|
|
1018
|
+
cdxgenRepl.defineCommand("exit", {
|
|
1019
|
+
help: "exit",
|
|
1020
|
+
action() {
|
|
1021
|
+
this.close();
|
|
1022
|
+
},
|
|
1023
|
+
});
|
|
1024
|
+
cdxgenRepl.defineCommand("sbom", {
|
|
1025
|
+
help: "show the current sbom",
|
|
1026
|
+
action() {
|
|
1027
|
+
if (sbom) {
|
|
1028
|
+
console.log(sbom);
|
|
1029
|
+
} else {
|
|
1030
|
+
console.log(
|
|
1031
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
1032
|
+
);
|
|
1033
|
+
}
|
|
1034
|
+
this.displayPrompt();
|
|
1035
|
+
},
|
|
1036
|
+
});
|
|
1037
|
+
cdxgenRepl.defineCommand("search", {
|
|
1038
|
+
help: "search the current bom. performs case insensitive search on various attributes.",
|
|
1039
|
+
async action(searchStr) {
|
|
1040
|
+
if (sbom) {
|
|
1041
|
+
if (searchStr) {
|
|
1042
|
+
try {
|
|
1043
|
+
let fixedSearchStr = searchStr.replaceAll("/", "\\/");
|
|
1044
|
+
let dependenciesSearchStr = fixedSearchStr;
|
|
1045
|
+
if (!fixedSearchStr.includes("~>")) {
|
|
1046
|
+
dependenciesSearchStr = `dependencies[ref ~> /${fixedSearchStr}/i or dependsOn ~> /${fixedSearchStr}/i or provides ~> /${fixedSearchStr}/i]`;
|
|
1047
|
+
fixedSearchStr = `components[group ~> /${fixedSearchStr}/i or name ~> /${fixedSearchStr}/i or description ~> /${fixedSearchStr}/i or publisher ~> /${fixedSearchStr}/i or purl ~> /${fixedSearchStr}/i or tags ~> /${fixedSearchStr}/i]`;
|
|
1048
|
+
}
|
|
1049
|
+
const expression = jsonata(fixedSearchStr);
|
|
1050
|
+
const bomForSearch = searchStr.includes("~>")
|
|
1051
|
+
? sbom
|
|
1052
|
+
: getInteractiveBom();
|
|
1053
|
+
let components = await expression.evaluate(bomForSearch);
|
|
1054
|
+
const dexpression = jsonata(dependenciesSearchStr);
|
|
1055
|
+
let dependencies = await dexpression.evaluate(bomForSearch);
|
|
1056
|
+
if (components && !Array.isArray(components)) {
|
|
1057
|
+
components = [components];
|
|
1058
|
+
}
|
|
1059
|
+
if (dependencies && !Array.isArray(dependencies)) {
|
|
1060
|
+
dependencies = [dependencies];
|
|
1061
|
+
}
|
|
1062
|
+
if (!components) {
|
|
1063
|
+
console.log("No results found!");
|
|
1064
|
+
} else {
|
|
1065
|
+
printTable({ components, dependencies }, undefined, searchStr);
|
|
1066
|
+
if (dependencies?.length) {
|
|
1067
|
+
printDependencyTree(
|
|
1068
|
+
{ components, dependencies },
|
|
1069
|
+
"dependsOn",
|
|
1070
|
+
searchStr,
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
} catch (e) {
|
|
1075
|
+
console.log(e);
|
|
1076
|
+
}
|
|
1077
|
+
} else {
|
|
1078
|
+
console.log('⚠ Specify the search string. Eg: .search "search string"');
|
|
1079
|
+
}
|
|
1080
|
+
} else {
|
|
1081
|
+
console.log(
|
|
1082
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
1085
|
+
this.displayPrompt();
|
|
1086
|
+
},
|
|
1087
|
+
});
|
|
1088
|
+
cdxgenRepl.defineCommand("sort", {
|
|
1089
|
+
help: "sort the current bom based on the attribute",
|
|
1090
|
+
async action(sortStr) {
|
|
1091
|
+
if (sbom) {
|
|
1092
|
+
if (sortStr) {
|
|
1093
|
+
try {
|
|
1094
|
+
if (!sortStr.includes("^")) {
|
|
1095
|
+
sortStr = `components^(${sortStr})`;
|
|
1096
|
+
}
|
|
1097
|
+
const expression = jsonata(sortStr);
|
|
1098
|
+
const components = await expression.evaluate(sbom);
|
|
1099
|
+
if (!components) {
|
|
1100
|
+
console.log("No results found!");
|
|
1101
|
+
} else {
|
|
1102
|
+
printTable({ components, dependencies: [] });
|
|
1103
|
+
// Store the sorted list in memory
|
|
1104
|
+
if (components.length === sbom.components.length) {
|
|
1105
|
+
sbom.components = components;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
} catch (e) {
|
|
1109
|
+
console.log(e);
|
|
1110
|
+
}
|
|
1111
|
+
} else {
|
|
1112
|
+
console.log("⚠ Specify the attribute to sort by. Eg: .sort name");
|
|
1113
|
+
}
|
|
1114
|
+
} else {
|
|
1115
|
+
console.log(
|
|
1116
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
1117
|
+
);
|
|
1118
|
+
}
|
|
1119
|
+
this.displayPrompt();
|
|
1120
|
+
},
|
|
1121
|
+
});
|
|
1122
|
+
cdxgenRepl.defineCommand("query", {
|
|
1123
|
+
help: "query the current bom using jsonata expression",
|
|
1124
|
+
async action(querySpec) {
|
|
1125
|
+
if (sbom) {
|
|
1126
|
+
if (querySpec) {
|
|
1127
|
+
try {
|
|
1128
|
+
const expression = jsonata(querySpec);
|
|
1129
|
+
console.log(await expression.evaluate(sbom));
|
|
1130
|
+
} catch (e) {
|
|
1131
|
+
console.log(e);
|
|
1132
|
+
}
|
|
1133
|
+
} else {
|
|
1134
|
+
console.log(
|
|
1135
|
+
"⚠ Specify the search specification in jsonata format. Eg: .query metadata.component",
|
|
1136
|
+
);
|
|
1137
|
+
}
|
|
1138
|
+
} else {
|
|
1139
|
+
console.log(
|
|
1140
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
1141
|
+
);
|
|
1142
|
+
}
|
|
1143
|
+
this.displayPrompt();
|
|
1144
|
+
},
|
|
1145
|
+
});
|
|
1146
|
+
cdxgenRepl.defineCommand("print", {
|
|
1147
|
+
help: "print the current bom as a table",
|
|
1148
|
+
action() {
|
|
1149
|
+
const interactiveBom = getInteractiveBom();
|
|
1150
|
+
if (interactiveBom) {
|
|
1151
|
+
printTable(interactiveBom);
|
|
1152
|
+
} else {
|
|
1153
|
+
console.log(
|
|
1154
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
1155
|
+
);
|
|
1156
|
+
}
|
|
1157
|
+
this.displayPrompt();
|
|
1158
|
+
},
|
|
1159
|
+
});
|
|
1160
|
+
cdxgenRepl.defineCommand("trusted", {
|
|
1161
|
+
help: "print components with trusted publishing",
|
|
1162
|
+
action() {
|
|
1163
|
+
const interactiveBom = getInteractiveBom();
|
|
1164
|
+
if (interactiveBom?.components) {
|
|
1165
|
+
const trustedComponents = getTrustedComponents(interactiveBom.components);
|
|
1166
|
+
if (!trustedComponents.length) {
|
|
1167
|
+
console.log(
|
|
1168
|
+
"No trusted-publishing components found. Look for components enriched with cdx:npm:trustedPublishing or cdx:pypi:trustedPublishing.",
|
|
1169
|
+
);
|
|
1170
|
+
} else {
|
|
1171
|
+
printTable(
|
|
1172
|
+
{ components: trustedComponents, dependencies: [] },
|
|
1173
|
+
undefined,
|
|
1174
|
+
undefined,
|
|
1175
|
+
`Found ${trustedComponents.length} trusted component(s) backed by trusted publishing metadata.`,
|
|
1176
|
+
);
|
|
1177
|
+
}
|
|
1178
|
+
} else {
|
|
1179
|
+
console.log(
|
|
1180
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
1181
|
+
);
|
|
1182
|
+
}
|
|
1183
|
+
this.displayPrompt();
|
|
1184
|
+
},
|
|
1185
|
+
});
|
|
1186
|
+
cdxgenRepl.defineCommand("provenance", {
|
|
1187
|
+
help: "print components with direct registry provenance evidence",
|
|
1188
|
+
action() {
|
|
1189
|
+
const interactiveBom = getInteractiveBom();
|
|
1190
|
+
if (interactiveBom?.components) {
|
|
1191
|
+
const provenanceComponents = getProvenanceComponents(
|
|
1192
|
+
interactiveBom.components,
|
|
1193
|
+
);
|
|
1194
|
+
if (!provenanceComponents.length) {
|
|
1195
|
+
console.log(
|
|
1196
|
+
"No provenance-backed components found. Look for registry URLs, digests, signatures, or key IDs captured as component properties.",
|
|
1197
|
+
);
|
|
1198
|
+
} else {
|
|
1199
|
+
printTable(
|
|
1200
|
+
{ components: provenanceComponents, dependencies: [] },
|
|
1201
|
+
undefined,
|
|
1202
|
+
undefined,
|
|
1203
|
+
`Found ${provenanceComponents.length} component(s) with direct registry provenance evidence.`,
|
|
1204
|
+
);
|
|
1205
|
+
}
|
|
1206
|
+
} else {
|
|
1207
|
+
console.log(
|
|
1208
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
1209
|
+
);
|
|
1210
|
+
}
|
|
1211
|
+
this.displayPrompt();
|
|
1212
|
+
},
|
|
1213
|
+
});
|
|
1214
|
+
cdxgenRepl.defineCommand("cryptos", {
|
|
1215
|
+
help: "print the components of type cryptographic-asset as a table",
|
|
1216
|
+
action() {
|
|
1217
|
+
if (sbom) {
|
|
1218
|
+
printTable(sbom, ["cryptographic-asset"]);
|
|
1219
|
+
} else {
|
|
1220
|
+
console.log(
|
|
1221
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
1222
|
+
);
|
|
1223
|
+
}
|
|
1224
|
+
this.displayPrompt();
|
|
1225
|
+
},
|
|
1226
|
+
});
|
|
1227
|
+
cdxgenRepl.defineCommand("sourcecryptos", {
|
|
1228
|
+
help: "show source-derived cryptographic assets detected from JS AST analysis",
|
|
1229
|
+
action() {
|
|
1230
|
+
const interactiveBom = getInteractiveBom();
|
|
1231
|
+
if (!interactiveBom?.components) {
|
|
1232
|
+
console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
|
|
1233
|
+
this.displayPrompt();
|
|
1234
|
+
return;
|
|
1235
|
+
}
|
|
1236
|
+
const sourceCryptoComponents = getSourceDerivedCryptoComponents(
|
|
1237
|
+
interactiveBom.components,
|
|
1238
|
+
);
|
|
1239
|
+
if (!sourceCryptoComponents.length) {
|
|
1240
|
+
console.log(
|
|
1241
|
+
"No source-derived crypto assets found. Generate a CBOM or SBOM with source crypto analysis to use this view.",
|
|
1242
|
+
);
|
|
1243
|
+
this.displayPrompt();
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1246
|
+
printTable(
|
|
1247
|
+
{ components: sourceCryptoComponents, dependencies: [] },
|
|
1248
|
+
["cryptographic-asset"],
|
|
1249
|
+
undefined,
|
|
1250
|
+
`Found ${sourceCryptoComponents.length} source-derived cryptographic asset component(s).`,
|
|
1251
|
+
);
|
|
1252
|
+
this.displayPrompt();
|
|
1253
|
+
},
|
|
1254
|
+
});
|
|
1255
|
+
cdxgenRepl.defineCommand("unpackagedbins", {
|
|
1256
|
+
help: "show executable file components that were not matched to OS package ownership",
|
|
1257
|
+
action() {
|
|
1258
|
+
const interactiveBom = getInteractiveBom();
|
|
1259
|
+
if (!interactiveBom?.components) {
|
|
1260
|
+
console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
|
|
1261
|
+
this.displayPrompt();
|
|
1262
|
+
return;
|
|
1263
|
+
}
|
|
1264
|
+
const unpackagedExecutables = getUnpackagedExecutableComponents(
|
|
1265
|
+
interactiveBom.components,
|
|
1266
|
+
);
|
|
1267
|
+
if (!unpackagedExecutables.length) {
|
|
1268
|
+
console.log(
|
|
1269
|
+
"No unpackaged executable file components found. Import a container or rootfs BOM with native file inventory to use this view.",
|
|
1270
|
+
);
|
|
1271
|
+
this.displayPrompt();
|
|
1272
|
+
return;
|
|
1273
|
+
}
|
|
1274
|
+
printTable(
|
|
1275
|
+
{ components: unpackagedExecutables, dependencies: [] },
|
|
1276
|
+
["file"],
|
|
1277
|
+
undefined,
|
|
1278
|
+
`Found ${unpackagedExecutables.length} executable file component(s) that were not traced to OS package ownership.`,
|
|
1279
|
+
);
|
|
1280
|
+
this.displayPrompt();
|
|
1281
|
+
},
|
|
1282
|
+
});
|
|
1283
|
+
cdxgenRepl.defineCommand("unpackagedlibs", {
|
|
1284
|
+
help: "show shared library file components that were not matched to OS package ownership",
|
|
1285
|
+
action() {
|
|
1286
|
+
const interactiveBom = getInteractiveBom();
|
|
1287
|
+
if (!interactiveBom?.components) {
|
|
1288
|
+
console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
|
|
1289
|
+
this.displayPrompt();
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
const unpackagedSharedLibraries = getUnpackagedSharedLibraryComponents(
|
|
1293
|
+
interactiveBom.components,
|
|
1294
|
+
);
|
|
1295
|
+
if (!unpackagedSharedLibraries.length) {
|
|
1296
|
+
console.log(
|
|
1297
|
+
"No unpackaged shared library file components found. Import a container or rootfs BOM with native file inventory to use this view.",
|
|
1298
|
+
);
|
|
1299
|
+
this.displayPrompt();
|
|
1300
|
+
return;
|
|
1301
|
+
}
|
|
1302
|
+
printTable(
|
|
1303
|
+
{ components: unpackagedSharedLibraries, dependencies: [] },
|
|
1304
|
+
["file"],
|
|
1305
|
+
undefined,
|
|
1306
|
+
`Found ${unpackagedSharedLibraries.length} shared library file component(s) that were not traced to OS package ownership.`,
|
|
1307
|
+
);
|
|
1308
|
+
this.displayPrompt();
|
|
1309
|
+
},
|
|
1310
|
+
});
|
|
1311
|
+
cdxgenRepl.defineCommand("frameworks", {
|
|
1312
|
+
help: "print the components of type framework as a table",
|
|
1313
|
+
action() {
|
|
1314
|
+
if (sbom) {
|
|
1315
|
+
printTable(sbom, ["framework"]);
|
|
1316
|
+
} else {
|
|
1317
|
+
console.log(
|
|
1318
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
1319
|
+
);
|
|
1320
|
+
}
|
|
1321
|
+
this.displayPrompt();
|
|
1322
|
+
},
|
|
1323
|
+
});
|
|
1324
|
+
cdxgenRepl.defineCommand("tree", {
|
|
1325
|
+
help: "display the dependency tree",
|
|
1326
|
+
action() {
|
|
1327
|
+
const interactiveBom = getInteractiveBom();
|
|
1328
|
+
if (interactiveBom) {
|
|
1329
|
+
printDependencyTree(interactiveBom);
|
|
1330
|
+
} else {
|
|
1331
|
+
console.log(
|
|
1332
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
1333
|
+
);
|
|
1334
|
+
}
|
|
1335
|
+
this.displayPrompt();
|
|
1336
|
+
},
|
|
1337
|
+
});
|
|
1338
|
+
cdxgenRepl.defineCommand("provides", {
|
|
1339
|
+
help: "display the provides tree",
|
|
1340
|
+
action() {
|
|
1341
|
+
const interactiveBom = getInteractiveBom();
|
|
1342
|
+
if (interactiveBom) {
|
|
1343
|
+
printDependencyTree(interactiveBom, "provides");
|
|
1344
|
+
} else {
|
|
1345
|
+
console.log(
|
|
1346
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
1347
|
+
);
|
|
1348
|
+
}
|
|
1349
|
+
this.displayPrompt();
|
|
1350
|
+
},
|
|
1351
|
+
});
|
|
1352
|
+
cdxgenRepl.defineCommand("validate", {
|
|
1353
|
+
help: "validate the bom using jsonschema",
|
|
1354
|
+
action() {
|
|
1355
|
+
if (sbom) {
|
|
1356
|
+
validateBom(sbom).then((result) => {
|
|
1357
|
+
if (result) {
|
|
1358
|
+
console.log("BOM is valid!");
|
|
1359
|
+
}
|
|
1360
|
+
});
|
|
1361
|
+
} else {
|
|
1362
|
+
console.log(
|
|
1363
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
1364
|
+
);
|
|
1365
|
+
}
|
|
1366
|
+
this.displayPrompt();
|
|
1367
|
+
},
|
|
1368
|
+
});
|
|
1369
|
+
cdxgenRepl.defineCommand("save", {
|
|
1370
|
+
help: "save the bom to a new file",
|
|
1371
|
+
action(saveToFile) {
|
|
1372
|
+
if (sbom) {
|
|
1373
|
+
if (!saveToFile) {
|
|
1374
|
+
saveToFile = "bom.json";
|
|
1375
|
+
}
|
|
1376
|
+
if (isDryRun) {
|
|
1377
|
+
console.log(
|
|
1378
|
+
`⚠ Dry run mode blocks saving the BOM to ${saveToFile}. Disable --dry-run or CDXGEN_DRY_RUN to persist it.`,
|
|
1379
|
+
);
|
|
1380
|
+
this.displayPrompt();
|
|
1381
|
+
return;
|
|
1382
|
+
}
|
|
1383
|
+
safeWriteSync(saveToFile, JSON.stringify(sbom, null, 2));
|
|
1384
|
+
console.log(`BOM saved successfully to ${saveToFile}`);
|
|
1385
|
+
} else {
|
|
1386
|
+
console.log(
|
|
1387
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
this.displayPrompt();
|
|
1391
|
+
},
|
|
1392
|
+
});
|
|
1393
|
+
cdxgenRepl.defineCommand("update", {
|
|
1394
|
+
help: "update the bom components based on the given query",
|
|
1395
|
+
async action(updateSpec) {
|
|
1396
|
+
if (sbom) {
|
|
1397
|
+
if (!updateSpec) {
|
|
1398
|
+
return;
|
|
1399
|
+
}
|
|
1400
|
+
if (!updateSpec.startsWith("|")) {
|
|
1401
|
+
updateSpec = `|${updateSpec}`;
|
|
1402
|
+
}
|
|
1403
|
+
if (!updateSpec.endsWith("|")) {
|
|
1404
|
+
updateSpec = `${updateSpec}|`;
|
|
1405
|
+
}
|
|
1406
|
+
updateSpec = `$ ~> ${updateSpec}`;
|
|
1407
|
+
const expression = jsonata(updateSpec);
|
|
1408
|
+
const newSbom = await expression.evaluate(sbom);
|
|
1409
|
+
if (newSbom && newSbom.components.length <= sbom.components.length) {
|
|
1410
|
+
sbom = newSbom;
|
|
1411
|
+
}
|
|
1412
|
+
console.log("BOM updated successfully.");
|
|
1413
|
+
} else {
|
|
1414
|
+
console.log(
|
|
1415
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
1416
|
+
);
|
|
1417
|
+
}
|
|
1418
|
+
this.displayPrompt();
|
|
1419
|
+
},
|
|
1420
|
+
});
|
|
1421
|
+
cdxgenRepl.defineCommand("occurrences", {
|
|
1422
|
+
help: "view components with evidence.occurrences",
|
|
1423
|
+
async action() {
|
|
1424
|
+
if (sbom) {
|
|
1425
|
+
try {
|
|
1426
|
+
const expression = jsonata(
|
|
1427
|
+
"components[$count(evidence.occurrences) > 0]",
|
|
1428
|
+
);
|
|
1429
|
+
let components = await expression.evaluate(sbom);
|
|
1430
|
+
if (!components) {
|
|
1431
|
+
console.log(
|
|
1432
|
+
"No results found. Use evinse command to generate an BOM with evidence.",
|
|
1433
|
+
);
|
|
1434
|
+
} else {
|
|
1435
|
+
if (!Array.isArray(components)) {
|
|
1436
|
+
components = [components];
|
|
1437
|
+
}
|
|
1438
|
+
printOccurrences({ components });
|
|
1439
|
+
}
|
|
1440
|
+
} catch (e) {
|
|
1441
|
+
console.log(e);
|
|
1442
|
+
}
|
|
1443
|
+
} else {
|
|
1444
|
+
console.log(
|
|
1445
|
+
"⚠ No BOM is loaded. Use .import command to import an evinse BOM",
|
|
1446
|
+
);
|
|
1447
|
+
}
|
|
1448
|
+
this.displayPrompt();
|
|
1449
|
+
},
|
|
1450
|
+
});
|
|
1451
|
+
cdxgenRepl.defineCommand("callstack", {
|
|
1452
|
+
help: "view components with evidence.callstack",
|
|
1453
|
+
async action() {
|
|
1454
|
+
if (sbom) {
|
|
1455
|
+
try {
|
|
1456
|
+
const expression = jsonata(
|
|
1457
|
+
"components[$count(evidence.callstack.frames) > 0]",
|
|
1458
|
+
);
|
|
1459
|
+
let components = await expression.evaluate(sbom);
|
|
1460
|
+
if (!components) {
|
|
1461
|
+
console.log(
|
|
1462
|
+
"callstack evidence was not found. Use evinse command to generate an SBOM with evidence.",
|
|
1463
|
+
);
|
|
1464
|
+
} else {
|
|
1465
|
+
if (!Array.isArray(components)) {
|
|
1466
|
+
components = [components];
|
|
1467
|
+
}
|
|
1468
|
+
printCallStack({ components });
|
|
1469
|
+
}
|
|
1470
|
+
} catch (e) {
|
|
1471
|
+
console.log(e);
|
|
1472
|
+
}
|
|
1473
|
+
} else {
|
|
1474
|
+
console.log(
|
|
1475
|
+
"⚠ No SBOM is loaded. Use .import command to import an evinse SBOM",
|
|
1476
|
+
);
|
|
1477
|
+
}
|
|
1478
|
+
this.displayPrompt();
|
|
1479
|
+
},
|
|
1480
|
+
});
|
|
1481
|
+
cdxgenRepl.defineCommand("services", {
|
|
1482
|
+
help: "view services",
|
|
1483
|
+
async action() {
|
|
1484
|
+
if (sbom) {
|
|
1485
|
+
try {
|
|
1486
|
+
const expression = jsonata("services");
|
|
1487
|
+
let services = await expression.evaluate(sbom);
|
|
1488
|
+
if (!services) {
|
|
1489
|
+
console.log(
|
|
1490
|
+
"No services found. Use evinse command to generate a SaaSBOM with evidence.",
|
|
1491
|
+
);
|
|
1492
|
+
} else {
|
|
1493
|
+
if (!Array.isArray(services)) {
|
|
1494
|
+
services = [services];
|
|
1495
|
+
}
|
|
1496
|
+
printServices({ services });
|
|
1497
|
+
}
|
|
1498
|
+
} catch (e) {
|
|
1499
|
+
console.log(e);
|
|
1500
|
+
}
|
|
1501
|
+
} else {
|
|
1502
|
+
console.log(
|
|
1503
|
+
"⚠ No SaaSBOM is loaded. Use .import command to import a SaaSBOM",
|
|
1504
|
+
);
|
|
1505
|
+
}
|
|
1506
|
+
this.displayPrompt();
|
|
1507
|
+
},
|
|
1508
|
+
});
|
|
1509
|
+
cdxgenRepl.defineCommand("vulnerabilities", {
|
|
1510
|
+
help: "view vulnerabilities",
|
|
1511
|
+
async action() {
|
|
1512
|
+
if (sbom) {
|
|
1513
|
+
try {
|
|
1514
|
+
const expression = jsonata("vulnerabilities");
|
|
1515
|
+
let vulnerabilities = await expression.evaluate(sbom);
|
|
1516
|
+
if (!vulnerabilities) {
|
|
1517
|
+
console.log(
|
|
1518
|
+
"No vulnerabilities found. Use depscan to generate a VDR file with vulnerabilities.",
|
|
1519
|
+
);
|
|
1520
|
+
} else {
|
|
1521
|
+
if (!Array.isArray(vulnerabilities)) {
|
|
1522
|
+
vulnerabilities = [vulnerabilities];
|
|
1523
|
+
}
|
|
1524
|
+
printVulnerabilities(vulnerabilities);
|
|
1525
|
+
}
|
|
1526
|
+
} catch (e) {
|
|
1527
|
+
console.log(e);
|
|
1528
|
+
}
|
|
1529
|
+
} else {
|
|
1530
|
+
console.log("⚠ No BOM is loaded. Use .import command to import a VDR");
|
|
1531
|
+
}
|
|
1532
|
+
this.displayPrompt();
|
|
1533
|
+
},
|
|
1534
|
+
});
|
|
1535
|
+
cdxgenRepl.defineCommand("formulation", {
|
|
1536
|
+
help: "view formulation",
|
|
1537
|
+
async action() {
|
|
1538
|
+
if (sbom) {
|
|
1539
|
+
try {
|
|
1540
|
+
const expression = jsonata("formulation");
|
|
1541
|
+
let formulation = await expression.evaluate(sbom);
|
|
1542
|
+
if (!formulation) {
|
|
1543
|
+
console.log(
|
|
1544
|
+
"No formulation found. Pass the argument --include-formulation to generate SBOM with formulation details.",
|
|
1545
|
+
);
|
|
1546
|
+
} else {
|
|
1547
|
+
if (!Array.isArray(formulation)) {
|
|
1548
|
+
formulation = [formulation];
|
|
1549
|
+
}
|
|
1550
|
+
printFormulation({ formulation });
|
|
1551
|
+
}
|
|
1552
|
+
} catch (e) {
|
|
1553
|
+
console.log(e);
|
|
1554
|
+
}
|
|
1555
|
+
} else {
|
|
1556
|
+
console.log("⚠ No SBOM is loaded. Use .import command to import an SBOM");
|
|
1557
|
+
}
|
|
1558
|
+
this.displayPrompt();
|
|
1559
|
+
},
|
|
1560
|
+
});
|
|
1561
|
+
cdxgenRepl.defineCommand("cargohotspots", {
|
|
1562
|
+
help: "show Cargo package components with high-signal source, workspace, or build metadata",
|
|
1563
|
+
action() {
|
|
1564
|
+
const interactiveBom = getInteractiveBom();
|
|
1565
|
+
if (!interactiveBom?.components) {
|
|
1566
|
+
console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
|
|
1567
|
+
this.displayPrompt();
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
const cargoComponents = getCargoHotspotComponents(interactiveBom);
|
|
1571
|
+
if (!cargoComponents.length) {
|
|
1572
|
+
console.log(
|
|
1573
|
+
"No Cargo hotspot components found. Look for Cargo BOMs enriched with manifest, registry, or workspace metadata.",
|
|
1574
|
+
);
|
|
1575
|
+
this.displayPrompt();
|
|
1576
|
+
return;
|
|
1577
|
+
}
|
|
1578
|
+
printTable(
|
|
1579
|
+
{ components: cargoComponents, dependencies: [] },
|
|
1580
|
+
undefined,
|
|
1581
|
+
undefined,
|
|
1582
|
+
`Found ${cargoComponents.length} Cargo component(s) with high-signal source, workspace, or build metadata.`,
|
|
1583
|
+
);
|
|
1584
|
+
this.displayPrompt();
|
|
1585
|
+
},
|
|
1586
|
+
});
|
|
1587
|
+
cdxgenRepl.defineCommand("cargoworkflows", {
|
|
1588
|
+
help: "show Cargo-native build formulation plus Cargo-related workflow actions and run steps",
|
|
1589
|
+
action() {
|
|
1590
|
+
const interactiveBom = getInteractiveBom();
|
|
1591
|
+
if (!interactiveBom) {
|
|
1592
|
+
console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
|
|
1593
|
+
this.displayPrompt();
|
|
1594
|
+
return;
|
|
1595
|
+
}
|
|
1596
|
+
const cargoWorkflowComponents = getCargoWorkflowComponents(interactiveBom);
|
|
1597
|
+
const cargoFormulation = getCargoFormulationEntries(interactiveBom);
|
|
1598
|
+
if (!cargoWorkflowComponents.length && !cargoFormulation.length) {
|
|
1599
|
+
console.log(
|
|
1600
|
+
"No Cargo workflow or formulation pivots found. Import an SBOM generated with --include-formulation for Cargo projects.",
|
|
1601
|
+
);
|
|
1602
|
+
this.displayPrompt();
|
|
1603
|
+
return;
|
|
1604
|
+
}
|
|
1605
|
+
if (cargoWorkflowComponents.length) {
|
|
1606
|
+
printTable(
|
|
1607
|
+
{ components: cargoWorkflowComponents, dependencies: [] },
|
|
1608
|
+
undefined,
|
|
1609
|
+
undefined,
|
|
1610
|
+
`Found ${cargoWorkflowComponents.length} Cargo-related workflow component(s).`,
|
|
1611
|
+
);
|
|
1612
|
+
}
|
|
1613
|
+
if (cargoFormulation.length) {
|
|
1614
|
+
printFormulation({ formulation: cargoFormulation });
|
|
1615
|
+
}
|
|
1616
|
+
this.displayPrompt();
|
|
1617
|
+
},
|
|
1618
|
+
});
|
|
1619
|
+
cdxgenRepl.defineCommand("golemsummary", {
|
|
1620
|
+
help: "summarize Go Evinse/Golem metadata and evidence coverage",
|
|
1621
|
+
action() {
|
|
1622
|
+
const interactiveBom = getInteractiveBom();
|
|
1623
|
+
if (!interactiveBom) {
|
|
1624
|
+
console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
|
|
1625
|
+
this.displayPrompt();
|
|
1626
|
+
return;
|
|
1627
|
+
}
|
|
1628
|
+
if (!isLikelyGolemBom(interactiveBom)) {
|
|
1629
|
+
console.log(
|
|
1630
|
+
"No Golem properties found. Generate an evidence BOM with evinse -l go to use this view.",
|
|
1631
|
+
);
|
|
1632
|
+
this.displayPrompt();
|
|
1633
|
+
return;
|
|
1634
|
+
}
|
|
1635
|
+
const rootComponent = interactiveBom.metadata?.component || {};
|
|
1636
|
+
const golemComponents = getGolemComponents(interactiveBom);
|
|
1637
|
+
const hotspotComponents = getGolemHotspotComponents(interactiveBom);
|
|
1638
|
+
const coverageComponents = getGolemCoverageComponents(interactiveBom);
|
|
1639
|
+
printKeyValueTable("Go Evinse / Golem summary", [
|
|
1640
|
+
[
|
|
1641
|
+
"Tool version",
|
|
1642
|
+
getPropertyValue(rootComponent, "cdx:golem:toolVersion"),
|
|
1643
|
+
],
|
|
1644
|
+
[
|
|
1645
|
+
"Call graph mode",
|
|
1646
|
+
getPropertyValue(rootComponent, "cdx:golem:callGraphMode"),
|
|
1647
|
+
],
|
|
1648
|
+
["Packages", getPropertyValue(rootComponent, "cdx:golem:packageCount")],
|
|
1649
|
+
["Modules", getPropertyValue(rootComponent, "cdx:golem:moduleCount")],
|
|
1650
|
+
["Files", getPropertyValue(rootComponent, "cdx:golem:fileCount")],
|
|
1651
|
+
[
|
|
1652
|
+
"Generated files",
|
|
1653
|
+
getPropertyValue(rootComponent, "cdx:golem:generatedFileCount"),
|
|
1654
|
+
],
|
|
1655
|
+
["Imports", getPropertyValue(rootComponent, "cdx:golem:importCount")],
|
|
1656
|
+
["Usages", getPropertyValue(rootComponent, "cdx:golem:usageCount")],
|
|
1657
|
+
[
|
|
1658
|
+
"Runtime usages",
|
|
1659
|
+
getPropertyValue(rootComponent, "cdx:golem:runtimeUsageCount"),
|
|
1660
|
+
],
|
|
1661
|
+
[
|
|
1662
|
+
"Test usages",
|
|
1663
|
+
getPropertyValue(rootComponent, "cdx:golem:testUsageCount"),
|
|
1664
|
+
],
|
|
1665
|
+
[
|
|
1666
|
+
"Build directives",
|
|
1667
|
+
getPropertyValue(rootComponent, "cdx:golem:buildDirectiveKinds"),
|
|
1668
|
+
],
|
|
1669
|
+
[
|
|
1670
|
+
"Native artifact kinds",
|
|
1671
|
+
getPropertyValue(rootComponent, "cdx:golem:nativeArtifactKinds"),
|
|
1672
|
+
],
|
|
1673
|
+
[
|
|
1674
|
+
"Security signal categories",
|
|
1675
|
+
getPropertyValue(rootComponent, "cdx:golem:securitySignalCategories"),
|
|
1676
|
+
],
|
|
1677
|
+
[
|
|
1678
|
+
"Go directive",
|
|
1679
|
+
getPropertyValue(rootComponent, "cdx:golem:goDirectiveVersion"),
|
|
1680
|
+
],
|
|
1681
|
+
[
|
|
1682
|
+
"Toolchain directive",
|
|
1683
|
+
getPropertyValue(rootComponent, "cdx:golem:toolchainDirective"),
|
|
1684
|
+
],
|
|
1685
|
+
["Components with Golem properties", golemComponents.length],
|
|
1686
|
+
["Components with evidence coverage", coverageComponents.length],
|
|
1687
|
+
["Hotspot components", hotspotComponents.length],
|
|
1688
|
+
]);
|
|
1689
|
+
this.displayPrompt();
|
|
1690
|
+
},
|
|
1691
|
+
});
|
|
1692
|
+
cdxgenRepl.defineCommand("golemhotspots", {
|
|
1693
|
+
help: "show Go components with Golem security, replacement, private, or vendored signals",
|
|
1694
|
+
action() {
|
|
1695
|
+
const interactiveBom = getInteractiveBom();
|
|
1696
|
+
if (!interactiveBom?.components) {
|
|
1697
|
+
console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
|
|
1698
|
+
this.displayPrompt();
|
|
1699
|
+
return;
|
|
1700
|
+
}
|
|
1701
|
+
const hotspotComponents = getGolemHotspotComponents(interactiveBom);
|
|
1702
|
+
if (!hotspotComponents.length) {
|
|
1703
|
+
console.log(
|
|
1704
|
+
"No Golem hotspot components found. Look for cdx:golem security signals, local replacements, private modules, or vendored modules.",
|
|
1705
|
+
);
|
|
1706
|
+
this.displayPrompt();
|
|
1707
|
+
return;
|
|
1708
|
+
}
|
|
1709
|
+
printTable(
|
|
1710
|
+
{ components: hotspotComponents, dependencies: [] },
|
|
1711
|
+
undefined,
|
|
1712
|
+
undefined,
|
|
1713
|
+
`Found ${hotspotComponents.length} Go component(s) with Golem hotspot properties.`,
|
|
1714
|
+
);
|
|
1715
|
+
this.displayPrompt();
|
|
1716
|
+
},
|
|
1717
|
+
});
|
|
1718
|
+
cdxgenRepl.defineCommand("golemcoverage", {
|
|
1719
|
+
help: "show Go components with Golem occurrence, scope, or call-stack evidence",
|
|
1720
|
+
action() {
|
|
1721
|
+
const interactiveBom = getInteractiveBom();
|
|
1722
|
+
if (!interactiveBom?.components) {
|
|
1723
|
+
console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
|
|
1724
|
+
this.displayPrompt();
|
|
1725
|
+
return;
|
|
1726
|
+
}
|
|
1727
|
+
const coverageComponents = getGolemCoverageComponents(interactiveBom);
|
|
1728
|
+
if (!coverageComponents.length) {
|
|
1729
|
+
console.log(
|
|
1730
|
+
"No Golem coverage components found. Generate an evidence BOM with evinse -l go and import the enriched output.",
|
|
1731
|
+
);
|
|
1732
|
+
this.displayPrompt();
|
|
1733
|
+
return;
|
|
1734
|
+
}
|
|
1735
|
+
printTable(
|
|
1736
|
+
{ components: coverageComponents, dependencies: [] },
|
|
1737
|
+
undefined,
|
|
1738
|
+
undefined,
|
|
1739
|
+
`Found ${coverageComponents.length} Go component(s) with Golem evidence coverage.`,
|
|
1740
|
+
);
|
|
1741
|
+
this.displayPrompt();
|
|
1742
|
+
},
|
|
1743
|
+
});
|
|
1744
|
+
cdxgenRepl.defineCommand("auditfindings", {
|
|
1745
|
+
help: "summarize cdx-audit and bom-audit annotations from the loaded BOM",
|
|
1746
|
+
action() {
|
|
1747
|
+
if (!sbom) {
|
|
1748
|
+
console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
|
|
1749
|
+
this.displayPrompt();
|
|
1750
|
+
return;
|
|
1751
|
+
}
|
|
1752
|
+
const auditAnnotations = getAuditAnnotations();
|
|
1753
|
+
if (!auditAnnotations.length) {
|
|
1754
|
+
console.log(
|
|
1755
|
+
"No audit annotations found. Generate an SBOM with --bom-audit or import a BOM enriched by cdx-audit.",
|
|
1756
|
+
);
|
|
1757
|
+
this.displayPrompt();
|
|
1758
|
+
return;
|
|
1759
|
+
}
|
|
1760
|
+
const rows = [
|
|
1761
|
+
["Engine", "Severity", "Rule", "Target / Edge", "Next action"],
|
|
1762
|
+
];
|
|
1763
|
+
auditAnnotations.forEach((annotation) => {
|
|
1764
|
+
const props = annotation.properties;
|
|
1765
|
+
rows.push([
|
|
1766
|
+
props["cdx:audit:engine"] || "bom-audit",
|
|
1767
|
+
props["cdx:audit:severity"] || "unknown",
|
|
1768
|
+
props["cdx:audit:topFinding:ruleId"] ||
|
|
1769
|
+
props["cdx:audit:ruleId"] ||
|
|
1770
|
+
"-",
|
|
1771
|
+
props["cdx:audit:dispatch:edge"] ||
|
|
1772
|
+
props["cdx:audit:target:purl"] ||
|
|
1773
|
+
props["cdx:audit:location:file"] ||
|
|
1774
|
+
annotation.firstLine,
|
|
1775
|
+
props["cdx:audit:nextAction"] ||
|
|
1776
|
+
props["cdx:audit:upstreamGuidance"] ||
|
|
1777
|
+
props["cdx:audit:mitigation"] ||
|
|
1778
|
+
"-",
|
|
1779
|
+
]);
|
|
1780
|
+
});
|
|
1781
|
+
printAuditTable("Audit findings", rows);
|
|
1782
|
+
this.displayPrompt();
|
|
1783
|
+
},
|
|
1784
|
+
});
|
|
1785
|
+
cdxgenRepl.defineCommand("auditactions", {
|
|
1786
|
+
help: "list next actions from predictive audit annotations",
|
|
1787
|
+
action() {
|
|
1788
|
+
if (!sbom) {
|
|
1789
|
+
console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
|
|
1790
|
+
this.displayPrompt();
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
const auditAnnotations = getAuditAnnotations().filter(
|
|
1794
|
+
(annotation) => annotation.properties["cdx:audit:nextAction"],
|
|
1795
|
+
);
|
|
1796
|
+
if (!auditAnnotations.length) {
|
|
1797
|
+
console.log(
|
|
1798
|
+
"No predictive next actions found. Import a BOM annotated by cdx-audit to review remediation guidance.",
|
|
1799
|
+
);
|
|
1800
|
+
this.displayPrompt();
|
|
1801
|
+
return;
|
|
1802
|
+
}
|
|
1803
|
+
const rows = [["Severity", "Target", "Next action", "Upstream guidance"]];
|
|
1804
|
+
auditAnnotations.forEach((annotation) => {
|
|
1805
|
+
const props = annotation.properties;
|
|
1806
|
+
rows.push([
|
|
1807
|
+
props["cdx:audit:severity"] || "unknown",
|
|
1808
|
+
props["cdx:audit:dispatch:edge"] ||
|
|
1809
|
+
props["cdx:audit:target:purl"] ||
|
|
1810
|
+
annotation.firstLine,
|
|
1811
|
+
props["cdx:audit:nextAction"] || "-",
|
|
1812
|
+
props["cdx:audit:upstreamGuidance"] || "-",
|
|
1813
|
+
]);
|
|
1814
|
+
});
|
|
1815
|
+
printAuditTable("Predictive audit actions", rows);
|
|
1816
|
+
this.displayPrompt();
|
|
1817
|
+
},
|
|
1818
|
+
});
|
|
1819
|
+
cdxgenRepl.defineCommand("dispatchedges", {
|
|
1820
|
+
help: "show local sender to receiver workflow edges captured by predictive audit",
|
|
1821
|
+
action() {
|
|
1822
|
+
if (!sbom) {
|
|
1823
|
+
console.log("⚠ No BOM is loaded. Use .import command to import an SBOM");
|
|
1824
|
+
this.displayPrompt();
|
|
1825
|
+
return;
|
|
1826
|
+
}
|
|
1827
|
+
const auditAnnotations = getAuditAnnotations().filter(
|
|
1828
|
+
(annotation) => annotation.properties["cdx:audit:dispatch:edge"],
|
|
1829
|
+
);
|
|
1830
|
+
if (!auditAnnotations.length) {
|
|
1831
|
+
console.log(
|
|
1832
|
+
"No local dispatch edges found. Import a BOM annotated by cdx-audit with correlated workflow dispatch findings.",
|
|
1833
|
+
);
|
|
1834
|
+
this.displayPrompt();
|
|
1835
|
+
return;
|
|
1836
|
+
}
|
|
1837
|
+
const rows = [["Severity", "Rule", "Sender -> Receiver", "Receiver files"]];
|
|
1838
|
+
auditAnnotations.forEach((annotation) => {
|
|
1839
|
+
const props = annotation.properties;
|
|
1840
|
+
rows.push([
|
|
1841
|
+
props["cdx:audit:severity"] || "unknown",
|
|
1842
|
+
props["cdx:audit:topFinding:ruleId"] || "-",
|
|
1843
|
+
props["cdx:audit:dispatch:edge"] || annotation.firstLine,
|
|
1844
|
+
props["cdx:audit:dispatch:receiverFiles"] || "-",
|
|
1845
|
+
]);
|
|
1846
|
+
});
|
|
1847
|
+
printAuditTable("Predictive workflow dispatch edges", rows);
|
|
1848
|
+
this.displayPrompt();
|
|
1849
|
+
},
|
|
1850
|
+
});
|
|
1851
|
+
cdxgenRepl.defineCommand("osinfocategories", {
|
|
1852
|
+
help: "view the category names for the OS info from the obom",
|
|
1853
|
+
async action() {
|
|
1854
|
+
if (sbom) {
|
|
1855
|
+
try {
|
|
1856
|
+
const expression = jsonata(
|
|
1857
|
+
'$distinct(components.properties[name="cdx:osquery:category"].value)',
|
|
1858
|
+
);
|
|
1859
|
+
const catgories = await expression.evaluate(sbom);
|
|
1860
|
+
if (!catgories) {
|
|
1861
|
+
console.log(
|
|
1862
|
+
"Unable to retrieve the os info categories. Only OBOMs generated by cdxgen are supported by this tool.",
|
|
1863
|
+
);
|
|
1864
|
+
} else {
|
|
1865
|
+
console.log(catgories.join("\n"));
|
|
1866
|
+
}
|
|
1867
|
+
} catch (e) {
|
|
1868
|
+
console.log(e);
|
|
1869
|
+
}
|
|
1870
|
+
} else {
|
|
1871
|
+
console.log("⚠ No OBOM is loaded. Use .import command to import an OBOM");
|
|
1872
|
+
}
|
|
1873
|
+
this.displayPrompt();
|
|
1874
|
+
},
|
|
1875
|
+
});
|
|
1876
|
+
// OBOM-specific analyst helper tips for SOC/IR and compliance workflows.
|
|
1877
|
+
cdxgenRepl.defineCommand("obomtips", {
|
|
1878
|
+
help: "show analyst tips and useful commands for OBOM investigations",
|
|
1879
|
+
action() {
|
|
1880
|
+
console.log("OBOM analyst quick guide:");
|
|
1881
|
+
console.log("1. .osinfocategories");
|
|
1882
|
+
console.log(
|
|
1883
|
+
"2. Run an OS-query category command from .help (examples below)",
|
|
1884
|
+
);
|
|
1885
|
+
console.log(" .processes");
|
|
1886
|
+
console.log(" .services_snapshot");
|
|
1887
|
+
console.log(" .scheduled_tasks");
|
|
1888
|
+
console.log(" .startup_items");
|
|
1889
|
+
console.log("3. .inspect <name>");
|
|
1890
|
+
console.log("4. .services / .print / .summary for quick pivots");
|
|
1891
|
+
console.log(
|
|
1892
|
+
"Tip: Generate with --bom-audit --bom-audit-categories obom-runtime for prioritized findings.",
|
|
1893
|
+
);
|
|
1894
|
+
this.displayPrompt();
|
|
1895
|
+
},
|
|
1896
|
+
});
|
|
1897
|
+
cdxgenRepl.defineCommand("hbomtips", {
|
|
1898
|
+
help: "show analyst tips and useful commands for HBOM investigations",
|
|
1899
|
+
action() {
|
|
1900
|
+
console.log("HBOM analyst quick guide:");
|
|
1901
|
+
console.log("1. .hbomsummary");
|
|
1902
|
+
console.log("2. .hbomclasses");
|
|
1903
|
+
console.log("3. .hbomevidence");
|
|
1904
|
+
console.log("4. .hbomdiagnostics");
|
|
1905
|
+
console.log("5. .hbomfirmware / .hbombuses / .hbompower");
|
|
1906
|
+
console.log(
|
|
1907
|
+
"6. .auditfindings to review hbom-security, hbom-performance, and hbom-compliance findings",
|
|
1908
|
+
);
|
|
1909
|
+
console.log("7. .search <hardwareClass or device name>");
|
|
1910
|
+
console.log(
|
|
1911
|
+
'Tip: .query components[properties[name="cdx:hbom:hardwareClass" and value="storage"]] filters directly by hardware class.',
|
|
1912
|
+
);
|
|
1913
|
+
this.displayPrompt();
|
|
1914
|
+
},
|
|
1915
|
+
});
|
|
1916
|
+
cdxgenRepl.defineCommand("golemtips", {
|
|
1917
|
+
help: "show analyst tips and useful commands for Go Evinse/Golem investigations",
|
|
1918
|
+
action() {
|
|
1919
|
+
console.log("Go Evinse/Golem analyst quick guide:");
|
|
1920
|
+
console.log("1. .golemsummary");
|
|
1921
|
+
console.log("2. .golemhotspots");
|
|
1922
|
+
console.log("3. .golemcoverage");
|
|
1923
|
+
console.log("4. .occurrences / .callstack for evidence details");
|
|
1924
|
+
console.log("5. .auditfindings after running --bom-audit or cdx-audit");
|
|
1925
|
+
console.log("6. .inspect <component name or purl fragment>");
|
|
1926
|
+
console.log(
|
|
1927
|
+
"Tip: use --bom-audit-categories golem for focused Golem findings.",
|
|
1928
|
+
);
|
|
1929
|
+
this.displayPrompt();
|
|
1930
|
+
},
|
|
1931
|
+
});
|
|
1932
|
+
cdxgenRepl.defineCommand("licenses", {
|
|
1933
|
+
help: "visualize license distribution",
|
|
1934
|
+
async action() {
|
|
1935
|
+
if (!sbom?.components) {
|
|
1936
|
+
console.log("⚠ No SBOM loaded.");
|
|
1937
|
+
this.displayPrompt();
|
|
1938
|
+
return;
|
|
1939
|
+
}
|
|
1940
|
+
const licenseCounts = {};
|
|
1941
|
+
let unknown = 0;
|
|
1942
|
+
sbom.components.forEach((c) => {
|
|
1943
|
+
if (c.licenses && c.licenses.length > 0) {
|
|
1944
|
+
c.licenses.forEach((l) => {
|
|
1945
|
+
const name = l.license?.id || l.license?.name || "Unknown";
|
|
1946
|
+
licenseCounts[name] = (licenseCounts[name] || 0) + 1;
|
|
1947
|
+
});
|
|
1948
|
+
} else {
|
|
1949
|
+
unknown++;
|
|
1950
|
+
}
|
|
1951
|
+
});
|
|
1952
|
+
if (unknown > 0) licenseCounts["None/Unknown"] = unknown;
|
|
1953
|
+
const sorted = Object.entries(licenseCounts).sort((a, b) => b[1] - a[1]);
|
|
1954
|
+
const maxVal = sorted[0][1];
|
|
1955
|
+
const maxBarLength = 40;
|
|
1956
|
+
console.log("\n📊 License Distribution:\n");
|
|
1957
|
+
sorted.forEach(([license, count]) => {
|
|
1958
|
+
const barLen = Math.ceil((count / maxVal) * maxBarLength);
|
|
1959
|
+
const bar = "█".repeat(barLen);
|
|
1960
|
+
let icon = "✅";
|
|
1961
|
+
if (["GPL", "AGPL"].some((r) => license.includes(r))) icon = "⚖️ ";
|
|
1962
|
+
if (license === "None/Unknown") icon = "❓";
|
|
1963
|
+
console.log(`${icon} ${license.padEnd(60)} | ${bar} (${count})`);
|
|
1964
|
+
});
|
|
1965
|
+
console.log("");
|
|
1966
|
+
this.displayPrompt();
|
|
1967
|
+
},
|
|
1968
|
+
});
|
|
1969
|
+
cdxgenRepl.defineCommand("inspect", {
|
|
1970
|
+
help: "view full JSON details of a component: .inspect <name_search_string>",
|
|
1971
|
+
async action(nameStr) {
|
|
1972
|
+
if (!nameStr) {
|
|
1973
|
+
console.log(
|
|
1974
|
+
"⚠ Specify a component name or purl fragment. Eg: .inspect lodash",
|
|
1975
|
+
);
|
|
1976
|
+
this.displayPrompt();
|
|
1977
|
+
return;
|
|
1978
|
+
}
|
|
1979
|
+
if (sbom?.components) {
|
|
1980
|
+
const found = sbom.components.find(
|
|
1981
|
+
(c) =>
|
|
1982
|
+
c.name.toLowerCase().includes(nameStr.toLowerCase()) ||
|
|
1983
|
+
c.purl?.includes(nameStr),
|
|
1984
|
+
);
|
|
1985
|
+
if (found) {
|
|
1986
|
+
console.log(JSON.stringify(found, null, 2));
|
|
1987
|
+
} else {
|
|
1988
|
+
console.log("❌ Component not found.");
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
this.displayPrompt();
|
|
1992
|
+
},
|
|
1993
|
+
});
|
|
1994
|
+
cdxgenRepl.defineCommand("tagcloud", {
|
|
1995
|
+
help: "generate a text/tag cloud based on component descriptions and tags",
|
|
1996
|
+
action() {
|
|
1997
|
+
if (!sbom?.components) {
|
|
1998
|
+
console.log("⚠ No SBOM loaded.");
|
|
1999
|
+
this.displayPrompt();
|
|
2000
|
+
return;
|
|
2001
|
+
}
|
|
2002
|
+
const stopWords = new Set([
|
|
2003
|
+
"the",
|
|
2004
|
+
"and",
|
|
2005
|
+
"for",
|
|
2006
|
+
"with",
|
|
2007
|
+
"that",
|
|
2008
|
+
"this",
|
|
2009
|
+
"from",
|
|
2010
|
+
"are",
|
|
2011
|
+
"can",
|
|
2012
|
+
"use",
|
|
2013
|
+
"library",
|
|
2014
|
+
"framework",
|
|
2015
|
+
"package",
|
|
2016
|
+
"component",
|
|
2017
|
+
"module",
|
|
2018
|
+
"application",
|
|
2019
|
+
"software",
|
|
2020
|
+
"tool",
|
|
2021
|
+
"version",
|
|
2022
|
+
"implementation",
|
|
2023
|
+
"support",
|
|
2024
|
+
"based",
|
|
2025
|
+
"provided",
|
|
2026
|
+
"provides",
|
|
2027
|
+
"using",
|
|
2028
|
+
"api",
|
|
2029
|
+
"interface",
|
|
2030
|
+
"data",
|
|
2031
|
+
"system",
|
|
2032
|
+
"http",
|
|
2033
|
+
"https",
|
|
2034
|
+
"com",
|
|
2035
|
+
"org",
|
|
2036
|
+
"net",
|
|
2037
|
+
"git",
|
|
2038
|
+
"source",
|
|
2039
|
+
"code",
|
|
2040
|
+
"file",
|
|
2041
|
+
"project",
|
|
2042
|
+
"open",
|
|
2043
|
+
"free",
|
|
2044
|
+
"web",
|
|
2045
|
+
"runtime",
|
|
2046
|
+
"client",
|
|
2047
|
+
"server",
|
|
2048
|
+
"utils",
|
|
2049
|
+
]);
|
|
2050
|
+
const wordCounts = new Map();
|
|
2051
|
+
const addWord = (w) => {
|
|
2052
|
+
if (!w) return;
|
|
2053
|
+
const clean = w.toLowerCase().replace(/[^a-z0-9-]/g, "");
|
|
2054
|
+
if (clean.length > 2 && !stopWords.has(clean) && Number.isNaN(clean)) {
|
|
2055
|
+
wordCounts.set(clean, (wordCounts.get(clean) || 0) + 1);
|
|
2056
|
+
}
|
|
2057
|
+
};
|
|
2058
|
+
sbom.components.forEach((c) => {
|
|
2059
|
+
if (c.tags) {
|
|
2060
|
+
c.tags.forEach((t) => {
|
|
2061
|
+
addWord(t);
|
|
2062
|
+
addWord(t);
|
|
2063
|
+
});
|
|
2064
|
+
}
|
|
2065
|
+
if (c.description) {
|
|
2066
|
+
c.description.split(/\s+/).forEach(addWord);
|
|
2067
|
+
}
|
|
2068
|
+
if (c.group) {
|
|
2069
|
+
addWord(c.group);
|
|
2070
|
+
}
|
|
2071
|
+
});
|
|
2072
|
+
if (wordCounts.size === 0) {
|
|
2073
|
+
console.log("⚠ Not enough text data found in Description or Tags.");
|
|
2074
|
+
this.displayPrompt();
|
|
2075
|
+
return;
|
|
2076
|
+
}
|
|
2077
|
+
let sortedWords = Array.from(wordCounts.entries()).sort(
|
|
2078
|
+
(a, b) => b[1] - a[1],
|
|
2079
|
+
);
|
|
2080
|
+
sortedWords = sortedWords.slice(0, 100);
|
|
2081
|
+
const maxCount = sortedWords[0][1];
|
|
2082
|
+
const minCount = sortedWords[sortedWords.length - 1][1];
|
|
2083
|
+
const styles = {
|
|
2084
|
+
tier1: (str) => `\x1b[1;35m${str.toUpperCase()}\x1b[0m`,
|
|
2085
|
+
tier2: (str) => `\x1b[1;36m${str}\x1b[0m`,
|
|
2086
|
+
tier3: (str) => `\x1b[32m${str}\x1b[0m`,
|
|
2087
|
+
tier4: (str) => `\x1b[2m${str}\x1b[0m`,
|
|
2088
|
+
};
|
|
2089
|
+
const cloudNodes = sortedWords.map(([word, count]) => {
|
|
2090
|
+
const score = (count - minCount) / (maxCount - minCount || 1);
|
|
2091
|
+
let styledWord = "";
|
|
2092
|
+
if (score > 0.7) styledWord = styles.tier1(word);
|
|
2093
|
+
else if (score > 0.4) styledWord = styles.tier2(word);
|
|
2094
|
+
else if (score > 0.1) styledWord = styles.tier3(word);
|
|
2095
|
+
else styledWord = styles.tier4(word);
|
|
2096
|
+
return styledWord;
|
|
2097
|
+
});
|
|
2098
|
+
for (let i = cloudNodes.length - 1; i > 0; i--) {
|
|
2099
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
2100
|
+
[cloudNodes[i], cloudNodes[j]] = [cloudNodes[j], cloudNodes[i]];
|
|
2101
|
+
}
|
|
2102
|
+
console.log("\n☁️ Word Cloud\n");
|
|
2103
|
+
const terminalWidth = process.stdout.columns || 80;
|
|
2104
|
+
let currentLine = "";
|
|
2105
|
+
cloudNodes.forEach((node) => {
|
|
2106
|
+
const visualLength = node.replace(/[[0-9;]*m/g, "").length + 1;
|
|
2107
|
+
if (currentLine.length + visualLength > terminalWidth) {
|
|
2108
|
+
console.log(currentLine);
|
|
2109
|
+
currentLine = "";
|
|
2110
|
+
}
|
|
2111
|
+
currentLine += `${node} `;
|
|
2112
|
+
});
|
|
2113
|
+
console.log(currentLine);
|
|
2114
|
+
console.log("\n");
|
|
2115
|
+
this.displayPrompt();
|
|
2116
|
+
},
|
|
2117
|
+
});
|
|
2118
|
+
// Let's dynamically define more commands from the queries
|
|
2119
|
+
[
|
|
2120
|
+
"apt_sources",
|
|
2121
|
+
"behavioral_reverse_shell",
|
|
2122
|
+
"certificates",
|
|
2123
|
+
"chrome_extensions",
|
|
2124
|
+
"crontab_snapshot",
|
|
2125
|
+
"deb_packages",
|
|
2126
|
+
"docker_container_ports",
|
|
2127
|
+
"docker_containers",
|
|
2128
|
+
"docker_networks",
|
|
2129
|
+
"docker_volumes",
|
|
2130
|
+
"etc_hosts",
|
|
2131
|
+
"firefox_addons",
|
|
2132
|
+
"gatekeeper",
|
|
2133
|
+
"vscode_extensions",
|
|
2134
|
+
"homebrew_packages",
|
|
2135
|
+
"installed_applications",
|
|
2136
|
+
"interface_addresses",
|
|
2137
|
+
"kernel_info",
|
|
2138
|
+
"kernel_integrity",
|
|
2139
|
+
"kernel_modules",
|
|
2140
|
+
"ld_preload",
|
|
2141
|
+
"elevated_processes",
|
|
2142
|
+
"listening_ports",
|
|
2143
|
+
"os_version",
|
|
2144
|
+
"pipes",
|
|
2145
|
+
"pipes_snapshot",
|
|
2146
|
+
"portage_packages",
|
|
2147
|
+
"process_events",
|
|
2148
|
+
"processes",
|
|
2149
|
+
"secureboot_certificates",
|
|
2150
|
+
"privilege_transitions",
|
|
2151
|
+
"privileged_listening_ports",
|
|
2152
|
+
"npm_packages",
|
|
2153
|
+
"python_packages",
|
|
2154
|
+
"rpm_packages",
|
|
2155
|
+
"scheduled_tasks",
|
|
2156
|
+
"services_snapshot",
|
|
2157
|
+
"startup_items",
|
|
2158
|
+
"sudo_executions",
|
|
2159
|
+
"system_info_snapshot",
|
|
2160
|
+
"windows_drivers",
|
|
2161
|
+
"windows_patches",
|
|
2162
|
+
"windows_programs",
|
|
2163
|
+
"windows_shared_resources",
|
|
2164
|
+
"yum_sources",
|
|
2165
|
+
"appcompat_shims",
|
|
2166
|
+
"browser_plugins",
|
|
2167
|
+
"certificates",
|
|
2168
|
+
"chocolatey_packages",
|
|
2169
|
+
"chrome_extensions",
|
|
2170
|
+
"etc_hosts",
|
|
2171
|
+
"firefox_addons",
|
|
2172
|
+
"ie_extensions",
|
|
2173
|
+
"kernel_info",
|
|
2174
|
+
"npm_packages",
|
|
2175
|
+
"opera_extensions",
|
|
2176
|
+
"pipes_snapshot",
|
|
2177
|
+
"process_open_handles_snapshot",
|
|
2178
|
+
"process_open_sockets",
|
|
2179
|
+
"safari_extensions",
|
|
2180
|
+
"scheduled_tasks",
|
|
2181
|
+
"services_snapshot",
|
|
2182
|
+
"startup_items",
|
|
2183
|
+
"routes",
|
|
2184
|
+
"system_info_snapshot",
|
|
2185
|
+
"win_version",
|
|
2186
|
+
"windows_firewall_rules",
|
|
2187
|
+
"windows_optional_features",
|
|
2188
|
+
"windows_programs",
|
|
2189
|
+
"windows_shared_resources",
|
|
2190
|
+
"windows_update_history",
|
|
2191
|
+
"wmi_cli_event_consumers",
|
|
2192
|
+
"wmi_cli_event_consumers_snapshot",
|
|
2193
|
+
"wmi_event_filters",
|
|
2194
|
+
"wmi_filter_consumer_binding",
|
|
2195
|
+
].forEach((c) => {
|
|
2196
|
+
cdxgenRepl.defineCommand(c, {
|
|
2197
|
+
help: `query the ${c} category from the OS info`,
|
|
2198
|
+
async action() {
|
|
2199
|
+
if (sbom) {
|
|
2200
|
+
try {
|
|
2201
|
+
const expression = jsonata(
|
|
2202
|
+
`components[properties[name="cdx:osquery:category" and value="${c}"]]`,
|
|
2203
|
+
);
|
|
2204
|
+
let components = await expression.evaluate(sbom);
|
|
2205
|
+
if (!components) {
|
|
2206
|
+
console.log("No results found.");
|
|
2207
|
+
} else {
|
|
2208
|
+
if (!Array.isArray(components)) {
|
|
2209
|
+
components = [components];
|
|
2210
|
+
}
|
|
2211
|
+
printOSTable({ components });
|
|
2212
|
+
}
|
|
2213
|
+
} catch (e) {
|
|
2214
|
+
console.log(e);
|
|
2215
|
+
}
|
|
2216
|
+
} else {
|
|
2217
|
+
console.log(
|
|
2218
|
+
"⚠ No OBOM is loaded. Use .import command to import an OBOM",
|
|
2219
|
+
);
|
|
2220
|
+
}
|
|
2221
|
+
this.displayPrompt();
|
|
2222
|
+
},
|
|
2223
|
+
});
|
|
2224
|
+
});
|