@cdxgen/cdxgen 0.0.1 → 13.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (722) hide show
  1. package/README.md +921 -87
  2. package/bin/audit.js +239 -0
  3. package/bin/cdxgen.js +2324 -0
  4. package/bin/convert.js +213 -0
  5. package/bin/evinse.js +353 -0
  6. package/bin/hbom.js +495 -0
  7. package/bin/repl.js +2224 -0
  8. package/bin/sign.js +195 -0
  9. package/bin/tracebom.js +295 -0
  10. package/bin/validate.js +268 -0
  11. package/bin/verify.js +189 -0
  12. package/data/README.md +307 -0
  13. package/data/bom-1.4.schema.json +1605 -0
  14. package/data/bom-1.5.schema.json +3660 -0
  15. package/data/bom-1.6.schema.json +5511 -0
  16. package/data/bom-1.7.schema.json +6700 -0
  17. package/data/cbomosdb-queries.json +68 -0
  18. package/data/component-tags.json +339 -0
  19. package/data/container-knowledge-index.json +125 -0
  20. package/data/cosdb-queries.json +17 -0
  21. package/data/crypto-oid.json +1998 -0
  22. package/data/cryptography-defs.json +3793 -0
  23. package/data/cryptography-defs.schema.json +576 -0
  24. package/data/cyclonedx-2.0-bundled.schema.json +7182 -0
  25. package/data/frameworks-list.json +219 -0
  26. package/data/glibc-stdlib.json +117 -0
  27. package/data/gtfobins-index.json +6296 -0
  28. package/data/helpers/init.gradle +71 -0
  29. package/data/jsf-0.82.schema.json +211 -0
  30. package/data/known-licenses.json +82 -0
  31. package/data/lic-mapping.json +338 -0
  32. package/data/license-aliases.json +6624 -0
  33. package/data/license-db.json +39059 -0
  34. package/data/license-deprecations.json +302 -0
  35. package/data/lolbas-index.json +150 -0
  36. package/data/predictive-audit-allowlist.json +11 -0
  37. package/data/pypi-pkg-aliases.json +1199 -0
  38. package/data/python-stdlib.json +308 -0
  39. package/data/queries-darwin.json +193 -0
  40. package/data/queries-win.json +257 -0
  41. package/data/queries.json +268 -0
  42. package/data/ruby-known-modules.json +281 -0
  43. package/data/rules/ai-agent-governance.yaml +323 -0
  44. package/data/rules/ai-bom.yaml +268 -0
  45. package/data/rules/ai-oversight.yaml +186 -0
  46. package/data/rules/ai-provenance.yaml +92 -0
  47. package/data/rules/asar-archives.yaml +150 -0
  48. package/data/rules/cbom-security.yaml +165 -0
  49. package/data/rules/chrome-extensions.yaml +248 -0
  50. package/data/rules/ci-permissions.yaml +802 -0
  51. package/data/rules/container-risk.yaml +353 -0
  52. package/data/rules/dependency-sources.yaml +236 -0
  53. package/data/rules/golem-go.yaml +229 -0
  54. package/data/rules/hbom-compliance.yaml +325 -0
  55. package/data/rules/hbom-performance.yaml +307 -0
  56. package/data/rules/hbom-security.yaml +248 -0
  57. package/data/rules/host-topology.yaml +165 -0
  58. package/data/rules/mcp-servers.yaml +388 -0
  59. package/data/rules/obom-runtime.yaml +1776 -0
  60. package/data/rules/package-integrity.yaml +364 -0
  61. package/data/rules/rootfs-hardening.yaml +179 -0
  62. package/data/rules/vscode-extensions.yaml +237 -0
  63. package/data/spdx-export.schema.json +6794 -0
  64. package/data/spdx-license-list.json +7449 -0
  65. package/data/spdx-licenses.json +759 -0
  66. package/data/spdx.schema.json +819 -0
  67. package/data/templates/README.md +3 -0
  68. package/data/templates/asvs-4.0.3.cdx.json +2943 -0
  69. package/data/templates/asvs-5.0.cdx.json +3046 -0
  70. package/data/templates/bsimm-v13.cdx.json +1008 -0
  71. package/data/templates/masvs-2.0.0.cdx.json +225 -0
  72. package/data/templates/nist-ssdf-1.1.cdx.json +828 -0
  73. package/data/templates/pcissc-secure-slc-1.1.cdx.json +1027 -0
  74. package/data/templates/scvs-1.0.0.cdx.json +813 -0
  75. package/data/templates/ssaf-DRAFT-2023-11.cdx.json +127 -0
  76. package/data/vendor-alias.json +41967 -0
  77. package/data/wrapdb-releases.json +4227 -0
  78. package/index.cjs +15 -0
  79. package/lib/audit/index.js +2800 -0
  80. package/lib/audit/progress.js +114 -0
  81. package/lib/audit/reporters.js +937 -0
  82. package/lib/audit/scoring.js +560 -0
  83. package/lib/audit/targets.js +798 -0
  84. package/lib/cli/bomAssembly.js +1833 -0
  85. package/lib/cli/cliOptions.js +513 -0
  86. package/lib/cli/index.js +2759 -0
  87. package/lib/cli/jsBom.js +2087 -0
  88. package/lib/cli/jvmBom.js +1858 -0
  89. package/lib/cli/managedBom.js +2083 -0
  90. package/lib/cli/nativeBom.js +2125 -0
  91. package/lib/core/activity.js +1087 -0
  92. package/lib/core/env.js +719 -0
  93. package/lib/core/fs.js +1058 -0
  94. package/lib/core/httpClient.js +730 -0
  95. package/lib/core/logger.js +142 -0
  96. package/lib/core/parallel.js +323 -0
  97. package/lib/core/paths.js +70 -0
  98. package/lib/core/projectConfig.js +122 -0
  99. package/lib/core/propertySanitizer.js +174 -0
  100. package/lib/core/spdx.js +5 -0
  101. package/lib/core/state.js +59 -0
  102. package/lib/core/text.js +207 -0
  103. package/lib/core/ui.js +876 -0
  104. package/lib/core/urls.js +84 -0
  105. package/lib/ecosystems/asarutils.js +1636 -0
  106. package/lib/ecosystems/bunutils.js +402 -0
  107. package/lib/ecosystems/caxa.js +77 -0
  108. package/lib/ecosystems/chromextutils.js +1174 -0
  109. package/lib/ecosystems/cmakeResolver.js +587 -0
  110. package/lib/ecosystems/cppEvidence.js +305 -0
  111. package/lib/ecosystems/denoutils.js +1094 -0
  112. package/lib/ecosystems/dotnetutils.js +132 -0
  113. package/lib/ecosystems/ecosystems.js +2772 -0
  114. package/lib/ecosystems/golem.js +1807 -0
  115. package/lib/ecosystems/gradleutils.js +1048 -0
  116. package/lib/ecosystems/jsEvidence.js +317 -0
  117. package/lib/ecosystems/npmutils.js +586 -0
  118. package/lib/ecosystems/parsers-bazel.js +875 -0
  119. package/lib/ecosystems/parsers-dotnet.js +1430 -0
  120. package/lib/ecosystems/parsers-gleam.js +302 -0
  121. package/lib/ecosystems/parsers-go.js +818 -0
  122. package/lib/ecosystems/parsers-js.js +4222 -0
  123. package/lib/ecosystems/parsers-jvm.js +948 -0
  124. package/lib/ecosystems/parsers-misc.js +3191 -0
  125. package/lib/ecosystems/parsers-python.js +2070 -0
  126. package/lib/ecosystems/parsers-rust.js +1294 -0
  127. package/lib/ecosystems/parsers-zig.js +861 -0
  128. package/lib/ecosystems/pep770.js +341 -0
  129. package/lib/ecosystems/pylockutils.js +427 -0
  130. package/lib/ecosystems/pythonutils.js +1281 -0
  131. package/lib/ecosystems/registryProvenance.js +1003 -0
  132. package/lib/ecosystems/remote/huggingface.js +1343 -0
  133. package/lib/ecosystems/rubyutils.js +1629 -0
  134. package/lib/ecosystems/rusi.js +820 -0
  135. package/lib/ecosystems/sbtutils.js +972 -0
  136. package/lib/ecosystems/tea.js +607 -0
  137. package/lib/ecosystems/utils.js +575 -0
  138. package/lib/ecosystems/zigResolver.js +410 -0
  139. package/lib/evinser/db.js +145 -0
  140. package/lib/evinser/evinser.js +2362 -0
  141. package/lib/evinser/scalasem.js +65 -0
  142. package/lib/evinser/swiftsem.js +767 -0
  143. package/lib/helpers/annotationFormatter.js +84 -0
  144. package/lib/helpers/bomSigner.js +312 -0
  145. package/lib/helpers/exportUtils.js +160 -0
  146. package/lib/helpers/remote/dependency-track.js +117 -0
  147. package/lib/helpers/versutils.js +202 -0
  148. package/lib/helpers/vsixutils.js +1069 -0
  149. package/lib/inventory/agentFormulationParser.js +322 -0
  150. package/lib/inventory/aiCollector.js +2140 -0
  151. package/lib/inventory/aiInventory.js +414 -0
  152. package/lib/inventory/aiModelVariants.js +121 -0
  153. package/lib/inventory/aiOversightCollector.js +661 -0
  154. package/lib/inventory/aiProvenanceCollector.js +822 -0
  155. package/lib/inventory/analyzer.js +6089 -0
  156. package/lib/inventory/analyzerScope.js +807 -0
  157. package/lib/inventory/astWorker.js +20 -0
  158. package/lib/inventory/atomUtils.js +1092 -0
  159. package/lib/inventory/auditCategories.js +192 -0
  160. package/lib/inventory/bomUtils.js +369 -0
  161. package/lib/inventory/cacheCommands.js +182 -0
  162. package/lib/inventory/cacheDir.js +104 -0
  163. package/lib/inventory/cbomutils.js +590 -0
  164. package/lib/inventory/cdxrs.js +434 -0
  165. package/lib/inventory/ciParsers/azurePipelines.js +295 -0
  166. package/lib/inventory/ciParsers/circleCi.js +286 -0
  167. package/lib/inventory/ciParsers/common.js +24 -0
  168. package/lib/inventory/ciParsers/githubActions.js +2434 -0
  169. package/lib/inventory/ciParsers/gitlabCi.js +213 -0
  170. package/lib/inventory/ciParsers/jenkins.js +180 -0
  171. package/lib/inventory/citations.js +234 -0
  172. package/lib/inventory/communityAiConfigParser.js +756 -0
  173. package/lib/inventory/containerRisk.js +204 -0
  174. package/lib/inventory/cryptoAlgorithmFamily.js +258 -0
  175. package/lib/inventory/deps.js +807 -0
  176. package/lib/inventory/depsUtils.js +588 -0
  177. package/lib/inventory/display.js +2128 -0
  178. package/lib/inventory/dosai.js +601 -0
  179. package/lib/inventory/dosaiParsers.js +154 -0
  180. package/lib/inventory/dynamic.js +145 -0
  181. package/lib/inventory/envcontext.js +1789 -0
  182. package/lib/inventory/evidenceUtils.js +774 -0
  183. package/lib/inventory/fetchBatch.js +779 -0
  184. package/lib/inventory/fetchRate.js +255 -0
  185. package/lib/inventory/forgeEnricher.js +300 -0
  186. package/lib/inventory/formulationParsers.js +422 -0
  187. package/lib/inventory/gtfobins.js +339 -0
  188. package/lib/inventory/hbom.js +719 -0
  189. package/lib/inventory/hbomAnalysis.js +310 -0
  190. package/lib/inventory/hbomLoader.js +35 -0
  191. package/lib/inventory/hostTopology.js +835 -0
  192. package/lib/inventory/inventoryStats.js +100 -0
  193. package/lib/inventory/jsonLike.js +121 -0
  194. package/lib/inventory/licenseEnhancer.js +918 -0
  195. package/lib/inventory/lolbas.js +285 -0
  196. package/lib/inventory/mcp.js +253 -0
  197. package/lib/inventory/mcpConfigParser.js +683 -0
  198. package/lib/inventory/mcpDiscovery.js +112 -0
  199. package/lib/inventory/mcpPinning.js +209 -0
  200. package/lib/inventory/osPackageResolver.js +493 -0
  201. package/lib/inventory/osinfo.js +277 -0
  202. package/lib/inventory/osqueryTransform.js +274 -0
  203. package/lib/inventory/plugins.js +466 -0
  204. package/lib/inventory/protobom.js +231 -0
  205. package/lib/inventory/protobomLoader.js +43 -0
  206. package/lib/inventory/provenanceUtils.js +224 -0
  207. package/lib/inventory/purl.js +749 -0
  208. package/lib/inventory/rustFormulationParser.js +339 -0
  209. package/lib/inventory/sbomDocument.js +340 -0
  210. package/lib/inventory/source.js +1488 -0
  211. package/lib/inventory/spdx.js +361 -0
  212. package/lib/inventory/spdxExpression.js +512 -0
  213. package/lib/inventory/spdxUtils.js +107 -0
  214. package/lib/inventory/table.js +263 -0
  215. package/lib/inventory/traceRunner.js +439 -0
  216. package/lib/inventory/unicodeScan.js +147 -0
  217. package/lib/managers/binary.js +3307 -0
  218. package/lib/managers/containerutils.js +125 -0
  219. package/lib/managers/docker.js +2145 -0
  220. package/lib/managers/dockerConnection.js +162 -0
  221. package/lib/managers/oci.js +704 -0
  222. package/lib/managers/piptree.js +267 -0
  223. package/lib/parsers/cmakeCache.js +199 -0
  224. package/lib/parsers/gguf.js +492 -0
  225. package/lib/parsers/gitAiNotes.js +233 -0
  226. package/lib/parsers/gitmodules.js +239 -0
  227. package/lib/parsers/htmlExtract.js +610 -0
  228. package/lib/parsers/huggingfaceManifest.js +551 -0
  229. package/lib/parsers/huggingfaceUtils.js +506 -0
  230. package/lib/parsers/iri.js +618 -0
  231. package/lib/parsers/npmrc.js +99 -0
  232. package/lib/parsers/ollama.js +101 -0
  233. package/lib/parsers/xml.js +841 -0
  234. package/lib/server/openapi.yaml +433 -0
  235. package/lib/server/server.js +616 -0
  236. package/lib/stages/postgen/annotator.js +977 -0
  237. package/lib/stages/postgen/auditBom.js +468 -0
  238. package/lib/stages/postgen/postgen.js +1239 -0
  239. package/lib/stages/postgen/ruleEngine.js +731 -0
  240. package/lib/stages/postgen/sortBom.js +195 -0
  241. package/lib/stages/postgen/spdxConverter.js +796 -0
  242. package/lib/stages/postgen/specVersionCompat.js +703 -0
  243. package/lib/stages/pregen/envAudit.js +388 -0
  244. package/lib/stages/pregen/pregen.js +637 -0
  245. package/lib/third-party/README.md +9 -0
  246. package/lib/third-party/arborist/CHANGELOG.md +1109 -0
  247. package/lib/third-party/arborist/LICENSE.md +20 -0
  248. package/lib/third-party/arborist/README.md +315 -0
  249. package/lib/third-party/arborist/lib/arborist/index.js +258 -0
  250. package/lib/third-party/arborist/lib/arborist/load-actual.js +605 -0
  251. package/lib/third-party/arborist/lib/arborist/load-virtual.js +300 -0
  252. package/lib/third-party/arborist/lib/bin-links.js +120 -0
  253. package/lib/third-party/arborist/lib/calc-dep-flags.js +130 -0
  254. package/lib/third-party/arborist/lib/case-insensitive-map.js +51 -0
  255. package/lib/third-party/arborist/lib/consistent-resolve.js +42 -0
  256. package/lib/third-party/arborist/lib/debug.js +50 -0
  257. package/lib/third-party/arborist/lib/dep-valid.js +190 -0
  258. package/lib/third-party/arborist/lib/edge.js +417 -0
  259. package/lib/third-party/arborist/lib/from-path.js +36 -0
  260. package/lib/third-party/arborist/lib/gather-dep-set.js +43 -0
  261. package/lib/third-party/arborist/lib/index.js +22 -0
  262. package/lib/third-party/arborist/lib/inventory.js +138 -0
  263. package/lib/third-party/arborist/lib/link.js +169 -0
  264. package/lib/third-party/arborist/lib/node.js +1673 -0
  265. package/lib/third-party/arborist/lib/npm-extension.js +45 -0
  266. package/lib/third-party/arborist/lib/override-resolves.js +11 -0
  267. package/lib/third-party/arborist/lib/override-set.js +319 -0
  268. package/lib/third-party/arborist/lib/package-extensions.js +289 -0
  269. package/lib/third-party/arborist/lib/printable.js +210 -0
  270. package/lib/third-party/arborist/lib/proc-log.js +30 -0
  271. package/lib/third-party/arborist/lib/realpath.js +100 -0
  272. package/lib/third-party/arborist/lib/relpath.js +4 -0
  273. package/lib/third-party/arborist/lib/shrinkwrap.js +1291 -0
  274. package/lib/third-party/arborist/lib/spec-from-lock.js +34 -0
  275. package/lib/third-party/arborist/lib/tree-check.js +165 -0
  276. package/lib/third-party/arborist/lib/validate-npm-package-name.js +107 -0
  277. package/lib/third-party/arborist/lib/version-from-tgz.js +51 -0
  278. package/lib/third-party/arborist/lib/yarn-lock.js +397 -0
  279. package/lib/validator/bomValidator.js +985 -0
  280. package/lib/validator/complianceEngine.js +241 -0
  281. package/lib/validator/complianceRules.js +1680 -0
  282. package/lib/validator/generated/runtime.mjs +17 -0
  283. package/lib/validator/generated/validate-1.6.mjs +21258 -0
  284. package/lib/validator/generated/validate-1.7.mjs +24803 -0
  285. package/lib/validator/generated/validate-2.0.mjs +22931 -0
  286. package/lib/validator/index.js +246 -0
  287. package/lib/validator/reporters/annotations.js +142 -0
  288. package/lib/validator/reporters/console.js +160 -0
  289. package/lib/validator/reporters/index.js +41 -0
  290. package/lib/validator/reporters/json.js +37 -0
  291. package/lib/validator/reporters/sarif.js +184 -0
  292. package/package.json +209 -26
  293. package/types/bin/audit.d.ts +3 -0
  294. package/types/bin/audit.d.ts.map +1 -0
  295. package/types/bin/cdxgen.d.ts +3 -0
  296. package/types/bin/cdxgen.d.ts.map +1 -0
  297. package/types/bin/convert.d.ts +3 -0
  298. package/types/bin/convert.d.ts.map +1 -0
  299. package/types/bin/evinse.d.ts +3 -0
  300. package/types/bin/evinse.d.ts.map +1 -0
  301. package/types/bin/hbom.d.ts +3 -0
  302. package/types/bin/hbom.d.ts.map +1 -0
  303. package/types/bin/repl.d.ts +3 -0
  304. package/types/bin/repl.d.ts.map +1 -0
  305. package/types/bin/sign.d.ts +3 -0
  306. package/types/bin/sign.d.ts.map +1 -0
  307. package/types/bin/tracebom.d.ts +3 -0
  308. package/types/bin/tracebom.d.ts.map +1 -0
  309. package/types/bin/validate.d.ts +14 -0
  310. package/types/bin/validate.d.ts.map +1 -0
  311. package/types/bin/verify.d.ts +3 -0
  312. package/types/bin/verify.d.ts.map +1 -0
  313. package/types/lib/audit/index.d.ts +153 -0
  314. package/types/lib/audit/index.d.ts.map +1 -0
  315. package/types/lib/audit/progress.d.ts +31 -0
  316. package/types/lib/audit/progress.d.ts.map +1 -0
  317. package/types/lib/audit/reporters.d.ts +62 -0
  318. package/types/lib/audit/reporters.d.ts.map +1 -0
  319. package/types/lib/audit/scoring.d.ts +36 -0
  320. package/types/lib/audit/scoring.d.ts.map +1 -0
  321. package/types/lib/audit/targets.d.ts +77 -0
  322. package/types/lib/audit/targets.d.ts.map +1 -0
  323. package/types/lib/cli/bomAssembly.d.ts +315 -0
  324. package/types/lib/cli/bomAssembly.d.ts.map +1 -0
  325. package/types/lib/cli/cliOptions.d.ts +156 -0
  326. package/types/lib/cli/cliOptions.d.ts.map +1 -0
  327. package/types/lib/cli/index.d.ts +107 -0
  328. package/types/lib/cli/index.d.ts.map +1 -0
  329. package/types/lib/cli/jsBom.d.ts +94 -0
  330. package/types/lib/cli/jsBom.d.ts.map +1 -0
  331. package/types/lib/cli/jvmBom.d.ts +54 -0
  332. package/types/lib/cli/jvmBom.d.ts.map +1 -0
  333. package/types/lib/cli/managedBom.d.ts +105 -0
  334. package/types/lib/cli/managedBom.d.ts.map +1 -0
  335. package/types/lib/cli/nativeBom.d.ts +143 -0
  336. package/types/lib/cli/nativeBom.d.ts.map +1 -0
  337. package/types/lib/core/activity.d.ts +178 -0
  338. package/types/lib/core/activity.d.ts.map +1 -0
  339. package/types/lib/core/env.d.ts +192 -0
  340. package/types/lib/core/env.d.ts.map +1 -0
  341. package/types/lib/core/fs.d.ts +158 -0
  342. package/types/lib/core/fs.d.ts.map +1 -0
  343. package/types/lib/core/httpClient.d.ts +149 -0
  344. package/types/lib/core/httpClient.d.ts.map +1 -0
  345. package/types/lib/core/logger.d.ts +28 -0
  346. package/types/lib/core/logger.d.ts.map +1 -0
  347. package/types/lib/core/parallel.d.ts +95 -0
  348. package/types/lib/core/parallel.d.ts.map +1 -0
  349. package/types/lib/core/paths.d.ts +36 -0
  350. package/types/lib/core/paths.d.ts.map +1 -0
  351. package/types/lib/core/projectConfig.d.ts +23 -0
  352. package/types/lib/core/projectConfig.d.ts.map +1 -0
  353. package/types/lib/core/propertySanitizer.d.ts +23 -0
  354. package/types/lib/core/propertySanitizer.d.ts.map +1 -0
  355. package/types/lib/core/spdx.d.ts +5 -0
  356. package/types/lib/core/spdx.d.ts.map +1 -0
  357. package/types/lib/core/state.d.ts +20 -0
  358. package/types/lib/core/state.d.ts.map +1 -0
  359. package/types/lib/core/text.d.ts +78 -0
  360. package/types/lib/core/text.d.ts.map +1 -0
  361. package/types/lib/core/ui.d.ts +87 -0
  362. package/types/lib/core/ui.d.ts.map +1 -0
  363. package/types/lib/core/urls.d.ts +43 -0
  364. package/types/lib/core/urls.d.ts.map +1 -0
  365. package/types/lib/ecosystems/asarutils.d.ts +71 -0
  366. package/types/lib/ecosystems/asarutils.d.ts.map +1 -0
  367. package/types/lib/ecosystems/bunutils.d.ts +38 -0
  368. package/types/lib/ecosystems/bunutils.d.ts.map +1 -0
  369. package/types/lib/ecosystems/caxa.d.ts +8 -0
  370. package/types/lib/ecosystems/caxa.d.ts.map +1 -0
  371. package/types/lib/ecosystems/chromextutils.d.ts +97 -0
  372. package/types/lib/ecosystems/chromextutils.d.ts.map +1 -0
  373. package/types/lib/ecosystems/cmakeResolver.d.ts +176 -0
  374. package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -0
  375. package/types/lib/ecosystems/cppEvidence.d.ts +35 -0
  376. package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -0
  377. package/types/lib/ecosystems/denoutils.d.ts +76 -0
  378. package/types/lib/ecosystems/denoutils.d.ts.map +1 -0
  379. package/types/lib/ecosystems/dotnetutils.d.ts +45 -0
  380. package/types/lib/ecosystems/dotnetutils.d.ts.map +1 -0
  381. package/types/lib/ecosystems/ecosystems.d.ts +279 -0
  382. package/types/lib/ecosystems/ecosystems.d.ts.map +1 -0
  383. package/types/lib/ecosystems/golem.d.ts +60 -0
  384. package/types/lib/ecosystems/golem.d.ts.map +1 -0
  385. package/types/lib/ecosystems/gradleutils.d.ts +139 -0
  386. package/types/lib/ecosystems/gradleutils.d.ts.map +1 -0
  387. package/types/lib/ecosystems/jsEvidence.d.ts +17 -0
  388. package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -0
  389. package/types/lib/ecosystems/npmutils.d.ts +183 -0
  390. package/types/lib/ecosystems/npmutils.d.ts.map +1 -0
  391. package/types/lib/ecosystems/parsers-bazel.d.ts +36 -0
  392. package/types/lib/ecosystems/parsers-bazel.d.ts.map +1 -0
  393. package/types/lib/ecosystems/parsers-dotnet.d.ts +116 -0
  394. package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -0
  395. package/types/lib/ecosystems/parsers-gleam.d.ts +33 -0
  396. package/types/lib/ecosystems/parsers-gleam.d.ts.map +1 -0
  397. package/types/lib/ecosystems/parsers-go.d.ts +92 -0
  398. package/types/lib/ecosystems/parsers-go.d.ts.map +1 -0
  399. package/types/lib/ecosystems/parsers-js.d.ts +242 -0
  400. package/types/lib/ecosystems/parsers-js.d.ts.map +1 -0
  401. package/types/lib/ecosystems/parsers-jvm.d.ts +100 -0
  402. package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -0
  403. package/types/lib/ecosystems/parsers-misc.d.ts +450 -0
  404. package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -0
  405. package/types/lib/ecosystems/parsers-python.d.ts +145 -0
  406. package/types/lib/ecosystems/parsers-python.d.ts.map +1 -0
  407. package/types/lib/ecosystems/parsers-rust.d.ts +56 -0
  408. package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -0
  409. package/types/lib/ecosystems/parsers-zig.d.ts +83 -0
  410. package/types/lib/ecosystems/parsers-zig.d.ts.map +1 -0
  411. package/types/lib/ecosystems/pep770.d.ts +38 -0
  412. package/types/lib/ecosystems/pep770.d.ts.map +1 -0
  413. package/types/lib/ecosystems/pylockutils.d.ts +68 -0
  414. package/types/lib/ecosystems/pylockutils.d.ts.map +1 -0
  415. package/types/lib/ecosystems/pythonutils.d.ts +70 -0
  416. package/types/lib/ecosystems/pythonutils.d.ts.map +1 -0
  417. package/types/lib/ecosystems/registryProvenance.d.ts +26 -0
  418. package/types/lib/ecosystems/registryProvenance.d.ts.map +1 -0
  419. package/types/lib/ecosystems/remote/huggingface.d.ts +31 -0
  420. package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -0
  421. package/types/lib/ecosystems/rubyutils.d.ts +182 -0
  422. package/types/lib/ecosystems/rubyutils.d.ts.map +1 -0
  423. package/types/lib/ecosystems/rusi.d.ts +40 -0
  424. package/types/lib/ecosystems/rusi.d.ts.map +1 -0
  425. package/types/lib/ecosystems/sbtutils.d.ts +179 -0
  426. package/types/lib/ecosystems/sbtutils.d.ts.map +1 -0
  427. package/types/lib/ecosystems/tea.d.ts +180 -0
  428. package/types/lib/ecosystems/tea.d.ts.map +1 -0
  429. package/types/lib/ecosystems/utils.d.ts +41 -0
  430. package/types/lib/ecosystems/utils.d.ts.map +1 -0
  431. package/types/lib/ecosystems/zigResolver.d.ts +70 -0
  432. package/types/lib/ecosystems/zigResolver.d.ts.map +1 -0
  433. package/types/lib/evinser/db.d.ts +17 -0
  434. package/types/lib/evinser/db.d.ts.map +1 -0
  435. package/types/lib/evinser/evinser.d.ts +354 -0
  436. package/types/lib/evinser/evinser.d.ts.map +1 -0
  437. package/types/lib/evinser/scalasem.d.ts +15 -0
  438. package/types/lib/evinser/scalasem.d.ts.map +1 -0
  439. package/types/lib/evinser/swiftsem.d.ts +103 -0
  440. package/types/lib/evinser/swiftsem.d.ts.map +1 -0
  441. package/types/lib/helpers/annotationFormatter.d.ts +23 -0
  442. package/types/lib/helpers/annotationFormatter.d.ts.map +1 -0
  443. package/types/lib/helpers/bomSigner.d.ts +28 -0
  444. package/types/lib/helpers/bomSigner.d.ts.map +1 -0
  445. package/types/lib/helpers/exportUtils.d.ts +52 -0
  446. package/types/lib/helpers/exportUtils.d.ts.map +1 -0
  447. package/types/lib/helpers/remote/dependency-track.d.ts +23 -0
  448. package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -0
  449. package/types/lib/helpers/versutils.d.ts +8 -0
  450. package/types/lib/helpers/versutils.d.ts.map +1 -0
  451. package/types/lib/helpers/vsixutils.d.ts +130 -0
  452. package/types/lib/helpers/vsixutils.d.ts.map +1 -0
  453. package/types/lib/inventory/agentFormulationParser.d.ts +21 -0
  454. package/types/lib/inventory/agentFormulationParser.d.ts.map +1 -0
  455. package/types/lib/inventory/aiCollector.d.ts +61 -0
  456. package/types/lib/inventory/aiCollector.d.ts.map +1 -0
  457. package/types/lib/inventory/aiInventory.d.ts +103 -0
  458. package/types/lib/inventory/aiInventory.d.ts.map +1 -0
  459. package/types/lib/inventory/aiModelVariants.d.ts +31 -0
  460. package/types/lib/inventory/aiModelVariants.d.ts.map +1 -0
  461. package/types/lib/inventory/aiOversightCollector.d.ts +28 -0
  462. package/types/lib/inventory/aiOversightCollector.d.ts.map +1 -0
  463. package/types/lib/inventory/aiProvenanceCollector.d.ts +13 -0
  464. package/types/lib/inventory/aiProvenanceCollector.d.ts.map +1 -0
  465. package/types/lib/inventory/analyzer.d.ts +157 -0
  466. package/types/lib/inventory/analyzer.d.ts.map +1 -0
  467. package/types/lib/inventory/analyzerScope.d.ts +106 -0
  468. package/types/lib/inventory/analyzerScope.d.ts.map +1 -0
  469. package/types/lib/inventory/astWorker.d.ts +9 -0
  470. package/types/lib/inventory/astWorker.d.ts.map +1 -0
  471. package/types/lib/inventory/atomUtils.d.ts +159 -0
  472. package/types/lib/inventory/atomUtils.d.ts.map +1 -0
  473. package/types/lib/inventory/auditCategories.d.ts +80 -0
  474. package/types/lib/inventory/auditCategories.d.ts.map +1 -0
  475. package/types/lib/inventory/bomUtils.d.ts +145 -0
  476. package/types/lib/inventory/bomUtils.d.ts.map +1 -0
  477. package/types/lib/inventory/cacheCommands.d.ts +28 -0
  478. package/types/lib/inventory/cacheCommands.d.ts.map +1 -0
  479. package/types/lib/inventory/cacheDir.d.ts +55 -0
  480. package/types/lib/inventory/cacheDir.d.ts.map +1 -0
  481. package/types/lib/inventory/cbomutils.d.ts +37 -0
  482. package/types/lib/inventory/cbomutils.d.ts.map +1 -0
  483. package/types/lib/inventory/cdxrs.d.ts +90 -0
  484. package/types/lib/inventory/cdxrs.d.ts.map +1 -0
  485. package/types/lib/inventory/ciParsers/azurePipelines.d.ts +27 -0
  486. package/types/lib/inventory/ciParsers/azurePipelines.d.ts.map +1 -0
  487. package/types/lib/inventory/ciParsers/circleCi.d.ts +27 -0
  488. package/types/lib/inventory/ciParsers/circleCi.d.ts.map +1 -0
  489. package/types/lib/inventory/ciParsers/common.d.ts +11 -0
  490. package/types/lib/inventory/ciParsers/common.d.ts.map +1 -0
  491. package/types/lib/inventory/ciParsers/githubActions.d.ts +38 -0
  492. package/types/lib/inventory/ciParsers/githubActions.d.ts.map +1 -0
  493. package/types/lib/inventory/ciParsers/gitlabCi.d.ts +26 -0
  494. package/types/lib/inventory/ciParsers/gitlabCi.d.ts.map +1 -0
  495. package/types/lib/inventory/ciParsers/jenkins.d.ts +26 -0
  496. package/types/lib/inventory/ciParsers/jenkins.d.ts.map +1 -0
  497. package/types/lib/inventory/citations.d.ts +90 -0
  498. package/types/lib/inventory/citations.d.ts.map +1 -0
  499. package/types/lib/inventory/communityAiConfigParser.d.ts +14 -0
  500. package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -0
  501. package/types/lib/inventory/containerRisk.d.ts +20 -0
  502. package/types/lib/inventory/containerRisk.d.ts.map +1 -0
  503. package/types/lib/inventory/cryptoAlgorithmFamily.d.ts +37 -0
  504. package/types/lib/inventory/cryptoAlgorithmFamily.d.ts.map +1 -0
  505. package/types/lib/inventory/deps.d.ts +140 -0
  506. package/types/lib/inventory/deps.d.ts.map +1 -0
  507. package/types/lib/inventory/depsUtils.d.ts +74 -0
  508. package/types/lib/inventory/depsUtils.d.ts.map +1 -0
  509. package/types/lib/inventory/display.d.ts +227 -0
  510. package/types/lib/inventory/display.d.ts.map +1 -0
  511. package/types/lib/inventory/dosai.d.ts +130 -0
  512. package/types/lib/inventory/dosai.d.ts.map +1 -0
  513. package/types/lib/inventory/dosaiParsers.d.ts +59 -0
  514. package/types/lib/inventory/dosaiParsers.d.ts.map +1 -0
  515. package/types/lib/inventory/dynamic.d.ts +25 -0
  516. package/types/lib/inventory/dynamic.d.ts.map +1 -0
  517. package/types/lib/inventory/envcontext.d.ts +377 -0
  518. package/types/lib/inventory/envcontext.d.ts.map +1 -0
  519. package/types/lib/inventory/evidenceUtils.d.ts +74 -0
  520. package/types/lib/inventory/evidenceUtils.d.ts.map +1 -0
  521. package/types/lib/inventory/fetchBatch.d.ts +127 -0
  522. package/types/lib/inventory/fetchBatch.d.ts.map +1 -0
  523. package/types/lib/inventory/fetchRate.d.ts +118 -0
  524. package/types/lib/inventory/fetchRate.d.ts.map +1 -0
  525. package/types/lib/inventory/forgeEnricher.d.ts +31 -0
  526. package/types/lib/inventory/forgeEnricher.d.ts.map +1 -0
  527. package/types/lib/inventory/formulationParsers.d.ts +50 -0
  528. package/types/lib/inventory/formulationParsers.d.ts.map +1 -0
  529. package/types/lib/inventory/gtfobins.d.ts +27 -0
  530. package/types/lib/inventory/gtfobins.d.ts.map +1 -0
  531. package/types/lib/inventory/hbom.d.ts +58 -0
  532. package/types/lib/inventory/hbom.d.ts.map +1 -0
  533. package/types/lib/inventory/hbomAnalysis.d.ts +56 -0
  534. package/types/lib/inventory/hbomAnalysis.d.ts.map +1 -0
  535. package/types/lib/inventory/hbomLoader.d.ts +7 -0
  536. package/types/lib/inventory/hbomLoader.d.ts.map +1 -0
  537. package/types/lib/inventory/hostTopology.d.ts +47 -0
  538. package/types/lib/inventory/hostTopology.d.ts.map +1 -0
  539. package/types/lib/inventory/inventoryStats.d.ts +42 -0
  540. package/types/lib/inventory/inventoryStats.d.ts.map +1 -0
  541. package/types/lib/inventory/jsonLike.d.ts +23 -0
  542. package/types/lib/inventory/jsonLike.d.ts.map +1 -0
  543. package/types/lib/inventory/licenseEnhancer.d.ts +70 -0
  544. package/types/lib/inventory/licenseEnhancer.d.ts.map +1 -0
  545. package/types/lib/inventory/lolbas.d.ts +16 -0
  546. package/types/lib/inventory/lolbas.d.ts.map +1 -0
  547. package/types/lib/inventory/mcp.d.ts +29 -0
  548. package/types/lib/inventory/mcp.d.ts.map +1 -0
  549. package/types/lib/inventory/mcpConfigParser.d.ts +20 -0
  550. package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -0
  551. package/types/lib/inventory/mcpDiscovery.d.ts +33 -0
  552. package/types/lib/inventory/mcpDiscovery.d.ts.map +1 -0
  553. package/types/lib/inventory/mcpPinning.d.ts +11 -0
  554. package/types/lib/inventory/mcpPinning.d.ts.map +1 -0
  555. package/types/lib/inventory/osPackageResolver.d.ts +49 -0
  556. package/types/lib/inventory/osPackageResolver.d.ts.map +1 -0
  557. package/types/lib/inventory/osinfo.d.ts +120 -0
  558. package/types/lib/inventory/osinfo.d.ts.map +1 -0
  559. package/types/lib/inventory/osqueryTransform.d.ts +84 -0
  560. package/types/lib/inventory/osqueryTransform.d.ts.map +1 -0
  561. package/types/lib/inventory/plugins.d.ts +58 -0
  562. package/types/lib/inventory/plugins.d.ts.map +1 -0
  563. package/types/lib/inventory/protobom.d.ts +71 -0
  564. package/types/lib/inventory/protobom.d.ts.map +1 -0
  565. package/types/lib/inventory/protobomLoader.d.ts +17 -0
  566. package/types/lib/inventory/protobomLoader.d.ts.map +1 -0
  567. package/types/lib/inventory/provenanceUtils.d.ts +98 -0
  568. package/types/lib/inventory/provenanceUtils.d.ts.map +1 -0
  569. package/types/lib/inventory/purl.d.ts +313 -0
  570. package/types/lib/inventory/purl.d.ts.map +1 -0
  571. package/types/lib/inventory/rustFormulationParser.d.ts +17 -0
  572. package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -0
  573. package/types/lib/inventory/sbomDocument.d.ts +59 -0
  574. package/types/lib/inventory/sbomDocument.d.ts.map +1 -0
  575. package/types/lib/inventory/source.d.ts +163 -0
  576. package/types/lib/inventory/source.d.ts.map +1 -0
  577. package/types/lib/inventory/spdx.d.ts +66 -0
  578. package/types/lib/inventory/spdx.d.ts.map +1 -0
  579. package/types/lib/inventory/spdxExpression.d.ts +58 -0
  580. package/types/lib/inventory/spdxExpression.d.ts.map +1 -0
  581. package/types/lib/inventory/spdxUtils.d.ts +12 -0
  582. package/types/lib/inventory/spdxUtils.d.ts.map +1 -0
  583. package/types/lib/inventory/table.d.ts +19 -0
  584. package/types/lib/inventory/table.d.ts.map +1 -0
  585. package/types/lib/inventory/traceRunner.d.ts +80 -0
  586. package/types/lib/inventory/traceRunner.d.ts.map +1 -0
  587. package/types/lib/inventory/unicodeScan.d.ts +46 -0
  588. package/types/lib/inventory/unicodeScan.d.ts.map +1 -0
  589. package/types/lib/managers/binary.d.ts +76 -0
  590. package/types/lib/managers/binary.d.ts.map +1 -0
  591. package/types/lib/managers/containerutils.d.ts +30 -0
  592. package/types/lib/managers/containerutils.d.ts.map +1 -0
  593. package/types/lib/managers/docker.d.ts +157 -0
  594. package/types/lib/managers/docker.d.ts.map +1 -0
  595. package/types/lib/managers/dockerConnection.d.ts +42 -0
  596. package/types/lib/managers/dockerConnection.d.ts.map +1 -0
  597. package/types/lib/managers/oci.d.ts +21 -0
  598. package/types/lib/managers/oci.d.ts.map +1 -0
  599. package/types/lib/managers/piptree.d.ts +13 -0
  600. package/types/lib/managers/piptree.d.ts.map +1 -0
  601. package/types/lib/parsers/cmakeCache.d.ts +70 -0
  602. package/types/lib/parsers/cmakeCache.d.ts.map +1 -0
  603. package/types/lib/parsers/gguf.d.ts +39 -0
  604. package/types/lib/parsers/gguf.d.ts.map +1 -0
  605. package/types/lib/parsers/gitAiNotes.d.ts +15 -0
  606. package/types/lib/parsers/gitAiNotes.d.ts.map +1 -0
  607. package/types/lib/parsers/gitmodules.d.ts +88 -0
  608. package/types/lib/parsers/gitmodules.d.ts.map +1 -0
  609. package/types/lib/parsers/htmlExtract.d.ts +34 -0
  610. package/types/lib/parsers/htmlExtract.d.ts.map +1 -0
  611. package/types/lib/parsers/huggingfaceManifest.d.ts +153 -0
  612. package/types/lib/parsers/huggingfaceManifest.d.ts.map +1 -0
  613. package/types/lib/parsers/huggingfaceUtils.d.ts +155 -0
  614. package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -0
  615. package/types/lib/parsers/iri.d.ts +68 -0
  616. package/types/lib/parsers/iri.d.ts.map +1 -0
  617. package/types/lib/parsers/npmrc.d.ts +33 -0
  618. package/types/lib/parsers/npmrc.d.ts.map +1 -0
  619. package/types/lib/parsers/ollama.d.ts +22 -0
  620. package/types/lib/parsers/ollama.d.ts.map +1 -0
  621. package/types/lib/parsers/xml.d.ts +47 -0
  622. package/types/lib/parsers/xml.d.ts.map +1 -0
  623. package/types/lib/server/server.d.ts +51 -0
  624. package/types/lib/server/server.d.ts.map +1 -0
  625. package/types/lib/stages/postgen/annotator.d.ts +36 -0
  626. package/types/lib/stages/postgen/annotator.d.ts.map +1 -0
  627. package/types/lib/stages/postgen/auditBom.d.ts +92 -0
  628. package/types/lib/stages/postgen/auditBom.d.ts.map +1 -0
  629. package/types/lib/stages/postgen/postgen.d.ts +59 -0
  630. package/types/lib/stages/postgen/postgen.d.ts.map +1 -0
  631. package/types/lib/stages/postgen/ruleEngine.d.ts +18 -0
  632. package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -0
  633. package/types/lib/stages/postgen/sortBom.d.ts +34 -0
  634. package/types/lib/stages/postgen/sortBom.d.ts.map +1 -0
  635. package/types/lib/stages/postgen/spdxConverter.d.ts +11 -0
  636. package/types/lib/stages/postgen/spdxConverter.d.ts.map +1 -0
  637. package/types/lib/stages/postgen/specVersionCompat.d.ts +71 -0
  638. package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -0
  639. package/types/lib/stages/pregen/envAudit.d.ts +14 -0
  640. package/types/lib/stages/pregen/envAudit.d.ts.map +1 -0
  641. package/types/lib/stages/pregen/pregen.d.ts +59 -0
  642. package/types/lib/stages/pregen/pregen.d.ts.map +1 -0
  643. package/types/lib/third-party/arborist/lib/arborist/index.d.ts +47 -0
  644. package/types/lib/third-party/arborist/lib/arborist/index.d.ts.map +1 -0
  645. package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts +4 -0
  646. package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts.map +1 -0
  647. package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts +4 -0
  648. package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts.map +1 -0
  649. package/types/lib/third-party/arborist/lib/bin-links.d.ts +18 -0
  650. package/types/lib/third-party/arborist/lib/bin-links.d.ts.map +1 -0
  651. package/types/lib/third-party/arborist/lib/calc-dep-flags.d.ts +3 -0
  652. package/types/lib/third-party/arborist/lib/calc-dep-flags.d.ts.map +1 -0
  653. package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts +9 -0
  654. package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts.map +1 -0
  655. package/types/lib/third-party/arborist/lib/consistent-resolve.d.ts +3 -0
  656. package/types/lib/third-party/arborist/lib/consistent-resolve.d.ts.map +1 -0
  657. package/types/lib/third-party/arborist/lib/debug.d.ts +3 -0
  658. package/types/lib/third-party/arborist/lib/debug.d.ts.map +1 -0
  659. package/types/lib/third-party/arborist/lib/dep-valid.d.ts +3 -0
  660. package/types/lib/third-party/arborist/lib/dep-valid.d.ts.map +1 -0
  661. package/types/lib/third-party/arborist/lib/edge.d.ts +46 -0
  662. package/types/lib/third-party/arborist/lib/edge.d.ts.map +1 -0
  663. package/types/lib/third-party/arborist/lib/from-path.d.ts +3 -0
  664. package/types/lib/third-party/arborist/lib/from-path.d.ts.map +1 -0
  665. package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts +3 -0
  666. package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts.map +1 -0
  667. package/types/lib/third-party/arborist/lib/index.d.ts +3 -0
  668. package/types/lib/third-party/arborist/lib/index.d.ts.map +1 -0
  669. package/types/lib/third-party/arborist/lib/inventory.d.ts +14 -0
  670. package/types/lib/third-party/arborist/lib/inventory.d.ts.map +1 -0
  671. package/types/lib/third-party/arborist/lib/link.d.ts +18 -0
  672. package/types/lib/third-party/arborist/lib/link.d.ts.map +1 -0
  673. package/types/lib/third-party/arborist/lib/node.d.ts +112 -0
  674. package/types/lib/third-party/arborist/lib/node.d.ts.map +1 -0
  675. package/types/lib/third-party/arborist/lib/npm-extension.d.ts +18 -0
  676. package/types/lib/third-party/arborist/lib/npm-extension.d.ts.map +1 -0
  677. package/types/lib/third-party/arborist/lib/override-resolves.d.ts +3 -0
  678. package/types/lib/third-party/arborist/lib/override-resolves.d.ts.map +1 -0
  679. package/types/lib/third-party/arborist/lib/override-set.d.ts +27 -0
  680. package/types/lib/third-party/arborist/lib/override-set.d.ts.map +1 -0
  681. package/types/lib/third-party/arborist/lib/package-extensions.d.ts +36 -0
  682. package/types/lib/third-party/arborist/lib/package-extensions.d.ts.map +1 -0
  683. package/types/lib/third-party/arborist/lib/printable.d.ts +3 -0
  684. package/types/lib/third-party/arborist/lib/printable.d.ts.map +1 -0
  685. package/types/lib/third-party/arborist/lib/proc-log.d.ts +20 -0
  686. package/types/lib/third-party/arborist/lib/proc-log.d.ts.map +1 -0
  687. package/types/lib/third-party/arborist/lib/realpath.d.ts +3 -0
  688. package/types/lib/third-party/arborist/lib/realpath.d.ts.map +1 -0
  689. package/types/lib/third-party/arborist/lib/relpath.d.ts +3 -0
  690. package/types/lib/third-party/arborist/lib/relpath.d.ts.map +1 -0
  691. package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts +54 -0
  692. package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts.map +1 -0
  693. package/types/lib/third-party/arborist/lib/spec-from-lock.d.ts +3 -0
  694. package/types/lib/third-party/arborist/lib/spec-from-lock.d.ts.map +1 -0
  695. package/types/lib/third-party/arborist/lib/tree-check.d.ts +3 -0
  696. package/types/lib/third-party/arborist/lib/tree-check.d.ts.map +1 -0
  697. package/types/lib/third-party/arborist/lib/validate-npm-package-name.d.ts +13 -0
  698. package/types/lib/third-party/arborist/lib/validate-npm-package-name.d.ts.map +1 -0
  699. package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts +6 -0
  700. package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts.map +1 -0
  701. package/types/lib/third-party/arborist/lib/yarn-lock.d.ts +35 -0
  702. package/types/lib/third-party/arborist/lib/yarn-lock.d.ts.map +1 -0
  703. package/types/lib/validator/bomValidator.d.ts +40 -0
  704. package/types/lib/validator/bomValidator.d.ts.map +1 -0
  705. package/types/lib/validator/complianceEngine.d.ts +72 -0
  706. package/types/lib/validator/complianceEngine.d.ts.map +1 -0
  707. package/types/lib/validator/complianceRules.d.ts +61 -0
  708. package/types/lib/validator/complianceRules.d.ts.map +1 -0
  709. package/types/lib/validator/index.d.ts +101 -0
  710. package/types/lib/validator/index.d.ts.map +1 -0
  711. package/types/lib/validator/reporters/annotations.d.ts +37 -0
  712. package/types/lib/validator/reporters/annotations.d.ts.map +1 -0
  713. package/types/lib/validator/reporters/console.d.ts +34 -0
  714. package/types/lib/validator/reporters/console.d.ts.map +1 -0
  715. package/types/lib/validator/reporters/index.d.ts +30 -0
  716. package/types/lib/validator/reporters/index.d.ts.map +1 -0
  717. package/types/lib/validator/reporters/json.d.ts +11 -0
  718. package/types/lib/validator/reporters/json.d.ts.map +1 -0
  719. package/types/lib/validator/reporters/sarif.d.ts +22 -0
  720. package/types/lib/validator/reporters/sarif.d.ts.map +1 -0
  721. package/mod.d.ts +0 -7
  722. package/mod.js +0 -22
package/bin/cdxgen.js ADDED
@@ -0,0 +1,2324 @@
1
+ #!/usr/bin/env node
2
+ import { Buffer } from "node:buffer";
3
+ import crypto from "node:crypto";
4
+ import fs from "node:fs";
5
+ import http from "node:http";
6
+ import https from "node:https";
7
+ import {
8
+ basename,
9
+ dirname,
10
+ isAbsolute,
11
+ join,
12
+ relative,
13
+ resolve,
14
+ } from "node:path";
15
+ import process from "node:process";
16
+
17
+ import { parse as _load } from "yaml";
18
+ import yargs from "yargs";
19
+ import { hideBin } from "yargs/helpers";
20
+
21
+ import {
22
+ applyAdvancedOptions as applyAdvancedOptionsImpl,
23
+ buildOptionsFromArgs,
24
+ isUserProvided,
25
+ validateSpecVersion,
26
+ } from "../lib/cli/cliOptions.js";
27
+ import { createBom, submitBom } from "../lib/cli/index.js";
28
+ import { TRACE_MODE, thoughtEnd, thoughtLog } from "../lib/core/logger.js";
29
+ import {
30
+ PROJECT_CONFIG_FILENAMES,
31
+ sanitizeProjectConfig,
32
+ } from "../lib/core/projectConfig.js";
33
+ import {
34
+ ui as defaultUi,
35
+ installConsoleShim,
36
+ restoreConsole,
37
+ } from "../lib/core/ui.js";
38
+ import { fetchPomXmlAsJson } from "../lib/ecosystems/ecosystems.js";
39
+ import { normalizeHuggingFaceReference } from "../lib/ecosystems/remote/huggingface.js";
40
+ import {
41
+ commandsExecuted,
42
+ DEBUG_MODE,
43
+ getDefaultBomAuditCategories,
44
+ getTmpDir,
45
+ isAllowedHttpHost,
46
+ isBun,
47
+ isDeno,
48
+ isDryRun,
49
+ isMac,
50
+ isNode,
51
+ isSecureMode,
52
+ isWin,
53
+ readEnvironmentVariable,
54
+ recordActivity,
55
+ recordSensitiveFileRead,
56
+ remoteHostsAccessed,
57
+ retrieveCdxgenVersion,
58
+ safeExistsSync,
59
+ safeMkdirSync,
60
+ safeSpawnSync,
61
+ safeWriteSync,
62
+ setActivityContext,
63
+ setDryRunMode,
64
+ shouldRunPredictiveBomAudit,
65
+ } from "../lib/ecosystems/utils.js";
66
+ import { signBom, verifyBom } from "../lib/helpers/bomSigner.js";
67
+ import {
68
+ createOutputPlan,
69
+ getOutputDirectory,
70
+ } from "../lib/helpers/exportUtils.js";
71
+ import {
72
+ DEFAULT_CDX_SPEC_VERSION,
73
+ getSupportedCycloneDxComponentTypes,
74
+ isCycloneDxBom,
75
+ isCycloneDxComponentTypeEnabled,
76
+ normalizeCycloneDxComponentTypeFilter,
77
+ toCycloneDxSpecVersionString,
78
+ } from "../lib/inventory/bomUtils.js";
79
+ import {
80
+ displaySelfThreatModel,
81
+ printActivitySummary,
82
+ printCallStack,
83
+ printDependencyTree,
84
+ printEnvironmentAuditFindings,
85
+ printFormulation,
86
+ printOccurrences,
87
+ printReachables,
88
+ printServices,
89
+ printSponsorBanner,
90
+ printSummary,
91
+ printTable,
92
+ } from "../lib/inventory/display.js";
93
+ import {
94
+ ensureNoMixedHbomProjectTypes,
95
+ ensureSupportedHbomSpecVersion,
96
+ hasHbomProjectType,
97
+ isHbomOnlyProjectTypes,
98
+ } from "../lib/inventory/hbom.js";
99
+ import { resolvePluginBinary } from "../lib/inventory/plugins.js";
100
+ import { importProtobomModule } from "../lib/inventory/protobomLoader.js";
101
+ import {
102
+ cleanupSourceDir,
103
+ findGitRefForPurlVersion,
104
+ gitClone,
105
+ isAllowedPath,
106
+ isAllowedWinPath,
107
+ maybePurlSource,
108
+ maybeRemotePath,
109
+ PURL_REGISTRY_LOOKUP_WARNING,
110
+ resolveGitUrlFromPurl,
111
+ resolvePurlSourceDirectory,
112
+ sanitizeRemoteUrlForLogs,
113
+ validateAndRejectGitSource,
114
+ validatePurlSource,
115
+ } from "../lib/inventory/source.js";
116
+ import { executeOsQuery } from "../lib/managers/binary.js";
117
+ import { getBomWithOras } from "../lib/managers/oci.js";
118
+ import { postProcess } from "../lib/stages/postgen/postgen.js";
119
+ import { convertCycloneDxToSpdx } from "../lib/stages/postgen/spdxConverter.js";
120
+ import { auditEnvironment } from "../lib/stages/pregen/envAudit.js";
121
+ import { prepareEnv } from "../lib/stages/pregen/pregen.js";
122
+ import { validateSpdx } from "../lib/validator/bomValidator.js";
123
+ import { validateGeneratedBom } from "../lib/validator/index.js";
124
+
125
+ // Support for config files. The config file lives in the directory under
126
+ // analysis, so it carries that directory's trust level; see
127
+ // sanitizeProjectConfig for the boundary this applies.
128
+ let config = {};
129
+ for (const configPattern of PROJECT_CONFIG_FILENAMES) {
130
+ const configPath = join(process.cwd(), configPattern);
131
+ if (!safeExistsSync(configPath)) {
132
+ continue;
133
+ }
134
+ try {
135
+ if (configPath.endsWith(".yml") || configPath.endsWith(".yaml")) {
136
+ config = _load(fs.readFileSync(configPath, "utf-8"));
137
+ } else {
138
+ config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
139
+ }
140
+ if (isSecureMode || DEBUG_MODE) {
141
+ console.log(`Config file '${configPath}' loaded successfully.`);
142
+ }
143
+ const sanitized = sanitizeProjectConfig(config, dirname(configPath));
144
+ config = sanitized.config;
145
+ for (const entry of sanitized.rejected) {
146
+ console.warn(
147
+ `\x1b[1;35mConfig file '${configPath}' sets '${entry}', which points outside the project directory. Ignoring it. Pass the option on the command line if this is intentional.\x1b[0m`,
148
+ );
149
+ }
150
+ for (const foundKey of sanitized.announced) {
151
+ console.warn(
152
+ `Config file '${configPath}' sets '${foundKey}'. Verify this is intentional.`,
153
+ );
154
+ }
155
+ } catch (_e) {
156
+ console.log("Invalid config file", configPath);
157
+ }
158
+ }
159
+
160
+ const _yargs = yargs(hideBin(process.argv));
161
+ /** Actions accepted by the `cdxgen cache` subcommand. */
162
+ const CACHE_ACTIONS = ["info", "clear"];
163
+ const invokedCommandName = basename(process.argv[1] || "cdxgen").replace(
164
+ /\.(?:[cm]?js|exe)$/u,
165
+ "",
166
+ );
167
+ const defaultComponentTypeChoices = getSupportedCycloneDxComponentTypes(
168
+ DEFAULT_CDX_SPEC_VERSION,
169
+ );
170
+
171
+ // Intercept --version --verbose BEFORE yargs' built-in --version handler exits.
172
+ if (
173
+ (process.argv.includes("--version") || process.argv.includes("-v")) &&
174
+ process.argv.includes("--verbose")
175
+ ) {
176
+ console.log(`cdxgen ${retrieveCdxgenVersion()}`);
177
+ try {
178
+ const { cdxrsAvailable } = await import("../lib/inventory/cdxrs.js");
179
+ const rs = cdxrsAvailable("info");
180
+ if (rs.available) {
181
+ console.log(`cdxrs ${rs.version} (available)`);
182
+ } else {
183
+ console.log(`cdxrs: not available (${rs.reason})`);
184
+ }
185
+ } catch {
186
+ console.log("cdxrs: bridge not loaded");
187
+ }
188
+ process.exit(0);
189
+ }
190
+
191
+ const args = _yargs
192
+ .env("CDXGEN")
193
+ .parserConfiguration({
194
+ "greedy-arrays": false,
195
+ "short-option-groups": false,
196
+ "dot-notation": false,
197
+ "parse-numbers": true,
198
+ "boolean-negation": true,
199
+ })
200
+ .option("output", {
201
+ alias: "o",
202
+ description:
203
+ "Output file. Default bom.json. Use -o - to write the BOM to stdout.",
204
+ default: "bom.json",
205
+ nargs: 1,
206
+ })
207
+ .option("evinse-output", {
208
+ description:
209
+ "Create bom with evidence as a separate file. Default bom.json",
210
+ hidden: true,
211
+ })
212
+ .option("type", {
213
+ alias: "t",
214
+ description:
215
+ "Project type. Please refer to https://cdxgen.github.io/cdxgen/#/PROJECT_TYPES for supported languages/platforms.",
216
+ })
217
+ .option("exclude-type", {
218
+ description:
219
+ "Project types to exclude. Please refer to https://cdxgen.github.io/cdxgen/#/PROJECT_TYPES for supported languages/platforms.",
220
+ })
221
+ .option("recurse", {
222
+ alias: "r",
223
+ type: "boolean",
224
+ default: true,
225
+ description:
226
+ "Recurse mode suitable for mono-repos. Defaults to true. Pass --no-recurse to disable.",
227
+ })
228
+ .option("print", {
229
+ alias: "p",
230
+ type: "boolean",
231
+ description: "Print the SBOM as a table with tree.",
232
+ })
233
+ .option("resolve-class", {
234
+ alias: "c",
235
+ type: "boolean",
236
+ description: "Resolve class names for packages. jars only for now.",
237
+ })
238
+ .option("deep", {
239
+ type: "boolean",
240
+ description:
241
+ "Perform deep searches for components. Useful while scanning C/C++ apps, live OS and oci images.",
242
+ })
243
+ .option("git-branch", {
244
+ description: "Git branch to clone when the source is a git URL or purl",
245
+ type: "string",
246
+ })
247
+ .option("server-url", {
248
+ description: "Dependency track url. Eg: https://deptrack.cyclonedx.io",
249
+ type: "string",
250
+ })
251
+ .option("skip-dt-tls-check", {
252
+ type: "boolean",
253
+ default: false,
254
+ description: "Skip TLS certificate check when calling Dependency-Track. ",
255
+ })
256
+ .option("api-key", {
257
+ description: "Dependency track api key",
258
+ type: "string",
259
+ })
260
+ .option("tea-fetch", {
261
+ description:
262
+ "Fetch upstream SBOMs for a Transparency Exchange Identifier (TEI, e.g. urn:tei:uuid:products.example.com:<uuid>) and merge them into the generated BOM.",
263
+ type: "string",
264
+ })
265
+ .option("tea-publish", {
266
+ description:
267
+ "Publish the generated BOM as a TEA Artifact in a Collection at the given TEA server URL (draft publisher API).",
268
+ type: "string",
269
+ })
270
+ .option("tea-leaf-identifier", {
271
+ description:
272
+ "UUID of the TEA leaf/release that the published Collection belongs to (required with --tea-publish).",
273
+ type: "string",
274
+ })
275
+ .option("tea-collection-name", {
276
+ description:
277
+ "Artifact name used with --tea-publish. Defaults to '<project> sbom'.",
278
+ type: "string",
279
+ })
280
+ .option("tea-reason", {
281
+ description:
282
+ "Collection update reason with --tea-publish: INITIAL_RELEASE, ARTIFACT_UPDATED, ARTIFACT_ADDED, ARTIFACT_REMOVED, or VEX_UPDATED.",
283
+ type: "string",
284
+ choices: [
285
+ "INITIAL_RELEASE",
286
+ "VEX_UPDATED",
287
+ "ARTIFACT_UPDATED",
288
+ "ARTIFACT_REMOVED",
289
+ "ARTIFACT_ADDED",
290
+ ],
291
+ default: "INITIAL_RELEASE",
292
+ })
293
+ .option("tea-author-name", {
294
+ description: "Author name recorded in the published TEA Collection.",
295
+ type: "string",
296
+ })
297
+ .option("tea-author-email", {
298
+ description: "Author email recorded in the published TEA Collection.",
299
+ type: "string",
300
+ })
301
+ .option("tea-artifact-url", {
302
+ description:
303
+ "Publicly reachable URL where the published BOM artifact can be downloaded. Defaults to the local output path, which a TEA server will usually not be able to fetch, so supply this whenever the BOM is hosted somewhere.",
304
+ type: "string",
305
+ })
306
+ .option("tea-token", {
307
+ description:
308
+ "Bearer token for TEA authentication. Sent only as an Authorization header and never logged. May also be supplied via the TEA_TOKEN environment variable.",
309
+ type: "string",
310
+ hidden: true,
311
+ })
312
+ .option("project-group", {
313
+ description: "Dependency track project group",
314
+ })
315
+ .option("project-name", {
316
+ description:
317
+ "Dependency track project name. Default use the directory name",
318
+ })
319
+ .option("project-version", {
320
+ description: "Dependency track project version",
321
+ default: "",
322
+ type: "string",
323
+ })
324
+ .option("project-tag", {
325
+ description: "Dependency track project tag. Multiple values allowed.",
326
+ })
327
+ .option("project-id", {
328
+ description:
329
+ "Dependency track project id. Either provide the id or the project name and version together",
330
+ type: "string",
331
+ })
332
+ .option("parent-project-id", {
333
+ description: "Dependency track parent project id",
334
+ type: "string",
335
+ })
336
+ .option("parent-project-name", {
337
+ description: "Dependency track parent project name",
338
+ type: "string",
339
+ })
340
+ .option("parent-project-version", {
341
+ description: "Dependency track parent project version",
342
+ type: "string",
343
+ })
344
+ .option("auto-create", {
345
+ description: "Dependency track autoCreate value for BOM uploads",
346
+ type: "boolean",
347
+ hidden: true,
348
+ })
349
+ .option("is-latest", {
350
+ description: "Dependency track isLatest value for BOM uploads",
351
+ type: "boolean",
352
+ hidden: true,
353
+ })
354
+ .option("required-only", {
355
+ type: "boolean",
356
+ description:
357
+ "Include only the packages with required scope on the SBOM. Would set compositions.aggregate to incomplete unless --no-auto-compositions is passed.",
358
+ })
359
+ .option("fail-on-error", {
360
+ type: "boolean",
361
+ default: isSecureMode,
362
+ description: "Fail if any dependency extractor fails.",
363
+ })
364
+ .option("dry-run", {
365
+ type: "boolean",
366
+ default: isDryRun,
367
+ description:
368
+ "Read-only mode. cdxgen only performs file reads and reports blocked writes, command execution, temp creation, network access, and submissions.",
369
+ })
370
+ .option("include-runtime", {
371
+ type: "boolean",
372
+ default: false,
373
+ description:
374
+ "For HBOM runs, also collect OBOM runtime inventory and emit a merged host view with strict hardware/runtime topology links.",
375
+ })
376
+ .option("activity-report", {
377
+ choices: ["json", "jsonl"],
378
+ description: "Render the activity report as JSON or JSON Lines.",
379
+ hidden: true,
380
+ type: "string",
381
+ })
382
+ .option("no-babel", {
383
+ type: "boolean",
384
+ description:
385
+ "Do not use babel to perform usage analysis for JavaScript/TypeScript projects.",
386
+ })
387
+ .option("generate-key-and-sign", {
388
+ type: "boolean",
389
+ description:
390
+ "Generate an RSA public/private key pair and then sign the generated SBOM using JSON Web Signatures.",
391
+ })
392
+ .option("server", {
393
+ type: "boolean",
394
+ description: "Run cdxgen as a server",
395
+ })
396
+ .option("server-host", {
397
+ description: "Listen address",
398
+ default: "127.0.0.1",
399
+ type: "string",
400
+ })
401
+ .option("server-port", {
402
+ description: "Listen port",
403
+ default: 9090,
404
+ type: "number",
405
+ })
406
+ .option("install-deps", {
407
+ type: "boolean",
408
+ default: !isSecureMode,
409
+ description:
410
+ "Install dependencies automatically for some projects. Defaults to true but disabled for containers and oci scans. Use --no-install-deps to disable this feature.",
411
+ })
412
+ .option("package-extensions", {
413
+ type: "boolean",
414
+ default: true,
415
+ description:
416
+ "Apply npm packageExtensions manifest repairs on --deep scans. Defaults to true, matching npm. Pass --no-package-extensions to produce a BOM that reflects manifests as published.",
417
+ })
418
+ .option("validate", {
419
+ type: "boolean",
420
+ default: true,
421
+ description:
422
+ "Validate the generated SBOM using json schema. Defaults to true. Pass --no-validate to disable.",
423
+ })
424
+ .option("evidence", {
425
+ type: "boolean",
426
+ default: false,
427
+ description: "Generate SBOM with evidence for supported languages.",
428
+ })
429
+ .option("deps-slices-file", {
430
+ description: "Path for the parsedeps slice file created by atom.",
431
+ default: "deps.slices.json",
432
+ hidden: true,
433
+ })
434
+ .option("usages-slices-file", {
435
+ description: "Path for the usages slices file created by atom.",
436
+ hidden: true,
437
+ })
438
+ .option("data-flow-slices-file", {
439
+ description: "Path for the data-flow slices file created by atom.",
440
+ hidden: true,
441
+ })
442
+ .option("reachables-slices-file", {
443
+ description: "Path for the reachables slices file created by atom.",
444
+ hidden: true,
445
+ })
446
+ .option("semantics-slices-file", {
447
+ description: "Path for the semantics slices file.",
448
+ default: "semantics.slices.json",
449
+ hidden: true,
450
+ })
451
+ .option("openapi-spec-file", {
452
+ description: "Path for the openapi specification file (SaaSBOM).",
453
+ hidden: true,
454
+ })
455
+ .option("spec-version", {
456
+ description:
457
+ "CycloneDX Specification version to use. Defaults to 1.7. Accepted generation targets: 1.6, 1.7, 2.0. (1.4 and 1.5 are rejected as generation targets; downgrade the serialized output if a legacy document is required.)",
458
+ default: DEFAULT_CDX_SPEC_VERSION,
459
+ type: "number",
460
+ })
461
+ .option("filter", {
462
+ description:
463
+ "Filter components containing this word in purl or component.properties.value. Multiple values allowed.",
464
+ })
465
+ .option("only", {
466
+ description:
467
+ "Include components only containing this word in purl. Useful to generate BOM with first party components alone. Multiple values allowed.",
468
+ })
469
+ .option("author", {
470
+ description:
471
+ "The person(s) who created the BOM. Set this value if you're intending the modify the BOM and claim authorship.",
472
+ default: "OWASP Foundation",
473
+ })
474
+ .option("profile", {
475
+ description: "BOM profile to use for generation. Default generic.",
476
+ default: "generic",
477
+ choices: [
478
+ "appsec",
479
+ "research",
480
+ "operational",
481
+ "threat-modeling",
482
+ "license-compliance",
483
+ "generic",
484
+ "machine-learning",
485
+ "ml",
486
+ "deep-learning",
487
+ "ml-deep",
488
+ "ml-tiny",
489
+ ],
490
+ })
491
+ .option("lifecycle", {
492
+ description: "Product lifecycle for the generated BOM.",
493
+ hidden: true,
494
+ choices: ["pre-build", "build", "post-build"],
495
+ })
496
+ .option("include-release-notes", {
497
+ type: "boolean",
498
+ default: false,
499
+ hidden: true,
500
+ description:
501
+ "Attach CycloneDX releaseNotes to the cdxgen tool component in metadata.",
502
+ })
503
+ .option("release-notes-current-tag", {
504
+ type: "string",
505
+ hidden: true,
506
+ description:
507
+ "Current git tag used to build CycloneDX releaseNotes for cdxgen metadata.",
508
+ })
509
+ .option("release-notes-previous-tag", {
510
+ type: "string",
511
+ hidden: true,
512
+ description:
513
+ "Previous git tag used to build CycloneDX releaseNotes for cdxgen metadata.",
514
+ })
515
+ .option("include-regex", {
516
+ description:
517
+ "glob pattern to include. This overrides the default pattern used during auto-detection.",
518
+ type: "string",
519
+ })
520
+ .option("exclude", {
521
+ alias: "exclude-regex",
522
+ description: "Additional glob pattern(s) to ignore",
523
+ nargs: 1,
524
+ type: "array",
525
+ })
526
+ .option("no-ignore", {
527
+ type: "boolean",
528
+ default: false,
529
+ description: "Disable default ignore lists during scanning.",
530
+ })
531
+ .option("export-proto", {
532
+ type: "boolean",
533
+ default: false,
534
+ description: "Serialize and export BOM as protobuf binary.",
535
+ })
536
+ .option("format", {
537
+ description:
538
+ "Export format(s). Supports cyclonedx, spdx, repeated --format flags, or a comma-separated list such as cyclonedx,spdx.",
539
+ })
540
+ .option("proto-bin-file", {
541
+ description: "Path for the serialized protobuf binary.",
542
+ default: "bom.cdx",
543
+ })
544
+ .option("include-formulation", {
545
+ type: "boolean",
546
+ default: false,
547
+ description:
548
+ "Generate formulation section with git metadata and build tools. Defaults to false.",
549
+ })
550
+ .option("include-crypto", {
551
+ type: "boolean",
552
+ default: false,
553
+ description: "Include crypto libraries as components.",
554
+ })
555
+ .option("experimental-mcp-pinning", {
556
+ type: "boolean",
557
+ default: false,
558
+ hidden: true,
559
+ description:
560
+ "Experimental: record an explicit pinning state (cdx:mcp:pinning) and composition (cdx:mcp:composition) for MCP server components. Off by default; the emitted property names are subject to change until the CycloneDX agent-BOM proposal is ratified.",
561
+ })
562
+ .option("license-policy", {
563
+ type: "string",
564
+ description: "Path to a license compliance policy YAML file.",
565
+ })
566
+ .option("license-ref", {
567
+ type: "boolean",
568
+ default: false,
569
+ description: "Synthesize custom LicenseRef IDs for unresolved licenses.",
570
+ })
571
+ .option("standard", {
572
+ description:
573
+ "The list of standards which may consist of regulations, industry or organizational-specific standards, maturity models, best practices, or any other requirements which can be evaluated against or attested to.",
574
+ choices: [
575
+ "asvs-5.0",
576
+ "asvs-4.0.3",
577
+ "bsimm-v13",
578
+ "masvs-2.0.0",
579
+ "nist_ssdf-1.1",
580
+ "pcissc-secure-slc-1.1",
581
+ "scvs-1.0.0",
582
+ "ssaf-DRAFT-2023-11",
583
+ ],
584
+ })
585
+ .option("no-banner", {
586
+ type: "boolean",
587
+ default: false,
588
+ hidden: true,
589
+ description:
590
+ "Do not show the donation banner. Set this attribute if you are an active sponsor for OWASP CycloneDX.",
591
+ })
592
+ .option("json-pretty", {
593
+ type: "boolean",
594
+ default: DEBUG_MODE,
595
+ description: "Pretty-print the generated BOM json.",
596
+ })
597
+ .option("feature-flags", {
598
+ description: "Experimental feature flags to enable. Advanced users only.",
599
+ hidden: true,
600
+ choices: [
601
+ "safe-pip-install",
602
+ "suggest-build-tools",
603
+ "ruby-docker-install",
604
+ "resolve-gradle-distribution",
605
+ ],
606
+ })
607
+ .option("min-confidence", {
608
+ description:
609
+ "Minimum confidence needed for the identity of a component from 0 - 1, where 1 is 100% confidence.",
610
+ default: 0,
611
+ type: "number",
612
+ })
613
+ .option("technique", {
614
+ description: "Analysis technique to use",
615
+ choices: [
616
+ "auto",
617
+ "source-code-analysis",
618
+ "binary-analysis",
619
+ "manifest-analysis",
620
+ "hash-comparison",
621
+ "instrumentation",
622
+ "filename",
623
+ ],
624
+ })
625
+ .option("component-type", {
626
+ description:
627
+ "CycloneDX component type(s) to include. Choices are validated against --spec-version.",
628
+ choices: defaultComponentTypeChoices,
629
+ type: "string",
630
+ })
631
+ .option("tlp-classification", {
632
+ description:
633
+ "Traffic Light Protocol (TLP) classification recorded under metadata.distributionConstraints.tlp (CycloneDX 1.7+). One of: CLEAR, GREEN, AMBER, AMBER_AND_STRICT, RED. See https://www.first.org/tlp/ for guidance.",
634
+ choices: ["CLEAR", "GREEN", "AMBER", "AMBER_AND_STRICT", "RED"],
635
+ })
636
+ .option("env-audit", {
637
+ type: "boolean",
638
+ description:
639
+ "Display a pre-generation environment and configuration security assessment",
640
+ default: false,
641
+ hidden: true,
642
+ })
643
+ .option("bom-audit", {
644
+ type: "boolean",
645
+ description: "Perform post-generation security audit of BOM data",
646
+ default: false,
647
+ hidden: true,
648
+ })
649
+ .option("bom-audit-rules-dir", {
650
+ description:
651
+ "Directory containing additional YAML audit rules (merged with built-in)",
652
+ type: "string",
653
+ hidden: true,
654
+ })
655
+ .option("bom-audit-categories", {
656
+ description:
657
+ "Comma-separated list of rule categories to enable (default: all)",
658
+ type: "string",
659
+ hidden: true,
660
+ })
661
+ .option("bom-audit-min-severity", {
662
+ description:
663
+ "Minimum severity to report: low, medium, or high (default: low)",
664
+ type: "string",
665
+ choices: ["low", "medium", "high"],
666
+ default: "low",
667
+ hidden: true,
668
+ })
669
+ .option("bom-audit-fail-severity", {
670
+ description: "Severity threshold for secure mode failure (default: high)",
671
+ type: "string",
672
+ choices: ["high", "medium", "low"],
673
+ default: "high",
674
+ hidden: true,
675
+ })
676
+ .option("bom-audit-scope", {
677
+ description:
678
+ "Predictive audit target scope. Use 'required' to scan only dependencies with scope=required (missing scope is treated as required).",
679
+ type: "string",
680
+ choices: ["all", "required"],
681
+ default: "all",
682
+ hidden: true,
683
+ })
684
+ .option("bom-audit-max-targets", {
685
+ description:
686
+ "Optional upper bound for predictive audit targets. By default cdxgen scans required dependencies first and expands to at least 50 targets.",
687
+ type: "number",
688
+ hidden: true,
689
+ })
690
+ .option("bom-audit-include-trusted", {
691
+ description:
692
+ "Include packages already marked with trusted publishing metadata in predictive BOM audit target selection.",
693
+ type: "boolean",
694
+ default: false,
695
+ hidden: true,
696
+ })
697
+ .option("bom-audit-only-trusted", {
698
+ description:
699
+ "Restrict predictive BOM audit target selection to packages marked with trusted publishing metadata.",
700
+ type: "boolean",
701
+ default: false,
702
+ hidden: true,
703
+ })
704
+ .option("tui", {
705
+ type: "boolean",
706
+ description: "Launch the terminal user interface (cdxui)",
707
+ default: false,
708
+ })
709
+ .completion("completion", "Generate bash/zsh completion")
710
+ .array("type")
711
+ .array("excludeType")
712
+ .array("filter")
713
+ .array("only")
714
+ .array("author")
715
+ .array("format")
716
+ .array("standard")
717
+ .array("feature-flags")
718
+ .array("technique")
719
+ .array("componentType")
720
+ .check((argv) => {
721
+ const specVersionError = validateSpecVersion(
722
+ argv.specVersion,
723
+ invokedCommandName,
724
+ );
725
+ if (specVersionError) {
726
+ throw new Error(specVersionError);
727
+ }
728
+ return true;
729
+ })
730
+ .check((argv) => {
731
+ const requestedComponentTypes = normalizeCycloneDxComponentTypeFilter(
732
+ argv.componentType,
733
+ );
734
+ if (!requestedComponentTypes.length) {
735
+ return true;
736
+ }
737
+ const normalizedSpecVersion =
738
+ toCycloneDxSpecVersionString(argv.specVersion) ||
739
+ toCycloneDxSpecVersionString(DEFAULT_CDX_SPEC_VERSION);
740
+ const supportedComponentTypes = getSupportedCycloneDxComponentTypes(
741
+ normalizedSpecVersion,
742
+ );
743
+ const unsupportedComponentTypes = requestedComponentTypes.filter(
744
+ (componentType) => !supportedComponentTypes.includes(componentType),
745
+ );
746
+ if (unsupportedComponentTypes.length) {
747
+ throw new Error(
748
+ `Unsupported --component-type value(s) for CycloneDX ${normalizedSpecVersion}: ${unsupportedComponentTypes.join(", ")}. Supported values: ${supportedComponentTypes.join(", ")}`,
749
+ );
750
+ }
751
+ return true;
752
+ })
753
+ .option("auto-compositions", {
754
+ type: "boolean",
755
+ default: true,
756
+ description:
757
+ "Automatically set compositions when the BOM was filtered. Defaults to true",
758
+ })
759
+ .example([
760
+ ["$0 -t java .", "Generate a Java SBOM for the current directory"],
761
+ [
762
+ "$0 -t java -t js .",
763
+ "Generate a SBOM for Java and JavaScript in the current directory",
764
+ ],
765
+ ["$0 -t hbom .", "Generate an HBOM for the current host"],
766
+ [
767
+ "$0 -t java --profile ml .",
768
+ "Generate a Java SBOM for machine learning purposes.",
769
+ ],
770
+ [
771
+ "$0 -t python --profile research .",
772
+ "Generate a Python SBOM for appsec research.",
773
+ ],
774
+ ["$0 --server", "Run cdxgen as a server"],
775
+ ])
776
+ .epilogue(
777
+ `Subcommands:\n cache <${CACHE_ACTIONS.join("|")}> Inspect or purge the registry metadata cache.\n\nfor documentation, visit https://cdxgen.github.io/cdxgen`,
778
+ )
779
+ .config(config)
780
+ .scriptName(invokedCommandName || "cdxgen")
781
+ .version(retrieveCdxgenVersion())
782
+ .alias("v", "version")
783
+ .help(false)
784
+ .option("help", {
785
+ alias: "h",
786
+ type: "boolean",
787
+ description: "Show help",
788
+ })
789
+ .option("verbose", {
790
+ count: true,
791
+ description:
792
+ "Increase log verbosity. Repeat for more detail: --verbose shows per-file detail, --verbose --verbose enables debug output. (Env: CDXGEN_LOG_LEVEL, CDXGEN_DEBUG_MODE)",
793
+ })
794
+ .option("quiet", {
795
+ alias: "q",
796
+ type: "boolean",
797
+ default: false,
798
+ description:
799
+ "Silent mode: show errors only. (Env: CDXGEN_LOG_LEVEL=silent)",
800
+ })
801
+ .option("progress", {
802
+ type: "boolean",
803
+ default: true,
804
+ description:
805
+ "Live progress region. Pass --no-progress to force static output. (Env: CDXGEN_NO_PROGRESS)",
806
+ })
807
+ .option("color", {
808
+ description:
809
+ "When to colorize output. auto detects the terminal. (Env: CDXGEN_COLOR, NO_COLOR, FORCE_COLOR)",
810
+ choices: ["auto", "always", "never"],
811
+ default: "auto",
812
+ })
813
+ .option("log-format", {
814
+ description:
815
+ "Diagnostic log format. json emits NDJSON records to stderr and disables the live region. (Env: CDXGEN_LOG_FORMAT)",
816
+ choices: ["text", "json"],
817
+ default: "text",
818
+ })
819
+ .option("rust", {
820
+ type: "boolean",
821
+ default: true,
822
+ description:
823
+ "Use Rust-native (cdxrs) acceleration where available. Pass --no-rust to force the JS path.",
824
+ })
825
+ .option("cache", {
826
+ type: "boolean",
827
+ default: true,
828
+ description:
829
+ "Use the on-disk metadata cache for registry lookups. Pass --no-cache to bypass it for this run.",
830
+ })
831
+ .option("cache-ttl", {
832
+ type: "number",
833
+ description:
834
+ "Override the metadata cache TTL in seconds. 0 means never expire. Default: 86400 (24h).",
835
+ })
836
+ .wrap(Math.min(120, yargs().terminalWidth())).argv;
837
+
838
+ if (readEnvironmentVariable("CDXGEN_NODE_OPTIONS")) {
839
+ process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS || ""} ${process.env.CDXGEN_NODE_OPTIONS}`;
840
+ }
841
+
842
+ // `--no-rust` is a front-end for CDXGEN_RS_DISABLE=all: the bridge reads only
843
+ // the env var, so every consumer honours the flag without threading an option
844
+ // through each call site. Declared as `rust` (default true) rather than
845
+ // `no-rust` so yargs' own boolean negation produces the flag.
846
+ if (args.rust === false) {
847
+ process.env.CDXGEN_RS_DISABLE = "all";
848
+ }
849
+
850
+ // `--no-cache` and `--cache-ttl` are front-ends for env vars that the fetch
851
+ // bridge reads when constructing cdxrs arguments. Declared as `cache` (default
852
+ // true) so yargs' boolean negation produces `--no-cache`.
853
+ if (args.cache === false) {
854
+ process.env.CDXGEN_NO_CACHE = "true";
855
+ }
856
+ if (args.cacheTtl != null && Number.isFinite(args.cacheTtl)) {
857
+ process.env.CDXGEN_CACHE_TTL = String(args.cacheTtl);
858
+ }
859
+
860
+ // The `cache` subcommand takes its action as a positional word rather than a
861
+ // flag, so an unrecognised action can be rejected instead of silently meaning
862
+ // `info`. A bare `cdxgen cache` is left alone: it is a path, so scanning a
863
+ // directory named `cache` keeps working.
864
+ if (args._[0] === "cache" && args._.length > 1) {
865
+ const action = String(args._[1]);
866
+ if (!CACHE_ACTIONS.includes(action)) {
867
+ console.error(
868
+ `Unknown cache action "${action}". Expected one of: ${CACHE_ACTIONS.join(", ")}.`,
869
+ );
870
+ process.exit(1);
871
+ }
872
+ const { runCacheCommand } = await import("../lib/inventory/cacheCommands.js");
873
+ process.exit(await runCacheCommand(action));
874
+ }
875
+
876
+ if (args.help) {
877
+ console.log(`${retrieveCdxgenVersion()}\n`);
878
+ _yargs.showHelp();
879
+ process.exit(0);
880
+ }
881
+ if (args.bomAuditIncludeTrusted && args.bomAuditOnlyTrusted) {
882
+ console.error(
883
+ "Use either --bom-audit-include-trusted or --bom-audit-only-trusted, not both.",
884
+ );
885
+ process.exit(1);
886
+ }
887
+
888
+ if (args.tui && !readEnvironmentVariable("CI")) {
889
+ const cdxuiPath = resolvePluginBinary("cdxui");
890
+ if (cdxuiPath) {
891
+ const cdxgenArgs = process.argv.slice(2).filter((a) => a !== "--tui");
892
+ const cdxuiResult = safeSpawnSync(cdxuiPath, ["--generate"], {
893
+ stdio: "inherit",
894
+ env: {
895
+ ...process.env,
896
+ CDXGEN_CMD:
897
+ readEnvironmentVariable("CDXGEN_CMD") || process.argv[1] || "cdxgen",
898
+ CDXGEN_ARGS: cdxgenArgs.join(" "),
899
+ },
900
+ });
901
+ process.exit(cdxuiResult.status || 0);
902
+ }
903
+ }
904
+
905
+ // Native Enterprise Network Configuration (Node.js v22.21+, Bun, Deno)
906
+ // https://nodejs.org/en/learn/http/enterprise-network-configuration
907
+ // https://docs.deno.com/runtime/reference/env_variables/#special-environment-variables
908
+ // https://bun.com/docs/guides/http/proxy#environment-variables
909
+ if (
910
+ readEnvironmentVariable("HTTP_PROXY") ||
911
+ readEnvironmentVariable("HTTPS_PROXY")
912
+ ) {
913
+ if (isNode && !isBun && !isDeno) {
914
+ process.env.NODE_USE_ENV_PROXY = "1";
915
+ try {
916
+ const proxyEnv = {
917
+ HTTP_PROXY: readEnvironmentVariable("HTTP_PROXY"),
918
+ HTTPS_PROXY: readEnvironmentVariable("HTTPS_PROXY"),
919
+ NO_PROXY: readEnvironmentVariable("NO_PROXY"),
920
+ };
921
+ http.globalAgent = new http.Agent({ proxyEnv });
922
+ https.globalAgent = new https.Agent({ proxyEnv });
923
+ thoughtLog("Configured native Node.js global agents for HTTP proxy. 🌐");
924
+ } catch (_e) {
925
+ console.warn(
926
+ "Warning: Native proxy configuration failed. Please use Node.js v22.21.0+ for proxy support.",
927
+ );
928
+ }
929
+ } else {
930
+ thoughtLog("Using runtime-native (Deno/Bun) proxy support. 🌐");
931
+ }
932
+ }
933
+
934
+ if (!readEnvironmentVariable("NODE_USE_SYSTEM_CA")) {
935
+ process.env.NODE_USE_SYSTEM_CA = "1";
936
+ }
937
+
938
+ const filePath = args._[0] || process.cwd();
939
+ const sourceInputIsRemoteOrPurl =
940
+ maybeRemotePath(filePath) || maybePurlSource(filePath);
941
+ if (!args.projectName) {
942
+ if (filePath !== ".") {
943
+ args.projectName = basename(filePath);
944
+ } else {
945
+ args.projectName = basename(resolve(filePath));
946
+ }
947
+ }
948
+ thoughtLog(`Let's try to generate a CycloneDX BOM for the path '${filePath}'`);
949
+ if (
950
+ !sourceInputIsRemoteOrPurl &&
951
+ (filePath.includes(" ") || filePath.includes("\r") || filePath.includes("\n"))
952
+ ) {
953
+ console.log(
954
+ `'${filePath}' contains spaces. This could lead to bugs when invoking external build tools.`,
955
+ );
956
+ if (isSecureMode) {
957
+ process.exit(1);
958
+ }
959
+ }
960
+ // Support for obom/cbom aliases
961
+ if (invokedCommandName.includes("obom") && !args.type) {
962
+ thoughtLog(
963
+ "Ok, the user wants to generate an Operations Bill-of-Materials (OBOM).",
964
+ );
965
+ }
966
+ if (invokedCommandName.includes("spdxgen") && !args.format) {
967
+ thoughtLog("Ok, defaulting the export format to SPDX.");
968
+ }
969
+ if (invokedCommandName.includes("aibom") && !args.type) {
970
+ thoughtLog(
971
+ "Ok, the user wants to generate an AI-BOM with direct model metadata and AI-focused inventory defaults.",
972
+ );
973
+ }
974
+
975
+ /**
976
+ * Command line options — built via the extracted buildOptionsFromArgs
977
+ * function in lib/cli/cliOptions.js. That function handles:
978
+ * - Command-name alias expansion (obom, spdxgen, aibom)
979
+ * - Field renames (type→projectType, recurse→multiProject, etc.)
980
+ * - Derived values (deep, noBabel, output path)
981
+ * - Post-construction overrides (dedup, cbom/saasbom, secure, dry-run,
982
+ * standard→specVersion, HBOM formulation)
983
+ *
984
+ * The `userSetSpecVersion` flag solves a subtle bug: yargs always
985
+ * populates `specVersion` with its default (1.7), so checking
986
+ * `!options.specVersion` is always false. We compare against the
987
+ * yargs default to detect explicit user intent.
988
+ */
989
+ const YARGS_SPEC_VERSION_DEFAULT = DEFAULT_CDX_SPEC_VERSION;
990
+ const userSetSpecVersion = isUserProvided(
991
+ args.specVersion,
992
+ YARGS_SPEC_VERSION_DEFAULT,
993
+ );
994
+ const { options, warnings: phase3Warnings } = buildOptionsFromArgs(args, {
995
+ invokedCommandName,
996
+ filePath,
997
+ isRemoteOrPurl: sourceInputIsRemoteOrPurl,
998
+ userSetSpecVersion,
999
+ isDryRun,
1000
+ isSecureMode,
1001
+ });
1002
+ const cliActivityProjectType = Array.isArray(options.projectType)
1003
+ ? options.projectType.join(",")
1004
+ : options.projectType;
1005
+ const cliActivityContext = {
1006
+ projectType: cliActivityProjectType,
1007
+ sourcePath: filePath,
1008
+ };
1009
+ setDryRunMode(options.dryRun);
1010
+ setActivityContext(cliActivityContext);
1011
+ const outputPlan = createOutputPlan(options);
1012
+ const outputIsStdout = options.output === "-";
1013
+ for (const outputFile of Object.values(outputPlan.outputs)) {
1014
+ if (outputFile === "-") {
1015
+ continue;
1016
+ }
1017
+ const outputDirectory = getOutputDirectory(outputFile);
1018
+ if (
1019
+ outputDirectory &&
1020
+ outputDirectory !== process.cwd() &&
1021
+ !safeExistsSync(outputDirectory)
1022
+ ) {
1023
+ safeMkdirSync(outputDirectory, { recursive: true });
1024
+ }
1025
+ }
1026
+ // Configure the live-region UI from the parsed flags, then install the console
1027
+ // shim so every existing console.log call site lands on the diagnostic stream
1028
+ // (stderr) above the live region. Env equivalents keep working and win when
1029
+ // both are set (resolved inside ui.configure).
1030
+ {
1031
+ // Verbosity ladder: 0 silent, 1 normal, 2 verbose, 3 debug. `undefined` means
1032
+ // no flag was given, leaving the env vars to decide.
1033
+ let flagLevel;
1034
+ if (args.quiet) {
1035
+ flagLevel = 0;
1036
+ } else if (args.verbose >= 2) {
1037
+ flagLevel = 3;
1038
+ } else if (args.verbose >= 1) {
1039
+ flagLevel = 2;
1040
+ }
1041
+ const colorByFlag = { always: true, never: false };
1042
+ defaultUi.configure({
1043
+ level: flagLevel,
1044
+ format: args.logFormat,
1045
+ noProgress: args.progress === false,
1046
+ color: colorByFlag[args.color],
1047
+ });
1048
+ installConsoleShim(defaultUi);
1049
+ // Restore the original console when the process exits so post-IIFE output
1050
+ // (and any atexit hooks) uses the real streams.
1051
+ process.once("exit", restoreConsole);
1052
+ }
1053
+ // HBOM validation (side-effects that must stay in the CLI entry point)
1054
+ try {
1055
+ ensureNoMixedHbomProjectTypes(options.projectType);
1056
+ if (hasHbomProjectType(options.projectType)) {
1057
+ ensureSupportedHbomSpecVersion(options.specVersion);
1058
+ }
1059
+ } catch (error) {
1060
+ console.error(error.message);
1061
+ process.exit(1);
1062
+ }
1063
+ if (!options.projectType) {
1064
+ thoughtLog(
1065
+ "Ok, the user wants me to identify all the project types and generate a consolidated BOM document.",
1066
+ );
1067
+ }
1068
+ // Handle dedicated cbom and saasbom commands
1069
+ if (["cbom", "saasbom"].includes(invokedCommandName)) {
1070
+ if (invokedCommandName.includes("cbom")) {
1071
+ thoughtLog(
1072
+ "Ok, the user wants to generate Cryptographic Bill-of-Materials (CBOM).",
1073
+ );
1074
+ } else if (invokedCommandName.includes("saasbom")) {
1075
+ thoughtLog(
1076
+ "Ok, the user wants to generate a Software as a Service Bill-of-Materials (SaaSBOM). I should carefully collect the services, endpoints, and data flows.",
1077
+ );
1078
+ if (readEnvironmentVariable("CDXGEN_IN_CONTAINER") !== "true") {
1079
+ thoughtLog(
1080
+ "Wait, I'm not running in a container. This means the chances of successfully collecting this inventory are quite low. Perhaps this is an advanced user who has set up atom and atom-tools already 🤔?",
1081
+ );
1082
+ }
1083
+ }
1084
+ }
1085
+ if (invokedCommandName.includes("cdxgen-secure")) {
1086
+ thoughtLog(
1087
+ "Ok, the user wants cdxgen to run in secure mode by default. Let's try and use the permissions api.",
1088
+ );
1089
+ process.env.CDXGEN_SECURE_MODE = true;
1090
+ }
1091
+ if (isDryRun) {
1092
+ thoughtLog(
1093
+ "Ok, the user wants cdxgen to run in dry-run mode. I must avoid writes, child processes, temp directories, network submissions, and cloning.",
1094
+ );
1095
+ }
1096
+ for (const warning of phase3Warnings) {
1097
+ if (warning.level === "error") {
1098
+ console.error(warning.message);
1099
+ process.exit(1);
1100
+ } else if (warning.level === "warn") {
1101
+ console.warn(`\x1b[1;35m${warning.message}\x1b[0m`);
1102
+ if (isSecureMode) {
1103
+ process.exit(1);
1104
+ }
1105
+ } else {
1106
+ console.log(warning.message);
1107
+ }
1108
+ }
1109
+ if (options.includeFormulation && options.serverUrl) {
1110
+ thoughtLog(
1111
+ "Wait, the user specified a server URL and wants to include formulation data. Let's warn about accidentally disclosing sensitive data to a remote server.",
1112
+ );
1113
+ } else if (options.includeFormulation) {
1114
+ thoughtLog(
1115
+ "Wait, the user wants to include formulation data. Let's warn about accidentally disclosing sensitive data via the generated BOM.",
1116
+ );
1117
+ }
1118
+
1119
+ /**
1120
+ * Apply advanced options (profile, lifecycle, technique expansion).
1121
+ */
1122
+ if (options?.profile !== "generic") {
1123
+ thoughtLog(`BOM profile to use is '${options.profile}'.`);
1124
+ } else {
1125
+ thoughtLog(
1126
+ "The user hasn't specified a profile. Should I suggest one to optimize the BOM for a specific use case or persona 🤔?",
1127
+ );
1128
+ }
1129
+ if (options.lifecycle) {
1130
+ thoughtLog(`BOM must be generated for the lifecycle '${options.lifecycle}'.`);
1131
+ }
1132
+ const isHbomOnlyInvocation = isHbomOnlyProjectTypes(options.projectType);
1133
+ const advancedWarnings = applyAdvancedOptionsImpl(options, {
1134
+ isSecureMode,
1135
+ });
1136
+ if (options?.technique && Array.isArray(options.technique)) {
1137
+ if (options.technique.length === 1) {
1138
+ thoughtLog(
1139
+ `Wait, the user wants me to use only the following technique: '${options.technique.join(", ")}'.`,
1140
+ );
1141
+ } else {
1142
+ thoughtLog(
1143
+ `Alright, I will use only the following techniques: '${options.technique.join(", ")}' for the final BOM.`,
1144
+ );
1145
+ }
1146
+ }
1147
+ if (!options.installDeps) {
1148
+ thoughtLog(
1149
+ "I must avoid any package installations and focus solely on the available artefacts, such as lock files.",
1150
+ );
1151
+ }
1152
+ if (options.bomAudit && isHbomOnlyInvocation) {
1153
+ thoughtLog(
1154
+ "HBOM-only bom-audit runs should stay focused on hardware inventory. Skipping automatic formulation collection.",
1155
+ );
1156
+ }
1157
+ // Surface warnings from applyAdvancedOptions
1158
+ for (const warning of advancedWarnings) {
1159
+ if (warning.level === "error") {
1160
+ console.log(warning.message);
1161
+ process.exit(1);
1162
+ } else {
1163
+ console.log(warning.message);
1164
+ }
1165
+ }
1166
+ if (options.bomAudit && !options.bomAuditCategories) {
1167
+ const defaultBomAuditCategories = getDefaultBomAuditCategories(
1168
+ options,
1169
+ process.argv[1],
1170
+ );
1171
+ if (defaultBomAuditCategories) {
1172
+ options.bomAuditCategories = defaultBomAuditCategories;
1173
+ thoughtLog(
1174
+ `Defaulting BOM audit categories to '${defaultBomAuditCategories}' for this OBOM or explicit os-only invocation.`,
1175
+ );
1176
+ }
1177
+ }
1178
+
1179
+ setActivityContext({
1180
+ projectType: "environment",
1181
+ sourcePath: filePath,
1182
+ });
1183
+ const envAuditFindings = auditEnvironment(process.env, options);
1184
+ setActivityContext(cliActivityContext);
1185
+ if (options.envAudit) {
1186
+ displaySelfThreatModel(filePath, config, options, envAuditFindings);
1187
+ }
1188
+
1189
+ /**
1190
+ * Check for node permission model
1191
+ *
1192
+ * @param {string} filePath File path
1193
+ * @param {Object} options CLI Options
1194
+ * @returns
1195
+ */
1196
+ const checkPermissions = (filePath, options) => {
1197
+ const fullFilePath = resolve(filePath);
1198
+ if (
1199
+ process.getuid &&
1200
+ process.getuid() === 0 &&
1201
+ readEnvironmentVariable("CDXGEN_IN_CONTAINER") !== "true" &&
1202
+ readEnvironmentVariable("RUNNING_IN_SAFER_EXEC_SANDBOX") !== "true"
1203
+ ) {
1204
+ console.log(
1205
+ "\x1b[1;35mSECURE MODE: DO NOT run cdxgen with root privileges.\x1b[0m",
1206
+ );
1207
+ }
1208
+ if (!process.permission) {
1209
+ if (isSecureMode) {
1210
+ console.log(
1211
+ "\x1b[1;35mSecure mode requires permission-related arguments. These can be passed as CLI arguments directly to the node runtime or set the NODE_OPTIONS environment variable as shown below.\x1b[0m",
1212
+ );
1213
+ const childProcessArgs = isDryRun
1214
+ ? ""
1215
+ : options?.lifecycle !== "pre-build"
1216
+ ? " --allow-child-process"
1217
+ : "";
1218
+ const fsWriteArgs = isDryRun
1219
+ ? ""
1220
+ : ` --allow-fs-write="${getTmpDir()}/*" --allow-fs-write="${options.output}"`;
1221
+ const nodeOptionsVal = `--permission --allow-fs-read="${getTmpDir()}/*" --allow-fs-read="${fullFilePath}/*"${fsWriteArgs}${childProcessArgs}`;
1222
+ console.log(
1223
+ `${isWin ? "$env:" : "export "}NODE_OPTIONS='${nodeOptionsVal}'`,
1224
+ );
1225
+ if (readEnvironmentVariable("CDXGEN_IN_CONTAINER") !== "true") {
1226
+ console.log(
1227
+ "TIP: Run cdxgen using the secure container image 'ghcr.io/cdxgen/cdxgen-secure' for best experience.",
1228
+ );
1229
+ }
1230
+ }
1231
+ return true;
1232
+ }
1233
+ // Secure mode checks
1234
+ if (isSecureMode) {
1235
+ if (readEnvironmentVariable("GITHUB_TOKEN")) {
1236
+ console.log(
1237
+ "Ensure that the GitHub token provided to cdxgen is restricted to read-only scopes.",
1238
+ );
1239
+ }
1240
+ if (process.permission.has("fs.read", "*")) {
1241
+ console.log(
1242
+ "\x1b[1;35mSECURE MODE: DO NOT run cdxgen with FileSystemRead permission set to wildcard.\x1b[0m",
1243
+ );
1244
+ }
1245
+ if (process.permission.has("fs.write", "*")) {
1246
+ console.log(
1247
+ "\x1b[1;35mSECURE MODE: DO NOT run cdxgen with FileSystemWrite permission set to wildcard.\x1b[0m",
1248
+ );
1249
+ }
1250
+ if (process.permission.has("worker")) {
1251
+ console.log(
1252
+ "SECURE MODE: DO NOT run cdxgen with worker thread permission! Remove `--allow-worker` argument.",
1253
+ );
1254
+ }
1255
+ if (filePath !== fullFilePath) {
1256
+ console.log(
1257
+ `\x1b[1;35mSECURE MODE: Invoke cdxgen with an absolute path to improve security. Use '${fullFilePath}' instead of '${filePath}'\x1b[0m`,
1258
+ );
1259
+ if (fullFilePath.includes(" ")) {
1260
+ console.log(
1261
+ "\x1b[1;35mSECURE MODE: Directory names containing spaces are known to cause issues. Rename the directories by replacing spaces with hyphens or underscores.\x1b[0m",
1262
+ );
1263
+ } else if (fullFilePath.length > 255 && isWin) {
1264
+ console.log(
1265
+ "Ensure 'Enable Win32 Long paths' is set to 'Enabled' by using Group Policy Editor.",
1266
+ );
1267
+ }
1268
+ return false;
1269
+ }
1270
+ }
1271
+
1272
+ if (!process.permission.has("fs.read", filePath)) {
1273
+ console.log(
1274
+ `\x1b[1;35mSECURE MODE: FileSystemRead permission required. Please invoke cdxgen with the argument --allow-fs-read="${resolve(
1275
+ filePath,
1276
+ )}"\x1b[0m`,
1277
+ );
1278
+ return false;
1279
+ }
1280
+ if (
1281
+ !isDryRun &&
1282
+ options.output !== "-" &&
1283
+ !process.permission.has("fs.write", options.output)
1284
+ ) {
1285
+ console.log(
1286
+ `\x1b[1;35mSECURE MODE: FileSystemWrite permission is required to create the output BOM file. Please invoke cdxgen with the argument --allow-fs-write="${options.output}"\x1b[0m`,
1287
+ );
1288
+ }
1289
+ if (!isDryRun && options.evidence) {
1290
+ const slicesFilesKeys = [
1291
+ "deps-slices-file",
1292
+ "usages-slices-file",
1293
+ "reachables-slices-file",
1294
+ ];
1295
+ if (options?.type?.includes("swift") || options?.type?.includes("scala")) {
1296
+ slicesFilesKeys.push("semantics-slices-file");
1297
+ }
1298
+ for (const sf of slicesFilesKeys) {
1299
+ let issueFound = false;
1300
+ if (!process.permission.has("fs.write", options[sf])) {
1301
+ console.log(
1302
+ `SECURE MODE: FileSystemWrite permission is required to create the output slices file. Please invoke cdxgen with the argument --allow-fs-write="${options[sf]}"`,
1303
+ );
1304
+ if (!issueFound) {
1305
+ issueFound = true;
1306
+ }
1307
+ }
1308
+ if (issueFound) {
1309
+ return false;
1310
+ }
1311
+ }
1312
+ }
1313
+ if (!isDryRun && !process.permission.has("fs.write", getTmpDir())) {
1314
+ console.log(
1315
+ `FileSystemWrite permission may be required for the TEMP directory. Please invoke cdxgen with the argument --allow-fs-write="${join(getTmpDir(), "*")}" in case of any crashes.`,
1316
+ );
1317
+ if (isMac) {
1318
+ console.log(
1319
+ "TIP: macOS doesn't use the `/tmp` prefix for TEMP directories. Use the argument shown above.",
1320
+ );
1321
+ }
1322
+ }
1323
+ if (!isDryRun && !process.permission.has("child") && !isSecureMode) {
1324
+ console.log(
1325
+ "ChildProcess permission is missing. This is required to spawn commands for some languages. Please invoke cdxgen with the argument --allow-child-process in case of issues.",
1326
+ );
1327
+ }
1328
+ if (
1329
+ !isDryRun &&
1330
+ process.permission.has("child") &&
1331
+ options?.lifecycle === "pre-build"
1332
+ ) {
1333
+ console.log(
1334
+ "SECURE MODE: ChildProcess permission is not required for pre-build SBOM generation. Please invoke cdxgen without the argument --allow-child-process.",
1335
+ );
1336
+ return false;
1337
+ }
1338
+ return true;
1339
+ };
1340
+
1341
+ const needsBomSigning = ({ generateKeyAndSign }) =>
1342
+ generateKeyAndSign ||
1343
+ (() => {
1344
+ setActivityContext({ projectType: "environment" });
1345
+ const sbomSignAlgorithm = readEnvironmentVariable("SBOM_SIGN_ALGORITHM");
1346
+ const sbomSignPrivateKey = readEnvironmentVariable(
1347
+ "SBOM_SIGN_PRIVATE_KEY",
1348
+ {
1349
+ sensitive: true,
1350
+ },
1351
+ );
1352
+ const sbomSignPrivateKeyBase64 = readEnvironmentVariable(
1353
+ "SBOM_SIGN_PRIVATE_KEY_BASE64",
1354
+ {
1355
+ sensitive: true,
1356
+ },
1357
+ );
1358
+ return (
1359
+ sbomSignAlgorithm &&
1360
+ sbomSignAlgorithm !== "none" &&
1361
+ ((sbomSignPrivateKey && safeExistsSync(sbomSignPrivateKey)) ||
1362
+ sbomSignPrivateKeyBase64)
1363
+ );
1364
+ })();
1365
+
1366
+ const stringifyJson = (jsonPayload, jsonPretty) =>
1367
+ typeof jsonPayload === "string" || jsonPayload instanceof String
1368
+ ? jsonPayload
1369
+ : JSON.stringify(jsonPayload, null, jsonPretty ? 2 : null);
1370
+
1371
+ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
1372
+ const jsonPayload = stringifyJson(bomJson, options.jsonPretty);
1373
+ safeWriteSync(jsonFile, jsonPayload);
1374
+ if (jsonFile.endsWith("bom.json")) {
1375
+ thoughtLog(
1376
+ `Let's save the file to "${jsonFile}". Should I suggest the '.cdx.json' file extension for better semantics?`,
1377
+ );
1378
+ } else {
1379
+ thoughtLog(`Let's save the file to "${jsonFile}".`);
1380
+ }
1381
+ if (!jsonPayload || !needsBomSigning(options)) {
1382
+ return jsonPayload;
1383
+ }
1384
+ if (isDryRun) {
1385
+ recordActivity({
1386
+ kind: "sign",
1387
+ reason: "Dry run mode skips BOM signing and key generation.",
1388
+ status: "blocked",
1389
+ target: jsonFile,
1390
+ });
1391
+ return jsonPayload;
1392
+ }
1393
+ const sbomSignAlgorithm = readEnvironmentVariable("SBOM_SIGN_ALGORITHM");
1394
+ const sbomSignPrivateKey = readEnvironmentVariable("SBOM_SIGN_PRIVATE_KEY", {
1395
+ sensitive: true,
1396
+ });
1397
+ const sbomSignPrivateKeyBase64 = readEnvironmentVariable(
1398
+ "SBOM_SIGN_PRIVATE_KEY_BASE64",
1399
+ {
1400
+ sensitive: true,
1401
+ },
1402
+ );
1403
+ const sbomSignPublicKey = readEnvironmentVariable("SBOM_SIGN_PUBLIC_KEY");
1404
+ const sbomSignPublicKeyBase64 = readEnvironmentVariable(
1405
+ "SBOM_SIGN_PUBLIC_KEY_BASE64",
1406
+ );
1407
+ let alg = sbomSignAlgorithm || "RS512";
1408
+ if (alg.includes("none")) {
1409
+ alg = "RS512";
1410
+ }
1411
+ let privateKeyToUse;
1412
+ let jwkPublicKey;
1413
+ let publicKeyFile;
1414
+ if (options.generateKeyAndSign) {
1415
+ const jdirName = dirname(jsonFile);
1416
+ publicKeyFile = join(jdirName, "public.key");
1417
+ const privateKeyFile = join(jdirName, "private.key");
1418
+ const privateKeyB64File = join(jdirName, "private.key.base64");
1419
+ const { privateKey, publicKey } = crypto.generateKeyPairSync("rsa", {
1420
+ modulusLength: 4096,
1421
+ publicKeyEncoding: {
1422
+ type: "spki",
1423
+ format: "pem",
1424
+ },
1425
+ privateKeyEncoding: {
1426
+ type: "pkcs8",
1427
+ format: "pem",
1428
+ },
1429
+ });
1430
+ safeWriteSync(publicKeyFile, publicKey);
1431
+ safeWriteSync(privateKeyFile, privateKey);
1432
+ safeWriteSync(
1433
+ privateKeyB64File,
1434
+ Buffer.from(privateKey, "utf8").toString("base64"),
1435
+ );
1436
+ console.log(
1437
+ "Created public/private key pairs for testing purposes",
1438
+ publicKeyFile,
1439
+ privateKeyFile,
1440
+ privateKeyB64File,
1441
+ );
1442
+ privateKeyToUse = privateKey;
1443
+ jwkPublicKey = crypto.createPublicKey(publicKey).export({ format: "jwk" });
1444
+ } else {
1445
+ if (sbomSignPrivateKey) {
1446
+ recordSensitiveFileRead(sbomSignPrivateKey, {
1447
+ label: "SBOM signing private key",
1448
+ });
1449
+ privateKeyToUse = fs.readFileSync(sbomSignPrivateKey, "utf8");
1450
+ } else if (sbomSignPrivateKeyBase64) {
1451
+ privateKeyToUse = Buffer.from(
1452
+ sbomSignPrivateKeyBase64,
1453
+ "base64",
1454
+ ).toString("utf8");
1455
+ }
1456
+ if (sbomSignPublicKey && safeExistsSync(sbomSignPublicKey)) {
1457
+ jwkPublicKey = crypto
1458
+ .createPublicKey(fs.readFileSync(sbomSignPublicKey, "utf8"))
1459
+ .export({ format: "jwk" });
1460
+ } else if (sbomSignPublicKeyBase64) {
1461
+ jwkPublicKey = Buffer.from(sbomSignPublicKeyBase64, "base64").toString(
1462
+ "utf8",
1463
+ );
1464
+ }
1465
+ }
1466
+ try {
1467
+ const bomJsonUnsignedObj = JSON.parse(jsonPayload);
1468
+ const signOptions = {
1469
+ privateKey: privateKeyToUse,
1470
+ algorithm: alg,
1471
+ publicKeyJwk: jwkPublicKey,
1472
+ mode: readEnvironmentVariable("SBOM_SIGN_MODE") || "replace",
1473
+ signComponents: true,
1474
+ signServices: true,
1475
+ signAnnotations: true,
1476
+ };
1477
+ thoughtLog(`Signing the BOM file "${jsonFile}".`);
1478
+ recordActivity({
1479
+ kind: "sign",
1480
+ status: "completed",
1481
+ target: jsonFile,
1482
+ });
1483
+ const signedBom = signBom(bomJsonUnsignedObj, signOptions);
1484
+ safeWriteSync(
1485
+ jsonFile,
1486
+ JSON.stringify(signedBom, null, options.jsonPretty ? 2 : null),
1487
+ );
1488
+ if (publicKeyFile) {
1489
+ const publicKeyStr = fs.readFileSync(publicKeyFile, "utf8");
1490
+ const signatureVerification = verifyBom(signedBom, publicKeyStr);
1491
+ if (signatureVerification) {
1492
+ console.log(
1493
+ "SBOM signature is verifiable natively with the public key and the algorithm",
1494
+ publicKeyFile,
1495
+ alg,
1496
+ );
1497
+ } else {
1498
+ console.log("SBOM signature verification was unsuccessful");
1499
+ console.log("Check if the public key was exported in PEM format");
1500
+ }
1501
+ }
1502
+ } catch (ex) {
1503
+ console.log("SBOM signing was unsuccessful:", ex.message);
1504
+ console.log(
1505
+ "Check if the private key was exported in PEM format and the algorithm is JSF-compliant.",
1506
+ );
1507
+ }
1508
+ return jsonPayload;
1509
+ };
1510
+
1511
+ /**
1512
+ * Method to start the bom creation process
1513
+ */
1514
+ (async () => {
1515
+ // Display the sponsor banner
1516
+ printSponsorBanner(options);
1517
+ // Our quest to audit and check the SBOM generation environment to prevent our users from getting exploited
1518
+ // during SBOM generation.
1519
+ if (envAuditFindings?.length) {
1520
+ printEnvironmentAuditFindings(envAuditFindings);
1521
+ // Only abort in secure mode for high or critical findings; low/medium are informational.
1522
+ if (
1523
+ isSecureMode &&
1524
+ envAuditFindings.some((f) => ["high", "critical"].includes(f.severity))
1525
+ ) {
1526
+ process.exit(1);
1527
+ }
1528
+ }
1529
+ // Start SBOM server
1530
+ if (options.server) {
1531
+ const serverModule = await import("../lib/server/server.js");
1532
+ return serverModule.start(options);
1533
+ }
1534
+ let sourcePath = filePath;
1535
+ let purlResolution;
1536
+ const directHuggingFaceSource = normalizeHuggingFaceReference(sourcePath);
1537
+ if (isDryRun && directHuggingFaceSource) {
1538
+ recordActivity({
1539
+ kind: "read",
1540
+ reason: "Dry run mode blocks direct Hugging Face metadata resolution.",
1541
+ status: "blocked",
1542
+ target: sourcePath,
1543
+ });
1544
+ console.warn("Dry run mode skips direct Hugging Face metadata resolution.");
1545
+ printActivitySummary(options.activityReport);
1546
+ return;
1547
+ }
1548
+ if (isDryRun && maybePurlSource(sourcePath) && !directHuggingFaceSource) {
1549
+ recordActivity({
1550
+ kind: "clone",
1551
+ reason:
1552
+ "Dry run mode blocks package-url source resolution and repository cloning.",
1553
+ status: "blocked",
1554
+ target: sourcePath,
1555
+ });
1556
+ console.warn("Dry run mode skips purl source resolution.");
1557
+ printActivitySummary(options.activityReport);
1558
+ return;
1559
+ }
1560
+ if (maybePurlSource(sourcePath) && !directHuggingFaceSource) {
1561
+ const purlValidationError = validatePurlSource(sourcePath);
1562
+ if (purlValidationError) {
1563
+ console.error(purlValidationError.error, purlValidationError.details);
1564
+ process.exit(1);
1565
+ }
1566
+ purlResolution = await resolveGitUrlFromPurl(sourcePath, {
1567
+ fetchPomXmlAsJson,
1568
+ });
1569
+ if (!purlResolution?.repoUrl) {
1570
+ console.error(
1571
+ "Unable to resolve the provided package URL to a repository URL.",
1572
+ );
1573
+ process.exit(1);
1574
+ }
1575
+ console.warn(
1576
+ `${PURL_REGISTRY_LOOKUP_WARNING} Registry: ${purlResolution.registry}, purl type: ${purlResolution.type}, resolved URL: ${sanitizeRemoteUrlForLogs(purlResolution.repoUrl)}`,
1577
+ );
1578
+ sourcePath = purlResolution.repoUrl;
1579
+ }
1580
+ if (
1581
+ maybeRemotePath(sourcePath) &&
1582
+ !directHuggingFaceSource &&
1583
+ isSecureMode &&
1584
+ !readEnvironmentVariable("CDXGEN_GIT_ALLOWED_HOSTS") &&
1585
+ !readEnvironmentVariable("CDXGEN_SERVER_ALLOWED_HOSTS")
1586
+ ) {
1587
+ console.error(
1588
+ "SECURE MODE: Configure CDXGEN_GIT_ALLOWED_HOSTS (or CDXGEN_SERVER_ALLOWED_HOSTS) before using git URL or purl sources.",
1589
+ );
1590
+ process.exit(1);
1591
+ }
1592
+ if (!maybeRemotePath(sourcePath) && !isAllowedPath(resolve(sourcePath))) {
1593
+ console.error(
1594
+ "Path is not allowed as per CDXGEN_ALLOWED_PATHS/CDXGEN_SERVER_ALLOWED_PATHS.",
1595
+ );
1596
+ process.exit(1);
1597
+ }
1598
+ if (!maybeRemotePath(sourcePath) && !isAllowedWinPath(resolve(sourcePath))) {
1599
+ console.error("Path is not allowed on this platform.");
1600
+ process.exit(1);
1601
+ }
1602
+ if (maybeRemotePath(sourcePath) && !directHuggingFaceSource) {
1603
+ const validationError = validateAndRejectGitSource(sourcePath);
1604
+ if (validationError) {
1605
+ console.error(validationError.error, validationError.details);
1606
+ process.exit(1);
1607
+ }
1608
+ }
1609
+ const checkPath = directHuggingFaceSource
1610
+ ? process.cwd()
1611
+ : maybeRemotePath(sourcePath)
1612
+ ? getTmpDir()
1613
+ : sourcePath;
1614
+ if (maybeRemotePath(sourcePath) && !directHuggingFaceSource) {
1615
+ options.releaseNotesGitUrl = sourcePath;
1616
+ }
1617
+ if (!checkPermissions(checkPath, options)) {
1618
+ if (isSecureMode) {
1619
+ process.exit(1);
1620
+ }
1621
+ return;
1622
+ }
1623
+ let srcDir = sourcePath;
1624
+ let cleanup = false;
1625
+ let gitRef = options.gitBranch;
1626
+ if (maybeRemotePath(sourcePath) && !directHuggingFaceSource) {
1627
+ if (isDryRun) {
1628
+ recordActivity({
1629
+ kind: "clone",
1630
+ reason: "Dry run mode blocks cloning git URL sources.",
1631
+ status: "blocked",
1632
+ target: sourcePath,
1633
+ });
1634
+ console.warn("Dry run mode skips remote git source cloning.");
1635
+ printActivitySummary(options.activityReport);
1636
+ return;
1637
+ }
1638
+ if (!gitRef && purlResolution?.version) {
1639
+ gitRef = findGitRefForPurlVersion(sourcePath, purlResolution);
1640
+ if (!gitRef) {
1641
+ console.warn(
1642
+ `Unable to find a matching git tag for version '${purlResolution.version}'. Falling back to repository default branch.`,
1643
+ );
1644
+ }
1645
+ }
1646
+ srcDir = gitClone(sourcePath, gitRef);
1647
+ if (purlResolution?.type === "npm") {
1648
+ const cloneRootDir = srcDir;
1649
+ const purlSourceDir = resolvePurlSourceDirectory(srcDir, purlResolution);
1650
+ if (purlSourceDir) {
1651
+ if (purlSourceDir !== cloneRootDir) {
1652
+ const relativeDir = relative(cloneRootDir, purlSourceDir);
1653
+ if (relativeDir.startsWith("..") || isAbsolute(relativeDir)) {
1654
+ console.warn(
1655
+ `Ignoring detected npm package directory outside clone root: ${purlSourceDir}`,
1656
+ );
1657
+ } else {
1658
+ console.warn(
1659
+ `Using npm package directory '${purlSourceDir}' for purl '${purlResolution.namespace ? `${purlResolution.namespace}/` : ""}${purlResolution.name}'.`,
1660
+ );
1661
+ srcDir = purlSourceDir;
1662
+ }
1663
+ }
1664
+ }
1665
+ }
1666
+ cleanup = true;
1667
+ }
1668
+ setActivityContext({ sourcePath: srcDir });
1669
+ if (!hasHbomProjectType(options.projectType)) {
1670
+ const prepPhase = defaultUi.phase("Preparing environment");
1671
+ try {
1672
+ prepareEnv(srcDir, options);
1673
+ prepPhase.succeed("");
1674
+ } catch (err) {
1675
+ prepPhase.fail(err);
1676
+ throw err;
1677
+ }
1678
+ }
1679
+ thoughtLog("Getting ready to generate the BOM ⚡️.");
1680
+ if (DEBUG_MODE) {
1681
+ try {
1682
+ const { cdxrsAvailable } = await import("../lib/inventory/cdxrs.js");
1683
+ const rs = cdxrsAvailable("info");
1684
+ console.log(
1685
+ `cdxrs: ${rs.available ? `available (${rs.version})` : `not available (${rs.reason}) — using JS path`}`,
1686
+ );
1687
+ } catch {
1688
+ console.log("cdxrs: bridge not loaded — using JS path");
1689
+ }
1690
+ }
1691
+ const originalFetchPackageMetadata = readEnvironmentVariable(
1692
+ "CDXGEN_FETCH_PKG_METADATA",
1693
+ );
1694
+ const shouldRunPredictiveAudit = shouldRunPredictiveBomAudit(
1695
+ options,
1696
+ process.argv[1],
1697
+ );
1698
+ if (options.bomAudit && shouldRunPredictiveAudit) {
1699
+ process.env.CDXGEN_FETCH_PKG_METADATA = "true";
1700
+ }
1701
+ let bomNSData;
1702
+ const bomPhase = defaultUi.phase("Generating BOM");
1703
+ try {
1704
+ bomNSData = (await createBom(srcDir, options)) || {};
1705
+ bomPhase.succeed(
1706
+ `${bomNSData?.bomJson?.components?.length || 0} components`,
1707
+ );
1708
+ } catch (err) {
1709
+ bomPhase.fail(err);
1710
+ throw err;
1711
+ } finally {
1712
+ if (originalFetchPackageMetadata === undefined) {
1713
+ delete process.env.CDXGEN_FETCH_PKG_METADATA;
1714
+ } else {
1715
+ process.env.CDXGEN_FETCH_PKG_METADATA = originalFetchPackageMetadata;
1716
+ }
1717
+ }
1718
+ if (bomNSData?.bomJson) {
1719
+ thoughtLog(
1720
+ "Tweaking the generated BOM data with useful annotations and properties.",
1721
+ );
1722
+ }
1723
+ // AI provenance/oversight detection is opt-in during generation via
1724
+ // `-t ai-provenance`. The detected cdx:ai:codegen:* / cdx:ai:oversight:*
1725
+ // properties are written to the BOM document root (bomJson.properties) BEFORE
1726
+ // post-processing so the generated annotation summary can reference them.
1727
+ const isAiProvenanceGeneration =
1728
+ Array.isArray(options.projectType) &&
1729
+ options.projectType.some((t) =>
1730
+ ["ai-provenance", "ai-authorship", "aicode", "ai-codegen"].includes(t),
1731
+ );
1732
+ if (isAiProvenanceGeneration && bomNSData?.bomJson) {
1733
+ const { ensureAiProvenanceProperties, ensureAiOversightProperties } =
1734
+ await import("../lib/stages/postgen/auditBom.js");
1735
+ ensureAiProvenanceProperties(bomNSData.bomJson, options);
1736
+ await ensureAiOversightProperties(bomNSData.bomJson, options);
1737
+ }
1738
+ // TEA upstream SBOM fetch runs BEFORE post-processing so the "upstream wins"
1739
+ // merge and the provenance citations flow through the normal pipeline.
1740
+ if (options.teaFetch) {
1741
+ const { applyTeaFetch } = await import("../lib/ecosystems/tea.js");
1742
+ bomNSData = await applyTeaFetch(bomNSData, options);
1743
+ }
1744
+ // Add extra metadata and annotations with post processing
1745
+ {
1746
+ const postPhase = defaultUi.phase("Post-processing BOM");
1747
+ try {
1748
+ bomNSData = postProcess(
1749
+ bomNSData,
1750
+ { ...options, executeOsQuery },
1751
+ srcDir,
1752
+ );
1753
+ postPhase.succeed("");
1754
+ } catch (err) {
1755
+ postPhase.fail(err);
1756
+ throw err;
1757
+ }
1758
+ }
1759
+ setActivityContext({
1760
+ projectType: Array.isArray(options.projectType)
1761
+ ? options.projectType.join(",")
1762
+ : options.projectType,
1763
+ sourcePath: srcDir,
1764
+ });
1765
+ if (options.bomAudit && bomNSData?.bomJson) {
1766
+ const { finalizeAuditReport, runAuditFromBoms } = await import(
1767
+ "../lib/audit/index.js"
1768
+ );
1769
+ const { createProgressTracker } = await import("../lib/audit/progress.js");
1770
+ const { collectAuditTargets } = await import("../lib/audit/targets.js");
1771
+ const { formatPredictiveAnnotations, renderConsoleReport } = await import(
1772
+ "../lib/audit/reporters.js"
1773
+ );
1774
+ const {
1775
+ auditBom,
1776
+ formatDryRunSupportSummary,
1777
+ formatAnnotations,
1778
+ formatConsoleOutput,
1779
+ getBomAuditDryRunSupportSummary,
1780
+ hasCriticalFindings,
1781
+ } = await import("../lib/stages/postgen/auditBom.js");
1782
+ thoughtLog("Let's run security audit...");
1783
+ const postAuditFindings = await auditBom(bomNSData.bomJson, {
1784
+ ...options,
1785
+ getBomWithOras,
1786
+ });
1787
+ if (postAuditFindings.length) {
1788
+ formatConsoleOutput(postAuditFindings);
1789
+ } else if (DEBUG_MODE) {
1790
+ console.log("BOM audit: No findings");
1791
+ }
1792
+ if (isDryRun) {
1793
+ const dryRunSupportSummary =
1794
+ await getBomAuditDryRunSupportSummary(options);
1795
+ const dryRunSupportMessage =
1796
+ formatDryRunSupportSummary(dryRunSupportSummary);
1797
+ if (dryRunSupportMessage) {
1798
+ console.log(dryRunSupportMessage);
1799
+ }
1800
+ }
1801
+ if (postAuditFindings.length && options.specVersion >= 1.4) {
1802
+ bomNSData.bomJson.annotations = [
1803
+ ...(bomNSData.bomJson.annotations || []),
1804
+ ...formatAnnotations(postAuditFindings, bomNSData.bomJson),
1805
+ ];
1806
+ thoughtLog(
1807
+ `Embedded ${postAuditFindings.length} audit findings as CycloneDX annotations`,
1808
+ );
1809
+ }
1810
+ if (isSecureMode && hasCriticalFindings(postAuditFindings, options)) {
1811
+ console.error("\nSecure mode: Critical audit findings detected.");
1812
+ console.error(
1813
+ "Review findings above or adjust --bom-audit-fail-severity to proceed.",
1814
+ );
1815
+ if (cleanup) {
1816
+ cleanupSourceDir(srcDir);
1817
+ }
1818
+ process.exit(1);
1819
+ }
1820
+
1821
+ if (!shouldRunPredictiveAudit) {
1822
+ thoughtLog(
1823
+ "Skipping predictive dependency audit for this OBOM or explicit os-only invocation.",
1824
+ );
1825
+ } else {
1826
+ thoughtLog("Let's run predictive dependency audit...");
1827
+ const progressTracker = createProgressTracker();
1828
+ const predictiveAuditScope =
1829
+ options.bomAuditScope === "required" ? "required" : undefined;
1830
+ const predictiveAuditTrusted = options.bomAuditOnlyTrusted
1831
+ ? "only"
1832
+ : options.bomAuditIncludeTrusted
1833
+ ? "include"
1834
+ : undefined;
1835
+ const requiredAuditTargetCount = collectAuditTargets(
1836
+ [
1837
+ {
1838
+ bomJson: bomNSData.bomJson,
1839
+ source: filePath,
1840
+ },
1841
+ ],
1842
+ {
1843
+ scope: "required",
1844
+ trusted: predictiveAuditTrusted,
1845
+ },
1846
+ ).targets.length;
1847
+ const predictiveAuditMaxTargets =
1848
+ typeof options.bomAuditMaxTargets === "number" &&
1849
+ options.bomAuditMaxTargets > 0
1850
+ ? options.bomAuditMaxTargets
1851
+ : predictiveAuditScope === "required"
1852
+ ? undefined
1853
+ : Math.max(50, requiredAuditTargetCount);
1854
+ let predictiveReport;
1855
+ try {
1856
+ predictiveReport = await runAuditFromBoms(
1857
+ [
1858
+ {
1859
+ bomJson: bomNSData.bomJson,
1860
+ source: filePath,
1861
+ },
1862
+ ],
1863
+ {
1864
+ categories: options.bomAuditCategories
1865
+ ? options.bomAuditCategories
1866
+ .split(",")
1867
+ .map((category) => category.trim())
1868
+ .filter(Boolean)
1869
+ : undefined,
1870
+ failSeverity: options.bomAuditFailSeverity,
1871
+ maxTargets: predictiveAuditMaxTargets,
1872
+ minSeverity: options.bomAuditMinSeverity,
1873
+ onProgress: progressTracker.onProgress,
1874
+ scope: predictiveAuditScope,
1875
+ trusted: predictiveAuditTrusted,
1876
+ trustedSelectionHelp:
1877
+ "Use --bom-audit-include-trusted to include them or --bom-audit-only-trusted to audit just those packages.",
1878
+ },
1879
+ );
1880
+ } finally {
1881
+ progressTracker.stop();
1882
+ }
1883
+ if (predictiveReport.summary.totalTargets > 0) {
1884
+ process.stderr.write(
1885
+ renderConsoleReport(predictiveReport, {
1886
+ minSeverity: options.bomAuditMinSeverity,
1887
+ }),
1888
+ );
1889
+ } else if (DEBUG_MODE) {
1890
+ console.log(
1891
+ "Predictive BOM audit: No supported npm/PyPI targets found",
1892
+ );
1893
+ }
1894
+ const predictiveAnnotations = formatPredictiveAnnotations(
1895
+ predictiveReport,
1896
+ bomNSData.bomJson,
1897
+ {
1898
+ minSeverity: options.bomAuditMinSeverity,
1899
+ },
1900
+ );
1901
+ if (predictiveAnnotations.length && options.specVersion >= 1.4) {
1902
+ bomNSData.bomJson.annotations = [
1903
+ ...(bomNSData.bomJson.annotations || []),
1904
+ ...predictiveAnnotations,
1905
+ ];
1906
+ thoughtLog(
1907
+ `Embedded ${predictiveAnnotations.length} predictive audit annotations`,
1908
+ );
1909
+ }
1910
+ const predictiveResult = finalizeAuditReport(predictiveReport, {
1911
+ failSeverity: options.bomAuditFailSeverity,
1912
+ minSeverity: options.bomAuditMinSeverity,
1913
+ report: "console",
1914
+ });
1915
+ if (isSecureMode && predictiveResult.exitCode === 3) {
1916
+ console.error(
1917
+ "\nSecure mode: Predictive audit findings exceeded the configured threshold.",
1918
+ );
1919
+ console.error(
1920
+ "Review findings above or adjust --bom-audit-fail-severity to proceed.",
1921
+ );
1922
+ if (cleanup) {
1923
+ cleanupSourceDir(srcDir);
1924
+ }
1925
+ process.exit(1);
1926
+ }
1927
+ }
1928
+ }
1929
+ let internalCycloneDxInputPath = outputPlan.outputs.cyclonedx;
1930
+ if ((options.evidence || options.includeCrypto) && bomNSData?.bomJson) {
1931
+ if (!internalCycloneDxInputPath) {
1932
+ internalCycloneDxInputPath = join(
1933
+ getTmpDir(),
1934
+ `cdxgen-${Date.now()}-${basename(filePath)}.cdx.json`,
1935
+ );
1936
+ }
1937
+ if (isDryRun) {
1938
+ recordActivity({
1939
+ kind: "write",
1940
+ reason:
1941
+ "Dry run mode skips evidence input materialization because it writes a temporary BOM file.",
1942
+ status: "blocked",
1943
+ target: internalCycloneDxInputPath,
1944
+ });
1945
+ } else {
1946
+ safeWriteSync(
1947
+ internalCycloneDxInputPath,
1948
+ stringifyJson(bomNSData.bomJson, options.jsonPretty),
1949
+ );
1950
+ }
1951
+ }
1952
+ // Evidence generation
1953
+ if (options.evidence || options.includeCrypto) {
1954
+ if (isDryRun) {
1955
+ recordActivity({
1956
+ kind: "write",
1957
+ reason:
1958
+ "Dry run mode skips evidence and crypto enrichment because those flows require temp files and additional processing.",
1959
+ status: "blocked",
1960
+ target: options.evinseOutput || options.output || "evinse",
1961
+ });
1962
+ } else {
1963
+ // Set the evinse output file to be the same as output file
1964
+ if (!options.evinseOutput) {
1965
+ options.evinseOutput = options.output;
1966
+ }
1967
+ setActivityContext({
1968
+ projectType: "evinse",
1969
+ sourcePath: filePath,
1970
+ });
1971
+ const evinserModule = await import("../lib/evinser/evinser.js");
1972
+ options.projectType = options.projectType || ["java"];
1973
+ const evinseOptions = {
1974
+ _: args._,
1975
+ input: internalCycloneDxInputPath || options.output,
1976
+ output: options.evinseOutput,
1977
+ language: options.projectType,
1978
+ skipMavenCollector: false,
1979
+ force: false,
1980
+ withReachables: options.deep,
1981
+ usagesSlicesFile: options.usagesSlicesFile,
1982
+ dataFlowSlicesFile: options.dataFlowSlicesFile,
1983
+ reachablesSlicesFile: options.reachablesSlicesFile,
1984
+ semanticsSlicesFile: options.semanticsSlicesFile,
1985
+ openapiSpecFile: options.openapiSpecFile,
1986
+ componentType: options.componentType,
1987
+ includeCrypto:
1988
+ options.includeCrypto &&
1989
+ isCycloneDxComponentTypeEnabled("cryptographic-asset", options),
1990
+ specVersion: options.specVersion,
1991
+ profile: options.profile,
1992
+ jsonPretty: options.jsonPretty,
1993
+ };
1994
+ const dbObjMap = await evinserModule.prepareDB(evinseOptions);
1995
+ if (dbObjMap) {
1996
+ const sliceArtefacts = await evinserModule.analyzeProject(
1997
+ dbObjMap,
1998
+ evinseOptions,
1999
+ );
2000
+ const evinseJson = evinserModule.createEvinseFile(
2001
+ sliceArtefacts,
2002
+ evinseOptions,
2003
+ );
2004
+ bomNSData.bomJson = evinseJson;
2005
+ if (options.print && evinseJson) {
2006
+ printOccurrences(evinseJson);
2007
+ printCallStack(evinseJson);
2008
+ printReachables(sliceArtefacts);
2009
+ printServices(evinseJson);
2010
+ }
2011
+ }
2012
+ }
2013
+ }
2014
+ // Perform automatic validation
2015
+ if (options.validate && bomNSData?.bomJson) {
2016
+ thoughtLog("Wait, let's check the generated BOM file for any issues.");
2017
+ const validatePhase = defaultUi.phase("Validating BOM");
2018
+ const validation = await validateGeneratedBom(bomNSData.bomJson);
2019
+ const validationTarget = `cyclonedx-${bomNSData.bomJson.specVersion || options.specVersion}`;
2020
+ if (!validation.valid) {
2021
+ validatePhase.fail("schema validation failed");
2022
+ recordActivity({
2023
+ kind: "validate",
2024
+ reason: `The BOM failed schema validation using the ${validation.source} validator.`,
2025
+ status: "failed",
2026
+ target: validationTarget,
2027
+ });
2028
+ if (cleanup) {
2029
+ cleanupSourceDir(srcDir);
2030
+ }
2031
+ process.exit(1);
2032
+ } else {
2033
+ validatePhase.succeed(`valid (${validation.source})`);
2034
+ recordActivity({
2035
+ kind: "validate",
2036
+ reason: `Validated the BOM against the CycloneDX schema using the ${validation.source} validator.`,
2037
+ status: "completed",
2038
+ target: validationTarget,
2039
+ });
2040
+ thoughtLog("✅ BOM file looks valid.");
2041
+ }
2042
+ } else if (bomNSData?.bomJson) {
2043
+ recordActivity({
2044
+ kind: "validate",
2045
+ reason: "Validation is disabled with --no-validate.",
2046
+ status: "blocked",
2047
+ target: `cyclonedx-${bomNSData.bomJson.specVersion || options.specVersion}`,
2048
+ });
2049
+ }
2050
+ if (
2051
+ outputPlan.formats.has("spdx") &&
2052
+ bomNSData?.bomJson &&
2053
+ isCycloneDxBom(bomNSData.bomJson)
2054
+ ) {
2055
+ thoughtLog(
2056
+ "Preparing the SPDX 3.0.1 export from the validated CycloneDX BOM.",
2057
+ );
2058
+ if (isDryRun) {
2059
+ recordActivity({
2060
+ kind: "convert",
2061
+ reason:
2062
+ "Dry run mode skips SPDX conversion because the export path is read-only.",
2063
+ status: "blocked",
2064
+ target: "spdx",
2065
+ });
2066
+ } else {
2067
+ bomNSData.spdxJson = convertCycloneDxToSpdx(bomNSData.bomJson, options);
2068
+ recordActivity({
2069
+ kind: "convert",
2070
+ status: "completed",
2071
+ target: "spdx",
2072
+ });
2073
+ if (options.validate && !validateSpdx(bomNSData.spdxJson)) {
2074
+ process.exit(1);
2075
+ }
2076
+ }
2077
+ }
2078
+ if (outputIsStdout) {
2079
+ if (!isDryRun && bomNSData.bomJson) {
2080
+ const payload =
2081
+ outputPlan.formats.has("spdx") && bomNSData.spdxJson
2082
+ ? stringifyJson(bomNSData.spdxJson, options.jsonPretty)
2083
+ : stringifyJson(bomNSData.bomJson, options.jsonPretty);
2084
+ process.stdout.write(payload);
2085
+ } else if (isDryRun) {
2086
+ recordActivity({
2087
+ kind: "write",
2088
+ reason: "Dry run mode skips stdout BOM output.",
2089
+ status: "blocked",
2090
+ target: "stdout",
2091
+ });
2092
+ }
2093
+ } else if (
2094
+ options.output &&
2095
+ (typeof options.output === "string" || options.output instanceof String)
2096
+ ) {
2097
+ if (!isDryRun && outputPlan.outputs.cyclonedx && bomNSData.bomJson) {
2098
+ writeCycloneDxOutput(
2099
+ outputPlan.outputs.cyclonedx,
2100
+ bomNSData.bomJson,
2101
+ options,
2102
+ );
2103
+ if (bomNSData.nsMapping && Object.keys(bomNSData.nsMapping).length) {
2104
+ const nsFile = `${outputPlan.outputs.cyclonedx}.map`;
2105
+ safeWriteSync(nsFile, JSON.stringify(bomNSData.nsMapping));
2106
+ }
2107
+ } else if (isDryRun && outputPlan.outputs.cyclonedx) {
2108
+ recordActivity({
2109
+ kind: "write",
2110
+ reason: "Dry run mode skips CycloneDX file output.",
2111
+ status: "blocked",
2112
+ target: outputPlan.outputs.cyclonedx,
2113
+ });
2114
+ }
2115
+ if (!isDryRun && outputPlan.outputs.spdx && bomNSData.spdxJson) {
2116
+ safeWriteSync(
2117
+ outputPlan.outputs.spdx,
2118
+ stringifyJson(bomNSData.spdxJson, options.jsonPretty),
2119
+ );
2120
+ thoughtLog(`Let's save the SPDX file to "${outputPlan.outputs.spdx}".`);
2121
+ } else if (isDryRun && outputPlan.outputs.spdx) {
2122
+ recordActivity({
2123
+ kind: "write",
2124
+ reason: "Dry run mode skips SPDX file output.",
2125
+ status: "blocked",
2126
+ target: outputPlan.outputs.spdx,
2127
+ });
2128
+ }
2129
+ } else if (!options.print) {
2130
+ if (outputPlan.formats.has("spdx") && bomNSData?.spdxJson) {
2131
+ console.log(stringifyJson(bomNSData.spdxJson, options.jsonPretty));
2132
+ } else if (bomNSData.bomJson) {
2133
+ console.log(stringifyJson(bomNSData.bomJson, options.jsonPretty));
2134
+ } else {
2135
+ console.log("Unable to produce BOM for", filePath);
2136
+ console.log("Try running the command with -t <type> or -r argument");
2137
+ }
2138
+ }
2139
+ thoughtEnd();
2140
+ // Automatically submit the bom data
2141
+ // biome-ignore lint/suspicious/noDoubleEquals: yargs passes true for empty values
2142
+ if (options.serverUrl && options.serverUrl != true && options.apiKey) {
2143
+ if (isSecureMode) {
2144
+ let serverHostname;
2145
+ try {
2146
+ serverHostname = new URL(options.serverUrl).hostname;
2147
+ } catch (err) {
2148
+ console.log("Invalid Dependency-Track server URL", err);
2149
+ process.exit(1);
2150
+ }
2151
+ if (!isAllowedHttpHost(serverHostname)) {
2152
+ recordActivity({
2153
+ kind: "submit",
2154
+ reason: "The URL host is not allowed as per the allowlist.",
2155
+ status: "blocked",
2156
+ target: options.serverUrl,
2157
+ });
2158
+ console.log(
2159
+ `Dependency-Track server host '${serverHostname}' is not allowed by CDXGEN_ALLOWED_HOSTS.`,
2160
+ );
2161
+ process.exit(1);
2162
+ }
2163
+ }
2164
+ if (isDryRun) {
2165
+ recordActivity({
2166
+ kind: "submit",
2167
+ reason: "Dry run mode skips remote BOM submission.",
2168
+ status: "blocked",
2169
+ target: options.serverUrl,
2170
+ });
2171
+ } else {
2172
+ try {
2173
+ recordActivity({
2174
+ kind: "submit",
2175
+ status: "completed",
2176
+ target: options.serverUrl,
2177
+ });
2178
+ await submitBom(options, bomNSData.bomJson);
2179
+ } catch (err) {
2180
+ console.log(err);
2181
+ if (cleanup) {
2182
+ cleanupSourceDir(srcDir);
2183
+ }
2184
+ process.exit(1);
2185
+ }
2186
+ }
2187
+ }
2188
+ // TEA publish (draft publisher API). The CycloneDX BOM is already written to
2189
+ // disk above, so a publish failure never costs the user their SBOM: the
2190
+ // failure is reported and the process exits with a distinct status (3).
2191
+ if (options.teaPublish && bomNSData?.bomJson) {
2192
+ if (!options.teaLeafIdentifier) {
2193
+ console.error(
2194
+ "cdxgen: --tea-publish requires --tea-leaf-identifier (UUID of the TEA leaf/release).",
2195
+ );
2196
+ process.exit(3);
2197
+ }
2198
+ if (isDryRun) {
2199
+ recordActivity({
2200
+ kind: "submit",
2201
+ reason: "Dry run mode skips TEA collection publishing.",
2202
+ status: "blocked",
2203
+ target: options.teaPublish,
2204
+ });
2205
+ } else {
2206
+ try {
2207
+ const { buildPublishCollectionPayload, publishTeaCollection } =
2208
+ await import("../lib/ecosystems/tea.js");
2209
+ const parentComponent = bomNSData.bomJson.metadata?.component || {};
2210
+ const projectName =
2211
+ options.teaCollectionName ||
2212
+ parentComponent.name ||
2213
+ basename(resolve(srcDir));
2214
+ // The checksum has to describe the bytes a consumer will download, so
2215
+ // it is taken from the file that was written rather than from a fresh
2216
+ // re-serialisation of the in-memory BOM.
2217
+ const bomFile = outputPlan.outputs.cyclonedx;
2218
+ const artifactContent = bomFile
2219
+ ? fs.readFileSync(bomFile, "utf-8")
2220
+ : JSON.stringify(bomNSData.bomJson);
2221
+ const payload = buildPublishCollectionPayload({
2222
+ leafIdentifier: options.teaLeafIdentifier,
2223
+ productName: projectName,
2224
+ // The product's own version, not bomJson.version, which counts
2225
+ // revisions of the document.
2226
+ productVersion: parentComponent.version || "unknown",
2227
+ authorName: options.teaAuthorName || "cdxgen",
2228
+ authorEmail: options.teaAuthorEmail,
2229
+ reasonType: options.teaReason,
2230
+ artifactName: `${projectName} sbom`,
2231
+ artifactUrl: options.teaArtifactUrl || bomFile || "bom.json",
2232
+ artifactContent,
2233
+ });
2234
+ const result = await publishTeaCollection(
2235
+ options.teaPublish,
2236
+ payload,
2237
+ options,
2238
+ );
2239
+ recordActivity({
2240
+ kind: "submit",
2241
+ status: "completed",
2242
+ target: options.teaPublish,
2243
+ });
2244
+ console.log(
2245
+ `cdxgen: published TEA collection to ${options.teaPublish} (collection version ${result.body?.version ?? "assigned by server"}).`,
2246
+ );
2247
+ } catch (err) {
2248
+ console.error(
2249
+ `cdxgen: failed to publish TEA collection to ${options.teaPublish}: ${err?.message || err}. The local BOM was written regardless.`,
2250
+ );
2251
+ process.exit(3);
2252
+ }
2253
+ }
2254
+ }
2255
+ // Protobuf serialization
2256
+ if (options.exportProto) {
2257
+ if (isDryRun) {
2258
+ recordActivity({
2259
+ kind: "write",
2260
+ reason: "Dry run mode skips protobuf export.",
2261
+ status: "blocked",
2262
+ target: options.protoBinFile,
2263
+ });
2264
+ } else {
2265
+ const protobomModule = await importProtobomModule(
2266
+ invokedCommandName || "cdxgen",
2267
+ "protobuf export",
2268
+ );
2269
+ try {
2270
+ protobomModule.assertProtoSupportedSpecVersion(
2271
+ bomNSData?.bomJson?.specVersion || options.specVersion,
2272
+ "protobuf export",
2273
+ );
2274
+ } catch (error) {
2275
+ console.error(error.message);
2276
+ if (cleanup) {
2277
+ cleanupSourceDir(srcDir);
2278
+ }
2279
+ process.exit(1);
2280
+ }
2281
+ protobomModule.writeBinary(bomNSData.bomJson, options.protoBinFile);
2282
+ thoughtLog("BOM file is also available in .proto format!");
2283
+ }
2284
+ }
2285
+ if (options.print && bomNSData.bomJson?.components) {
2286
+ printSummary(bomNSData.bomJson);
2287
+ if (options.includeFormulation) {
2288
+ printFormulation(bomNSData.bomJson);
2289
+ }
2290
+ printDependencyTree(bomNSData.bomJson);
2291
+ printTable(bomNSData.bomJson);
2292
+ // CBOM related print
2293
+ if (options.includeCrypto) {
2294
+ printTable(bomNSData.bomJson, ["cryptographic-asset"]);
2295
+ printDependencyTree(bomNSData.bomJson, "provides");
2296
+ }
2297
+ }
2298
+ if (isDryRun || DEBUG_MODE) {
2299
+ printActivitySummary(options.activityReport);
2300
+ }
2301
+ if (
2302
+ (DEBUG_MODE || TRACE_MODE) &&
2303
+ (!readEnvironmentVariable("CDXGEN_ALLOWED_HOSTS") ||
2304
+ !readEnvironmentVariable("CDXGEN_ALLOWED_COMMANDS"))
2305
+ ) {
2306
+ let allowListSuggestion = "";
2307
+ const envPrefix = isWin ? "set $env:" : "export ";
2308
+ if (remoteHostsAccessed.size) {
2309
+ allowListSuggestion = `${envPrefix}CDXGEN_ALLOWED_HOSTS="${Array.from(remoteHostsAccessed).join(",")}"\n`;
2310
+ }
2311
+ if (commandsExecuted.size) {
2312
+ allowListSuggestion = `${allowListSuggestion}${envPrefix}CDXGEN_ALLOWED_COMMANDS="${Array.from(commandsExecuted).join(",")}"\n`;
2313
+ }
2314
+ if (allowListSuggestion) {
2315
+ console.log(
2316
+ "SECURE MODE: cdxgen supports allowlists for remote hosts and external commands. Set the following environment variables to get started.",
2317
+ );
2318
+ console.log(allowListSuggestion);
2319
+ }
2320
+ }
2321
+ if (cleanup) {
2322
+ cleanupSourceDir(srcDir);
2323
+ }
2324
+ })();