@cdxgen/cdxgen 0.0.1 → 13.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (722) hide show
  1. package/README.md +921 -87
  2. package/bin/audit.js +239 -0
  3. package/bin/cdxgen.js +2335 -0
  4. package/bin/convert.js +220 -0
  5. package/bin/evinse.js +353 -0
  6. package/bin/hbom.js +504 -0
  7. package/bin/repl.js +2224 -0
  8. package/bin/sign.js +195 -0
  9. package/bin/tracebom.js +303 -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 +1882 -0
  85. package/lib/cli/cliOptions.js +543 -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 +280 -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 +920 -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 +583 -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 +1793 -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 +383 -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 +267 -0
  215. package/lib/inventory/traceRunner.js +439 -0
  216. package/lib/inventory/unicodeScan.js +147 -0
  217. package/lib/managers/binary.js +3459 -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 +329 -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 +50 -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 +201 -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 +22 -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 +147 -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
@@ -0,0 +1,2759 @@
1
+ import {
2
+ accessSync,
3
+ constants,
4
+ lstatSync,
5
+ readFileSync,
6
+ statSync,
7
+ } from "node:fs";
8
+ import { platform as _platform, availableParallelism, homedir } from "node:os";
9
+ import { basename, join } from "node:path";
10
+ import process from "node:process";
11
+
12
+ import {
13
+ cdxgenAgent,
14
+ DEBUG_MODE,
15
+ isAllowedHttpHost,
16
+ isDryRun,
17
+ readEnvironmentVariable,
18
+ recordActivity,
19
+ setActivityContext,
20
+ } from "../core/activity.js";
21
+ import { hasAnyProjectType, PROJECT_TYPE_ALIASES } from "../core/env.js";
22
+ import {
23
+ clearFileDiscoveryCache,
24
+ getAllFiles,
25
+ getTmpDir,
26
+ safeExistsSync,
27
+ safeRmSync,
28
+ setDirWalkCacheRoot,
29
+ } from "../core/fs.js";
30
+ import { thoughtLog } from "../core/logger.js";
31
+ import { mapWithConcurrency } from "../core/parallel.js";
32
+ import { dirNameStr } from "../core/paths.js";
33
+ import { ui } from "../core/ui.js";
34
+ import {
35
+ parseBitbucketPipelinesFile,
36
+ parseContainerFile,
37
+ parseContainerSpecData,
38
+ parseOpenapiSpecData,
39
+ parsePrivadoFile,
40
+ } from "../ecosystems/parsers-misc.js";
41
+ import { isPyLockFile } from "../ecosystems/pylockutils.js";
42
+ import {
43
+ buildDependencyTrackBomPayload,
44
+ getDependencyTrackBomApiUrl,
45
+ } from "../helpers/remote/dependency-track.js";
46
+ import { optionIncludesAiInventoryProjectType } from "../inventory/aiInventory.js";
47
+ import { isCycloneDxComponentTypeEnabled } from "../inventory/bomUtils.js";
48
+ import {
49
+ mergeDependencies,
50
+ mergeServices,
51
+ trimComponents,
52
+ } from "../inventory/depsUtils.js";
53
+ import { buildDynamicComponents } from "../inventory/dynamic.js";
54
+ import { convertOSQueryResults } from "../inventory/evidenceUtils.js";
55
+ import {
56
+ createHbomDocument,
57
+ ensureHbomRuntimeSupport,
58
+ ensureNoMixedHbomProjectTypes,
59
+ hasHbomProjectType,
60
+ } from "../inventory/hbom.js";
61
+ import { mergeHostInventoryBoms } from "../inventory/hostTopology.js";
62
+ // Imported directly rather than through the utils.js barrel: purl validity is
63
+ // checked in a hot path and the barrel is already the root of several import
64
+ // cycles.
65
+ import { applyPurl, ociPurl } from "../inventory/purl.js";
66
+ import { table } from "../inventory/table.js";
67
+
68
+ export { summarizeAiInventory } from "../inventory/aiInventory.js";
69
+
70
+ import {
71
+ enrichOSComponentsWithTrustData,
72
+ executeOsQuery,
73
+ getOSPackages,
74
+ getPluginToolComponents,
75
+ } from "../managers/binary.js";
76
+ import {
77
+ addSkippedSrcFiles,
78
+ exportArchive,
79
+ exportImage,
80
+ getPkgPathList,
81
+ parseImageName,
82
+ } from "../managers/docker.js";
83
+ import {
84
+ buildBomNSData,
85
+ createAndroidBom,
86
+ createBinaryBom,
87
+ createDefaultParentComponent,
88
+ dedupeBom,
89
+ determineParentComponent,
90
+ } from "./bomAssembly.js";
91
+ import {
92
+ createAsarBom,
93
+ createCaxaBom,
94
+ createChromeExtensionBom,
95
+ createNodejsBom,
96
+ createVscodeExtensionBom,
97
+ getDirectAiInventoryType,
98
+ } from "./jsBom.js";
99
+ import {
100
+ createJarBom,
101
+ createJavaBom,
102
+ GRADLE_CACHE_DIR,
103
+ SBT_CACHE_DIR,
104
+ } from "./jvmBom.js";
105
+
106
+ export {
107
+ createAndroidBom,
108
+ createBinaryBom,
109
+ dedupeBom,
110
+ listComponents,
111
+ } from "./bomAssembly.js";
112
+ export {
113
+ createAsarBom,
114
+ createCaxaBom,
115
+ createChromeExtensionBom,
116
+ createNodejsBom,
117
+ createVscodeExtensionBom,
118
+ } from "./jsBom.js";
119
+ export { createJarBom, createJavaBom } from "./jvmBom.js";
120
+
121
+ import {
122
+ createCloudBuildBom,
123
+ createCryptoCertsBom,
124
+ createCsharpBom,
125
+ createGitHubBom,
126
+ createHelmBom,
127
+ createJenkinsBom,
128
+ createPHPBom,
129
+ createPythonBom,
130
+ createRubyBom,
131
+ } from "./managedBom.js";
132
+ import {
133
+ createCargoCacheBom,
134
+ createClojureBom,
135
+ createCocoaBom,
136
+ createCppBom,
137
+ createDartBom,
138
+ createElixirBom,
139
+ createGleamBom,
140
+ createGoBom,
141
+ createHaskellBom,
142
+ createNixBom,
143
+ createRustBom,
144
+ createSwiftBom,
145
+ createZigBom,
146
+ getCargoCacheDir,
147
+ } from "./nativeBom.js";
148
+
149
+ export {
150
+ createCloudBuildBom,
151
+ createCryptoCertsBom,
152
+ createCsharpBom,
153
+ createGitHubBom,
154
+ createHelmBom,
155
+ createJenkinsBom,
156
+ createPHPBom,
157
+ createPixiBom,
158
+ createPythonBom,
159
+ createRubyBom,
160
+ } from "./managedBom.js";
161
+ export {
162
+ createClojureBom,
163
+ createCocoaBom,
164
+ createCppBom,
165
+ createDartBom,
166
+ createElixirBom,
167
+ createGleamBom,
168
+ createGoBom,
169
+ createHaskellBom,
170
+ createNixBom,
171
+ createRustBom,
172
+ createSwiftBom,
173
+ createZigBom,
174
+ } from "./nativeBom.js";
175
+
176
+ const dirName = dirNameStr;
177
+
178
+ const isWin = _platform() === "win32";
179
+
180
+ let osQueries = {};
181
+ switch (_platform()) {
182
+ case "win32":
183
+ osQueries = JSON.parse(
184
+ readFileSync(join(dirName, "data", "queries-win.json"), "utf-8"),
185
+ );
186
+ break;
187
+ case "darwin":
188
+ osQueries = JSON.parse(
189
+ readFileSync(join(dirName, "data", "queries-darwin.json"), "utf-8"),
190
+ );
191
+ break;
192
+ default:
193
+ osQueries = JSON.parse(
194
+ readFileSync(join(dirName, "data", "queries.json"), "utf-8"),
195
+ );
196
+ break;
197
+ }
198
+
199
+ /**
200
+ * Function to create obom string for the current OS using osquery
201
+ *
202
+ * @param {string} _path to the project
203
+ * @param {Object} options Parse options from the cli
204
+ * @returns {Promise<Object>} Promise resolving to BOM object
205
+ */
206
+ export function createOSBom(_path, options) {
207
+ console.warn(
208
+ "About to generate OBOM for the current OS installation. This will take several minutes ...",
209
+ );
210
+ if (typeof process.getuid === "function" && process.getuid() !== 0) {
211
+ console.warn(
212
+ "Directories that are not readable by the current user will be skipped. Re-run with sudo for a complete OBOM.",
213
+ );
214
+ }
215
+ let pkgList = [];
216
+ let bomData = {};
217
+ let parentComponent = {};
218
+ let externalTools = getPluginToolComponents(["osquery"]);
219
+ for (const queryCategory of Object.keys(osQueries)) {
220
+ const queryObj = osQueries[queryCategory];
221
+ const results = executeOsQuery(queryObj.query);
222
+ const dlist = convertOSQueryResults(
223
+ queryCategory,
224
+ queryObj,
225
+ results,
226
+ false,
227
+ );
228
+ if (dlist?.length) {
229
+ if (!Object.keys(parentComponent).length) {
230
+ parentComponent = dlist.splice(0, 1)[0];
231
+ }
232
+ pkgList = pkgList.concat(
233
+ dlist.sort((a, b) => a.name.localeCompare(b.name)),
234
+ );
235
+ }
236
+ } // for
237
+ const hostTrustInventory = enrichOSComponentsWithTrustData(pkgList);
238
+ if (hostTrustInventory?.components?.length) {
239
+ pkgList = hostTrustInventory.components;
240
+ }
241
+ if (hostTrustInventory?.tools?.length) {
242
+ externalTools = externalTools.concat(hostTrustInventory.tools);
243
+ }
244
+ if (externalTools.length) {
245
+ options.tools = Array.from(
246
+ new Map(
247
+ externalTools.map((tool) => [tool["bom-ref"] || tool.name, tool]),
248
+ ).values(),
249
+ );
250
+ }
251
+ if (pkgList.length) {
252
+ bomData = buildBomNSData(options, pkgList, "", {
253
+ src: "",
254
+ filename: "",
255
+ parentComponent,
256
+ });
257
+ }
258
+ options.bomData = bomData;
259
+ options.multiProject = true;
260
+ options.installDeps = false;
261
+ options.parentComponent = parentComponent;
262
+ // Force the project type to os
263
+ options.projectType = ["os"];
264
+ options.lastWorkingDir = undefined;
265
+ options.allLayersExplodedDir = isWin ? "C:\\" : "";
266
+ const exportData = {
267
+ lastWorkingDir: undefined,
268
+ allLayersDir: options.allLayersExplodedDir,
269
+ allLayersExplodedDir: options.allLayersExplodedDir,
270
+ };
271
+ const pkgPathList = [];
272
+ if (options.deep) {
273
+ getPkgPathList(exportData, undefined);
274
+ }
275
+ return createMultiXBom(pkgPathList, options);
276
+ }
277
+
278
+ /**
279
+ * Function to create bom string for docker compose
280
+ *
281
+ * @param {string} path to the project
282
+ * @param {Object} options Parse options from the cli
283
+ * @returns {Promise<Object>} Promise resolving to BOM object
284
+ */
285
+ export async function createContainerSpecLikeBom(path, options) {
286
+ let services = [];
287
+ const ociSpecs = [];
288
+ let components = [];
289
+ let parentComponent = {};
290
+ let dependencies = [];
291
+ const doneimages = [];
292
+ const skippedImageSrcs = [];
293
+ const doneservices = [];
294
+ const origProjectType = options.projectType;
295
+ let dcFiles = getAllFiles(
296
+ path,
297
+ `${options.multiProject ? "**/" : ""}*.yml`,
298
+ options,
299
+ );
300
+ const dfFiles = getAllFiles(
301
+ path,
302
+ `${options.multiProject ? "**/" : ""}*Dockerfile*`,
303
+ options,
304
+ );
305
+ const bbPipelineFiles = getAllFiles(
306
+ path,
307
+ `${options.multiProject ? "**/" : ""}bitbucket-pipelines.yml`,
308
+ options,
309
+ );
310
+ const cfFiles = getAllFiles(
311
+ path,
312
+ `${options.multiProject ? "**/" : ""}*Containerfile*`,
313
+ options,
314
+ );
315
+ const yamlFiles = getAllFiles(
316
+ path,
317
+ `${options.multiProject ? "**/" : ""}*.yaml`,
318
+ options,
319
+ );
320
+ let oapiFiles = getAllFiles(
321
+ path,
322
+ `${options.multiProject ? "**/" : ""}open*.json`,
323
+ options,
324
+ );
325
+ const oapiYamlFiles = getAllFiles(
326
+ path,
327
+ `${options.multiProject ? "**/" : ""}open*.yaml`,
328
+ options,
329
+ );
330
+ if (oapiYamlFiles?.length) {
331
+ oapiFiles = oapiFiles.concat(oapiYamlFiles);
332
+ }
333
+ if (yamlFiles.length) {
334
+ dcFiles = dcFiles.concat(yamlFiles);
335
+ }
336
+ // Privado.ai json files
337
+ const privadoFiles = getAllFiles(path, ".privado/" + "*.json", options);
338
+
339
+ // Parse yaml manifest files, dockerfiles, containerfiles or bitbucket pipeline files
340
+ if (
341
+ dcFiles.length ||
342
+ dfFiles.length ||
343
+ cfFiles.length ||
344
+ bbPipelineFiles.length
345
+ ) {
346
+ for (const f of [...dcFiles, ...dfFiles, ...cfFiles, ...bbPipelineFiles]) {
347
+ if (DEBUG_MODE) {
348
+ console.log(`Parsing ${f}`);
349
+ }
350
+
351
+ const dData = readFileSync(f, { encoding: "utf-8" });
352
+ let imgList = [];
353
+ // parse yaml manifest files
354
+ if (f.endsWith("bitbucket-pipelines.yml")) {
355
+ imgList = parseBitbucketPipelinesFile(dData);
356
+ } else if (f.endsWith(".yml") || f.endsWith(".yaml")) {
357
+ imgList = parseContainerSpecData(dData);
358
+ } else {
359
+ imgList = parseContainerFile(dData);
360
+ }
361
+
362
+ if (imgList?.length) {
363
+ if (DEBUG_MODE) {
364
+ console.log("Images identified in", f, "are", imgList);
365
+ }
366
+ for (const img of imgList) {
367
+ const commonProperties = [
368
+ {
369
+ name: "internal:SrcFile",
370
+ value: f,
371
+ },
372
+ ];
373
+ if (img.image) {
374
+ commonProperties.push({
375
+ name: "oci:SrcImage",
376
+ value: img.image,
377
+ });
378
+ }
379
+ if (img.service) {
380
+ commonProperties.push({
381
+ name: "internal:ServiceName",
382
+ value: img.service,
383
+ });
384
+ }
385
+
386
+ // img could have .service, .ociSpec or .image
387
+ if (img.ociSpec) {
388
+ console.log(
389
+ `NOTE: ${img.ociSpec} needs to built using docker or podman and referred with a name to get included in this SBOM.`,
390
+ );
391
+ ociSpecs.push({
392
+ group: "",
393
+ name: img.ociSpec,
394
+ version: "latest",
395
+ properties: commonProperties,
396
+ });
397
+ }
398
+ if (img.service) {
399
+ let version = "latest";
400
+ let name = img.service;
401
+ if (img.service.includes(":")) {
402
+ const tmpA = img.service.split(":");
403
+ if (tmpA && tmpA.length === 2) {
404
+ name = tmpA[0];
405
+ version = tmpA[1];
406
+ }
407
+ }
408
+ const servbomRef = `urn:service:${name}:${version}`;
409
+ if (!doneservices.includes(servbomRef)) {
410
+ services.push({
411
+ "bom-ref": servbomRef,
412
+ name: name,
413
+ version: version,
414
+ group: "",
415
+ properties: commonProperties,
416
+ });
417
+ doneservices.push(servbomRef);
418
+ }
419
+ }
420
+ if (img.image) {
421
+ if (doneimages.includes(img.image)) {
422
+ if (DEBUG_MODE) {
423
+ console.log(
424
+ "Skipping image as it's already been processed",
425
+ img.image,
426
+ );
427
+ }
428
+
429
+ skippedImageSrcs.push({ image: img.image, src: f });
430
+
431
+ continue;
432
+ }
433
+ if (DEBUG_MODE) {
434
+ console.log(`Parsing image ${img.image}`);
435
+ }
436
+ const imageObj = parseImageName(img.image);
437
+
438
+ const pkg = {
439
+ name: imageObj.name,
440
+ group: imageObj.group,
441
+ version:
442
+ imageObj.tag ||
443
+ (imageObj.digest ? `sha256:${imageObj.digest}` : "latest"),
444
+ qualifiers: {},
445
+ properties: commonProperties,
446
+ type: "container",
447
+ };
448
+ if (imageObj.registry) {
449
+ // Skip adding repository_url if the registry or repo contains variables.
450
+ if (
451
+ imageObj.registry.includes("${") ||
452
+ imageObj.repo.includes("${")
453
+ ) {
454
+ if (DEBUG_MODE) {
455
+ console.warn(
456
+ "Skipping adding repository_url qualifier as it contains variables, which are not yet supported",
457
+ img.image,
458
+ );
459
+ }
460
+ } else {
461
+ pkg["qualifiers"]["repository_url"] =
462
+ `${imageObj.registry}/${imageObj.repo}`;
463
+ }
464
+ }
465
+ if (imageObj.platform) {
466
+ pkg["qualifiers"]["platform"] = imageObj.platform;
467
+ }
468
+ if (imageObj.tag) {
469
+ pkg["qualifiers"]["tag"] = imageObj.tag;
470
+ }
471
+ // Create an entry for the oci image
472
+ const imageBomData = buildBomNSData(options, [pkg], "oci", {
473
+ src: img.image,
474
+ filename: f,
475
+ nsMapping: {},
476
+ });
477
+ if (imageBomData?.bomJson?.components) {
478
+ components = components.concat(imageBomData.bomJson.components);
479
+ }
480
+ const bomData = await createBom(img.image, {
481
+ specVersion: options.specVersion,
482
+ projectType: ["oci"],
483
+ });
484
+ doneimages.push(img.image);
485
+ if (bomData) {
486
+ if (bomData.components?.length) {
487
+ // Inject properties
488
+ for (const co of bomData.components) {
489
+ co.properties = commonProperties;
490
+ }
491
+ components = components.concat(bomData.components);
492
+ }
493
+ }
494
+ } // img.image
495
+ } // for img
496
+ }
497
+ } // for
498
+
499
+ // Add additional SrcFile property to skipped image components
500
+ addSkippedSrcFiles(skippedImageSrcs, components);
501
+ } // if
502
+ // Parse openapi files
503
+ if (oapiFiles.length) {
504
+ for (const af of oapiFiles) {
505
+ if (DEBUG_MODE) {
506
+ console.log(`Parsing ${af}`);
507
+ }
508
+ const oaData = readFileSync(af, { encoding: "utf-8" });
509
+ const servlist = parseOpenapiSpecData(oaData);
510
+ if (servlist?.length) {
511
+ // Inject SrcFile property
512
+ for (const se of servlist) {
513
+ se.properties = [
514
+ {
515
+ name: "internal:SrcFile",
516
+ value: af,
517
+ },
518
+ ];
519
+ }
520
+ services = mergeServices(services, servlist);
521
+ }
522
+ }
523
+ }
524
+ // Parse privado files
525
+ if (privadoFiles.length) {
526
+ console.log(
527
+ "Enriching your SBOM with information from privado.ai scan reports",
528
+ );
529
+ let rows = [["Classification", "Flow"]];
530
+ const config = {
531
+ header: {
532
+ alignment: "center",
533
+ content: "Data Privacy Insights from privado.ai",
534
+ },
535
+ columns: [{ width: 50 }, { width: 10 }],
536
+ };
537
+ for (const f of privadoFiles) {
538
+ if (DEBUG_MODE) {
539
+ console.log(`Parsing ${f}`);
540
+ }
541
+ const servlist = parsePrivadoFile(f);
542
+ services = mergeServices(services, servlist);
543
+ if (servlist.length) {
544
+ const aservice = servlist[0];
545
+ if (aservice.data) {
546
+ for (const d of aservice.data) {
547
+ rows.push([d.classification, d.flow]);
548
+ }
549
+ console.log(table(rows, config));
550
+ }
551
+ if (aservice.endpoints) {
552
+ rows = [["Leaky Endpoints"]];
553
+ for (const e of aservice.endpoints) {
554
+ rows.push([e]);
555
+ }
556
+ console.log(
557
+ table(rows, {
558
+ columnDefault: {
559
+ width: 50,
560
+ },
561
+ }),
562
+ );
563
+ }
564
+ }
565
+ }
566
+ }
567
+ if (origProjectType?.includes("universal")) {
568
+ // In case of universal, repeat to collect multiX Boms
569
+ const mbomData = await createMultiXBom(path, {
570
+ ...options,
571
+ projectType: [],
572
+ multiProject: true,
573
+ excludeType: options.excludeType,
574
+ });
575
+ if (mbomData) {
576
+ if (mbomData.components?.length) {
577
+ components = components.concat(mbomData.components);
578
+ }
579
+ // We need to retain the parentComponent. See #527
580
+ // Parent component returned by multi X search is usually good
581
+ parentComponent = mbomData.parentComponent;
582
+ options.parentComponent = parentComponent;
583
+ if (mbomData.bomJson) {
584
+ if (mbomData.bomJson.dependencies) {
585
+ dependencies = mergeDependencies(
586
+ dependencies,
587
+ mbomData.bomJson.dependencies,
588
+ parentComponent,
589
+ );
590
+ }
591
+ if (mbomData.bomJson.services) {
592
+ services = mergeServices(services, mbomData.bomJson.services);
593
+ }
594
+ }
595
+ if (DEBUG_MODE) {
596
+ console.log(
597
+ `Received ${components.length} unfiltered components ${dependencies.length} dependencies so far.`,
598
+ );
599
+ }
600
+ }
601
+ }
602
+ options.services = mergeServices([], services);
603
+ options.ociSpecs = ociSpecs;
604
+ return dedupeBom(options, components, parentComponent, dependencies);
605
+ }
606
+
607
+ /**
608
+ * Decide how many paths of a multi-path scan may be inspected at once.
609
+ *
610
+ * A container image contributes around twenty rootfs paths, each of which is
611
+ * offered to every ecosystem, so overlapping them shortens the scan. Two
612
+ * situations stay sequential. A single path has nothing to overlap. Dry run and
613
+ * debug mode narrate their progress through one activity context and one log,
614
+ * so their output describes the paths one at a time.
615
+ *
616
+ * The bound follows the processor count and stops at eight, matching the worker
617
+ * pool. Every path also resolves packages over the network, where requests are
618
+ * already batched per host, so a registry sees the product of the two bounds.
619
+ *
620
+ * @param {string[]} pathList Paths about to be scanned
621
+ * @returns {number} Number of paths to scan at once
622
+ */
623
+ function pathScanConcurrency(pathList) {
624
+ if (!pathList || pathList.length < 2 || isDryRun || DEBUG_MODE) {
625
+ return 1;
626
+ }
627
+ const defaultLimit = Math.min(availableParallelism() || 4, 8);
628
+ const configured = Number.parseInt(
629
+ readEnvironmentVariable("CDXGEN_MAX_PATH_SCANS") || String(defaultLimit),
630
+ 10,
631
+ );
632
+ const limit =
633
+ Number.isNaN(configured) || configured < 1 ? defaultLimit : configured;
634
+ return Math.min(pathList.length, limit);
635
+ }
636
+
637
+ /**
638
+ * Function to create bom string for all languages
639
+ *
640
+ * @param {string[]} pathList list of to the project
641
+ * @param {Object} options Parse options from the cli
642
+ * @returns {Promise<Object>} Promise resolving to BOM object
643
+ */
644
+ /**
645
+ * Join non-zero counts into a phase summary.
646
+ *
647
+ * Each entry carries its own plural form rather than having one appended, so
648
+ * nouns like "shared library" read correctly.
649
+ *
650
+ * @param {Array<[number, string, string]>} entries Count, singular, and plural
651
+ * @returns {string} Summary such as "412 OS packages, 3 services"
652
+ */
653
+ export function summarizeCounts(entries) {
654
+ return entries
655
+ .filter(([count]) => count > 0)
656
+ .map(
657
+ ([count, singular, plural]) =>
658
+ `${count} ${count === 1 ? singular : plural}`,
659
+ )
660
+ .join(", ");
661
+ }
662
+
663
+ /**
664
+ * Summarize components by purl type, so a scan reports "412 npm, 88 pypi"
665
+ * rather than an anonymous total.
666
+ *
667
+ * @param {object[]} components Components carrying purls
668
+ * @returns {string} Comma-separated counts, busiest type first
669
+ */
670
+ export function summarizePurlTypes(components) {
671
+ const counts = new Map();
672
+ for (const component of components) {
673
+ const purlType = `${component?.purl || ""}`.split("/")[0].slice(4);
674
+ const key = purlType || component?.type || "component";
675
+ counts.set(key, (counts.get(key) || 0) + 1);
676
+ }
677
+ return [...counts.entries()]
678
+ .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
679
+ .map(([type, count]) => `${count} ${type}`)
680
+ .join(", ");
681
+ }
682
+
683
+ /**
684
+ * Generates BOMs across multiple project types and/or paths, then merges and
685
+ * deduplicates the results into a single BOM namespace data object. Handles
686
+ * OCI/container inventory, per-path scans, formulation accumulation, and
687
+ * parent-component reconciliation.
688
+ *
689
+ * @param {string|string[]} pathList Comma-separated string or array of paths
690
+ * @param {object} options CLI options
691
+ * @returns {Promise<object>} Promise resolving to a deduplicated BOM namespace
692
+ * data object (components, dependencies, bomJson, parentComponent, etc.)
693
+ */
694
+ export async function createMultiXBom(pathList, options) {
695
+ let components = [];
696
+ let dependencies = [];
697
+ let bomData;
698
+ let formulationList = [];
699
+ let parentComponent = determineParentComponent(options) || {};
700
+ let parentSubComponents = [];
701
+ const setProjectTypeActivityContext = (projectType, sourcePath) => {
702
+ setActivityContext({
703
+ projectType,
704
+ sourcePath,
705
+ });
706
+ };
707
+ options.createMultiXBom = true;
708
+ // Convert single path to an array
709
+ if (!Array.isArray(pathList)) {
710
+ pathList = pathList.split(",");
711
+ }
712
+ if (
713
+ options.projectType &&
714
+ hasAnyProjectType(["oci"], options, false) &&
715
+ options.allLayersExplodedDir
716
+ ) {
717
+ const osPhase = ui.phase("Inventorying OS packages");
718
+ const {
719
+ osPackages,
720
+ osPackageFiles,
721
+ dependenciesList,
722
+ allTypes,
723
+ bundledSdks,
724
+ bundledRuntimes,
725
+ binPaths,
726
+ executables,
727
+ sharedLibs,
728
+ services,
729
+ tools,
730
+ } = await getOSPackages(
731
+ options.allLayersExplodedDir,
732
+ options.exportData?.inspectData?.Config,
733
+ options,
734
+ );
735
+ osPhase.succeed(
736
+ summarizeCounts([
737
+ [osPackages.length, "OS package", "OS packages"],
738
+ [osPackageFiles?.length, "package-owned file", "package-owned files"],
739
+ [executables?.length, "executable", "executables"],
740
+ [sharedLibs?.length, "shared library", "shared libraries"],
741
+ [services?.length, "service", "services"],
742
+ ]),
743
+ );
744
+ // TODO: Need to test these with docker-compose type where multiple images could have different values.
745
+ // This is also clearly misusing options, which must become immutable at some point.
746
+ options.bundledSdks = bundledSdks;
747
+ options.bundledRuntimes = bundledRuntimes;
748
+ options.binPaths = binPaths;
749
+ options.unpackagedExecutableCount = executables?.length || 0;
750
+ options.unpackagedSharedLibraryCount = sharedLibs?.length || 0;
751
+ if (DEBUG_MODE) {
752
+ console.log(
753
+ `**OS**: Found ${osPackages.length} OS packages, ${osPackageFiles?.length} package-owned files, ${executables?.length} unpackaged executables, ${sharedLibs.length} unpackaged shared libraries, and ${services?.length || 0} packaged services at ${options.allLayersExplodedDir}`,
754
+ );
755
+ }
756
+ if (osPackages.length) {
757
+ thoughtLog(
758
+ `I found ${osPackages.length} OS packages, ${osPackageFiles?.length || 0} package-owned files, and ${services?.length || 0} packaged services at ${options.allLayersExplodedDir}`,
759
+ );
760
+ } else if (executables?.length || sharedLibs?.length) {
761
+ thoughtLog(
762
+ `I couldn't find any OS packages, but I found ${executables.length} executables and ${sharedLibs.length} shared libraries at ${options.allLayersExplodedDir}. Perhaps the binary plugin wasn't available, or the architecture is unsupported.`,
763
+ );
764
+ } else {
765
+ thoughtLog(
766
+ `I couldn't find any OS packages at ${options.allLayersExplodedDir}. Perhaps the binary plugin wasn't available, or the architecture is unsupported.`,
767
+ );
768
+ }
769
+ if (allTypes?.length) {
770
+ options.allOSComponentTypes = allTypes;
771
+ }
772
+ if (tools?.length) {
773
+ options.tools = (
774
+ Array.isArray(options.tools)
775
+ ? options.tools
776
+ : options.tools?.components || []
777
+ ).concat(tools);
778
+ }
779
+ components = components.concat(osPackages);
780
+ components = components.concat(osPackageFiles || []);
781
+ components = components.concat(executables);
782
+ components = components.concat(sharedLibs);
783
+ if (dependenciesList?.length) {
784
+ dependencies = mergeDependencies(dependencies, dependenciesList);
785
+ }
786
+ if (services?.length) {
787
+ options.services = mergeServices(options.services || [], services);
788
+ }
789
+ if (parentComponent && Object.keys(parentComponent).length) {
790
+ // Make the parent oci image depend on all os components
791
+ const parentDependsOn = new Set(
792
+ osPackages.concat(osPackageFiles || []).map((p) => p["bom-ref"]),
793
+ );
794
+ dependencies.splice(0, 0, {
795
+ ref: parentComponent["bom-ref"],
796
+ dependsOn: Array.from(parentDependsOn).sort(),
797
+ });
798
+ }
799
+ }
800
+ if (hasAnyProjectType(["os"], options, false) && options.bomData) {
801
+ bomData = options.bomData;
802
+ if (bomData?.bomJson?.components) {
803
+ if (DEBUG_MODE) {
804
+ console.log(`Found ${bomData.bomJson.components.length} OS components`);
805
+ }
806
+ if (bomData.bomJson.components.length) {
807
+ thoughtLog(
808
+ `I found ${bomData.bomJson.components.length} OS packages 😎.`,
809
+ );
810
+ }
811
+ components = components.concat(bomData.bomJson.components);
812
+ }
813
+ }
814
+ const sharedOptions = options;
815
+ // The exploded image layers are written once by the extractor and only read
816
+ // from here on, so repeated walks of them can share one view of the tree.
817
+ setDirWalkCacheRoot(options.allLayersExplodedDir);
818
+ const scanOnePath = async (path) => {
819
+ // Each path accumulates into its own lists and its own view of options, so
820
+ // that legs which record a parent component or a tool cannot overwrite
821
+ // another path's. The lists are merged below in pathList order.
822
+ const options = { ...sharedOptions };
823
+ let bomData;
824
+ let components = [];
825
+ let dependencies = [];
826
+ let parentSubComponents = [];
827
+ setActivityContext({
828
+ projectType: Array.isArray(options.projectType)
829
+ ? options.projectType.join(",")
830
+ : options.projectType,
831
+ sourcePath: path,
832
+ });
833
+ recordActivity({
834
+ kind: "read",
835
+ reason:
836
+ "Scanning project path for supported languages and package managers.",
837
+ status: "completed",
838
+ target: path,
839
+ });
840
+ if (DEBUG_MODE) {
841
+ console.log("Scanning", path);
842
+ }
843
+ if (pathList.length > 2) {
844
+ thoughtLog(`Let's thoroughly check the path ${path}.`);
845
+ }
846
+ // Node.js and AI inventory
847
+ if (
848
+ hasAnyProjectType(["oci", "js"], options) ||
849
+ hasAnyProjectType(["mcp", "ai-skill", "ai"], options) ||
850
+ getDirectAiInventoryType(path, options)
851
+ ) {
852
+ const exactAiInventoryType = getDirectAiInventoryType(path, options);
853
+ if (!hasAnyProjectType(["oci"], options, false)) {
854
+ if (exactAiInventoryType === "mcp") {
855
+ thoughtLog(
856
+ "**MCP**: Looking for MCP services, MCP configs, and related AI control-plane artifacts.",
857
+ );
858
+ } else if (exactAiInventoryType === "ai") {
859
+ thoughtLog(
860
+ "**AI-BOM**: Looking for AI models, direct model metadata, pedigree, quantization, and operator-facing AI context.",
861
+ );
862
+ } else if (exactAiInventoryType === "ai-skill") {
863
+ thoughtLog(
864
+ "**AI-SKILL**: Looking for AI instruction, skill, and agent-definition files that can influence build or release flows.",
865
+ );
866
+ } else {
867
+ thoughtLog(
868
+ "**JS**: Now looking for JavaScript projects (npm, yarn, pnpm) and files.",
869
+ );
870
+ }
871
+ }
872
+ setProjectTypeActivityContext(exactAiInventoryType || "js", path);
873
+ bomData = await createNodejsBom(path, options);
874
+ if (bomData?.bomJson?.components?.length) {
875
+ if (exactAiInventoryType) {
876
+ thoughtLog(
877
+ `I found ${bomData.bomJson.components.length} ${exactAiInventoryType} component(s). Let's keep looking.`,
878
+ );
879
+ } else {
880
+ thoughtLog(
881
+ `I found ${bomData.bomJson.components.length} npm packages. Let's keep looking.`,
882
+ );
883
+ }
884
+ if (DEBUG_MODE) {
885
+ console.log(
886
+ `Found ${bomData.bomJson.components.length} ${exactAiInventoryType || "npm"} components at ${path}`,
887
+ );
888
+ }
889
+ components = components.concat(bomData.bomJson.components);
890
+ dependencies = mergeDependencies(
891
+ dependencies,
892
+ bomData.bomJson.dependencies,
893
+ );
894
+ if (bomData?.bomJson?.services?.length) {
895
+ options.services = mergeServices(
896
+ options.services || [],
897
+ bomData.bomJson.services,
898
+ );
899
+ }
900
+ if (
901
+ bomData.parentComponent &&
902
+ Object.keys(bomData.parentComponent).length
903
+ ) {
904
+ parentSubComponents.push(bomData.parentComponent);
905
+ }
906
+ // Retain metadata.component.components
907
+ if (bomData.parentComponent.components?.length) {
908
+ parentSubComponents = parentSubComponents.concat(
909
+ bomData.parentComponent.components,
910
+ );
911
+ delete bomData.parentComponent.components;
912
+ }
913
+ }
914
+ }
915
+ // Java
916
+ if (hasAnyProjectType(["oci", "java"], options)) {
917
+ if (!hasAnyProjectType(["oci"], options, false)) {
918
+ thoughtLog(
919
+ "**JAVA**: Looking for Java projects (e.g., Maven, Gradle, SBT). I hope all configurations—from Java version to individual build settings—are correctly aligned.",
920
+ );
921
+ }
922
+ setProjectTypeActivityContext("java", path);
923
+ bomData = await createJavaBom(path, options);
924
+ if (bomData?.bomJson?.components?.length) {
925
+ thoughtLog(
926
+ `I found ${bomData.bomJson.components.length} java packages.`,
927
+ );
928
+ if (DEBUG_MODE) {
929
+ console.log(
930
+ `Found ${bomData.bomJson.components.length} java packages at ${path}`,
931
+ );
932
+ }
933
+ components = components.concat(bomData.bomJson.components);
934
+ dependencies = mergeDependencies(
935
+ dependencies,
936
+ bomData.bomJson.dependencies,
937
+ );
938
+ if (
939
+ bomData.parentComponent &&
940
+ Object.keys(bomData.parentComponent).length
941
+ ) {
942
+ parentSubComponents.push(bomData.parentComponent);
943
+ }
944
+ // Retain metadata.component.components, but add duplicates to the list of current components
945
+ // and removing them from metadata.component.components -- the components are merged later
946
+ if (bomData.parentComponent.components?.length) {
947
+ let bomSubComponents = bomData.parentComponent.components;
948
+ if (
949
+ !["false", "0"].includes(
950
+ readEnvironmentVariable("GRADLE_RESOLVE_FROM_NODE"),
951
+ )
952
+ ) {
953
+ thoughtLog(
954
+ "Wait, the user wants me to resolve gradle projects from npm.",
955
+ );
956
+ const allRefs = components.map((c) => c["bom-ref"]);
957
+ const duplicateComponents = bomSubComponents.filter((c) =>
958
+ allRefs.includes(c["bom-ref"]),
959
+ );
960
+ components = components.concat(duplicateComponents);
961
+ const duplicateComponentRefs = duplicateComponents.map(
962
+ (c) => c["bom-ref"],
963
+ );
964
+ bomSubComponents = bomSubComponents.filter(
965
+ (c) => !duplicateComponentRefs.includes(c["bom-ref"]),
966
+ );
967
+ }
968
+ parentSubComponents = parentSubComponents.concat(bomSubComponents);
969
+ delete bomData.parentComponent.components;
970
+ }
971
+ }
972
+ }
973
+ if (hasAnyProjectType(["oci", "py"], options)) {
974
+ if (!hasAnyProjectType(["oci"], options, false)) {
975
+ thoughtLog(
976
+ "**PYTHON**: Looking for Python projects with package managers such as pip, poetry, uv, etc. Wish me good luck!",
977
+ );
978
+ }
979
+ if (
980
+ readEnvironmentVariable("CDXGEN_IN_CONTAINER") !== "true" &&
981
+ pathList.length <= 2
982
+ ) {
983
+ thoughtLog(
984
+ "I'm running in a non-container environment. Let's hope the correct build tools are available ✌️.",
985
+ );
986
+ }
987
+ setProjectTypeActivityContext("py", path);
988
+ bomData = await createPythonBom(path, options);
989
+ if (bomData?.bomJson?.components?.length) {
990
+ thoughtLog(
991
+ `I found ${bomData.bomJson.components.length} python packages.`,
992
+ );
993
+ if (DEBUG_MODE) {
994
+ console.log(
995
+ `Found ${bomData.bomJson.components.length} python packages at ${path}`,
996
+ );
997
+ }
998
+ components = components.concat(bomData.bomJson.components);
999
+ dependencies = mergeDependencies(
1000
+ dependencies,
1001
+ bomData.bomJson.dependencies,
1002
+ );
1003
+ if (
1004
+ bomData.parentComponent &&
1005
+ Object.keys(bomData.parentComponent).length
1006
+ ) {
1007
+ parentSubComponents.push(bomData.parentComponent);
1008
+ }
1009
+ }
1010
+ if (bomData?.formulationList?.length) {
1011
+ formulationList = formulationList.concat(bomData.formulationList);
1012
+ }
1013
+ }
1014
+ if (hasAnyProjectType(["oci", "go"], options)) {
1015
+ if (!hasAnyProjectType(["oci"], options, false)) {
1016
+ thoughtLog(
1017
+ "**GO**: Looking for go projects. I need to be cautious about purl namespaces and potential failures with the 'go list' command.",
1018
+ );
1019
+ }
1020
+ setProjectTypeActivityContext("go", path);
1021
+ bomData = await createGoBom(path, options);
1022
+ if (bomData?.bomJson?.components?.length) {
1023
+ thoughtLog(`I found ${bomData.bomJson.components.length} go packages.`);
1024
+ if (DEBUG_MODE) {
1025
+ console.log(
1026
+ `Found ${bomData.bomJson.components.length} go packages at ${path}`,
1027
+ );
1028
+ }
1029
+ components = components.concat(bomData.bomJson.components);
1030
+ dependencies = mergeDependencies(
1031
+ dependencies,
1032
+ bomData.bomJson.dependencies,
1033
+ );
1034
+ if (
1035
+ bomData.parentComponent &&
1036
+ Object.keys(bomData.parentComponent).length
1037
+ ) {
1038
+ parentSubComponents.push(bomData.parentComponent);
1039
+ }
1040
+ }
1041
+ }
1042
+ if (hasAnyProjectType(["oci", "rust"], options)) {
1043
+ if (!hasAnyProjectType(["oci"], options, false)) {
1044
+ thoughtLog(
1045
+ "**RUST**: Let's search for Cargo/Rust projects. Should I warn the user that we don't support Cargo 'features' and native dependencies, which may lead to both false positives and false negatives? 🤔?",
1046
+ );
1047
+ }
1048
+ setProjectTypeActivityContext("rust", path);
1049
+ bomData = await createRustBom(path, options);
1050
+ if (bomData?.bomJson?.components?.length) {
1051
+ thoughtLog(
1052
+ `I found ${bomData.bomJson.components.length} rust packages.`,
1053
+ );
1054
+ if (DEBUG_MODE) {
1055
+ console.log(
1056
+ `Found ${bomData.bomJson.components.length} rust packages at ${path}`,
1057
+ );
1058
+ }
1059
+ components = components.concat(bomData.bomJson.components);
1060
+ dependencies = mergeDependencies(
1061
+ dependencies,
1062
+ bomData.bomJson.dependencies,
1063
+ );
1064
+ if (
1065
+ bomData.parentComponent &&
1066
+ Object.keys(bomData.parentComponent).length
1067
+ ) {
1068
+ parentSubComponents.push(bomData.parentComponent);
1069
+ }
1070
+ // Retain metadata.component.components
1071
+ if (bomData.parentComponent?.components?.length) {
1072
+ parentSubComponents = parentSubComponents.concat(
1073
+ bomData.parentComponent.components,
1074
+ );
1075
+ delete bomData.parentComponent.components;
1076
+ }
1077
+ }
1078
+ }
1079
+ if (hasAnyProjectType(["oci", "php"], options)) {
1080
+ if (!hasAnyProjectType(["oci"], options, false)) {
1081
+ thoughtLog(
1082
+ "**PHP**: About to search for Composer-based projects. I hope lock files are available; otherwise, the 'composer install' command might fail for various reasons.",
1083
+ );
1084
+ }
1085
+ setProjectTypeActivityContext("php", path);
1086
+ bomData = createPHPBom(path, options);
1087
+ if (bomData?.bomJson?.components?.length) {
1088
+ thoughtLog(
1089
+ `I found ${bomData.bomJson.components.length} php packages.`,
1090
+ );
1091
+ if (DEBUG_MODE) {
1092
+ console.log(
1093
+ `Found ${bomData.bomJson.components.length} php packages at ${path}`,
1094
+ );
1095
+ }
1096
+ components = components.concat(bomData.bomJson.components);
1097
+ dependencies = mergeDependencies(
1098
+ dependencies,
1099
+ bomData.bomJson.dependencies,
1100
+ );
1101
+ if (
1102
+ bomData.parentComponent &&
1103
+ Object.keys(bomData.parentComponent).length
1104
+ ) {
1105
+ parentSubComponents.push(bomData.parentComponent);
1106
+ }
1107
+ // Retain metadata.component.components
1108
+ if (bomData.parentComponent?.components?.length) {
1109
+ parentSubComponents = parentSubComponents.concat(
1110
+ bomData.parentComponent.components,
1111
+ );
1112
+ delete bomData.parentComponent.components;
1113
+ }
1114
+ }
1115
+ }
1116
+ if (hasAnyProjectType(["oci", "ruby"], options)) {
1117
+ if (!hasAnyProjectType(["oci"], options, false)) {
1118
+ thoughtLog(
1119
+ "**RUBY**: Are there any Ruby projects in this path? There's only one way to know.",
1120
+ );
1121
+ }
1122
+ setProjectTypeActivityContext("ruby", path);
1123
+ bomData = await createRubyBom(path, options);
1124
+ if (bomData?.bomJson?.components?.length) {
1125
+ thoughtLog(
1126
+ `We got ${bomData.bomJson.components.length} ruby packages.`,
1127
+ );
1128
+ if (DEBUG_MODE) {
1129
+ console.log(
1130
+ `Found ${bomData.bomJson.components.length} ruby packages at ${path}`,
1131
+ );
1132
+ }
1133
+ components = components.concat(bomData.bomJson.components);
1134
+ dependencies = mergeDependencies(
1135
+ dependencies,
1136
+ bomData.bomJson.dependencies,
1137
+ bomData.parentComponent,
1138
+ );
1139
+ if (
1140
+ bomData.parentComponent &&
1141
+ Object.keys(bomData.parentComponent).length
1142
+ ) {
1143
+ parentSubComponents.push(bomData.parentComponent);
1144
+ }
1145
+ // Retain metadata.component.components
1146
+ if (bomData.parentComponent?.components?.length) {
1147
+ parentSubComponents = parentSubComponents.concat(
1148
+ bomData.parentComponent.components,
1149
+ );
1150
+ delete bomData.parentComponent.components;
1151
+ }
1152
+ }
1153
+ }
1154
+ if (hasAnyProjectType(["oci", "csharp"], options)) {
1155
+ if (!hasAnyProjectType(["oci"], options, false)) {
1156
+ thoughtLog("**CSHARP**: What about csharp and fsharp projects?");
1157
+ }
1158
+ setProjectTypeActivityContext("csharp", path);
1159
+ bomData = await createCsharpBom(path, options);
1160
+ if (bomData?.bomJson?.components?.length) {
1161
+ thoughtLog(
1162
+ `There are ${bomData.bomJson.components.length} csharp packages.`,
1163
+ );
1164
+ if (DEBUG_MODE) {
1165
+ console.log(
1166
+ `Found ${bomData.bomJson.components.length} csharp packages at ${path}`,
1167
+ );
1168
+ }
1169
+ components = components.concat(bomData.bomJson.components);
1170
+ dependencies = mergeDependencies(
1171
+ dependencies,
1172
+ bomData.bomJson.dependencies,
1173
+ );
1174
+ if (
1175
+ bomData.parentComponent &&
1176
+ Object.keys(bomData.parentComponent).length
1177
+ ) {
1178
+ parentSubComponents.push(bomData.parentComponent);
1179
+ }
1180
+ // Retain metadata.component.components
1181
+ if (bomData.parentComponent?.components?.length) {
1182
+ parentSubComponents = parentSubComponents.concat(
1183
+ bomData.parentComponent.components,
1184
+ );
1185
+ delete bomData.parentComponent.components;
1186
+ }
1187
+ }
1188
+ }
1189
+ if (hasAnyProjectType(["oci", "dart"], options)) {
1190
+ if (!hasAnyProjectType(["oci"], options, false)) {
1191
+ thoughtLog(
1192
+ "**DART**: Looking for Dart projects. These are rare ones. Should I inform the user that they can pass the types argument via the command-line to speed things up?",
1193
+ );
1194
+ }
1195
+ setProjectTypeActivityContext("dart", path);
1196
+ bomData = await createDartBom(path, options);
1197
+ if (bomData?.bomJson?.components?.length) {
1198
+ thoughtLog(
1199
+ `I found ${bomData.bomJson.components.length} pub packages.`,
1200
+ );
1201
+ if (DEBUG_MODE) {
1202
+ console.log(
1203
+ `Found ${bomData.bomJson.components.length} pub packages at ${path}`,
1204
+ );
1205
+ }
1206
+ components = components.concat(bomData.bomJson.components);
1207
+ dependencies = mergeDependencies(
1208
+ dependencies,
1209
+ bomData.bomJson.dependencies,
1210
+ );
1211
+ if (
1212
+ bomData.parentComponent &&
1213
+ Object.keys(bomData.parentComponent).length
1214
+ ) {
1215
+ parentSubComponents.push(bomData.parentComponent);
1216
+ }
1217
+ }
1218
+ }
1219
+ if (hasAnyProjectType(["oci", "haskell"], options)) {
1220
+ if (!hasAnyProjectType(["oci"], options, false)) {
1221
+ thoughtLog(
1222
+ "**HASKELL**: Looking for Haskell projects. They're rarely encountered.",
1223
+ );
1224
+ }
1225
+ setProjectTypeActivityContext("haskell", path);
1226
+ bomData = createHaskellBom(path, options);
1227
+ if (bomData?.bomJson?.components?.length) {
1228
+ thoughtLog(
1229
+ `I found ${bomData.bomJson.components.length} hackage packages.`,
1230
+ );
1231
+ if (DEBUG_MODE) {
1232
+ console.log(
1233
+ `Found ${bomData.bomJson.components.length} hackage packages at ${path}`,
1234
+ );
1235
+ }
1236
+ components = components.concat(bomData.bomJson.components);
1237
+ dependencies = mergeDependencies(
1238
+ dependencies,
1239
+ bomData.bomJson.dependencies,
1240
+ );
1241
+ if (
1242
+ bomData.parentComponent &&
1243
+ Object.keys(bomData.parentComponent).length
1244
+ ) {
1245
+ parentSubComponents.push(bomData.parentComponent);
1246
+ }
1247
+ }
1248
+ }
1249
+ if (hasAnyProjectType(["oci", "elixir"], options)) {
1250
+ if (!hasAnyProjectType(["oci"], options, false)) {
1251
+ thoughtLog(
1252
+ "**ELIXIR**: Looking for Elixir projects—they're quite rare as well.",
1253
+ );
1254
+ }
1255
+ setProjectTypeActivityContext("elixir", path);
1256
+ bomData = createElixirBom(path, options);
1257
+ if (bomData?.bomJson?.components?.length) {
1258
+ thoughtLog(
1259
+ `I found ${bomData.bomJson.components.length} mix packages.`,
1260
+ );
1261
+ if (DEBUG_MODE) {
1262
+ console.log(
1263
+ `Found ${bomData.bomJson.components.length} mix packages at ${path}`,
1264
+ );
1265
+ }
1266
+ components = components.concat(bomData.bomJson.components);
1267
+ dependencies = mergeDependencies(
1268
+ dependencies,
1269
+ bomData.bomJson.dependencies,
1270
+ );
1271
+ if (
1272
+ bomData.parentComponent &&
1273
+ Object.keys(bomData.parentComponent).length
1274
+ ) {
1275
+ parentSubComponents.push(bomData.parentComponent);
1276
+ }
1277
+ }
1278
+ }
1279
+ if (hasAnyProjectType(["oci", "c"], options)) {
1280
+ if (!hasAnyProjectType(["oci"], options, false)) {
1281
+ thoughtLog(
1282
+ "**C/C++**: Looking for C/C++ projects. Should I warn the user that the generated SBOM might have low accuracy and contain errors?",
1283
+ );
1284
+ }
1285
+ setProjectTypeActivityContext("c", path);
1286
+ bomData = createCppBom(path, options);
1287
+ if (bomData?.bomJson?.components?.length) {
1288
+ thoughtLog(
1289
+ `I found ${bomData.bomJson.components.length} cpp packages.`,
1290
+ );
1291
+ if (DEBUG_MODE) {
1292
+ console.log(
1293
+ `Found ${bomData.bomJson.components.length} cpp packages at ${path}`,
1294
+ );
1295
+ }
1296
+ components = components.concat(bomData.bomJson.components);
1297
+ dependencies = mergeDependencies(
1298
+ dependencies,
1299
+ bomData.bomJson.dependencies,
1300
+ );
1301
+ if (
1302
+ bomData.parentComponent &&
1303
+ Object.keys(bomData.parentComponent).length
1304
+ ) {
1305
+ parentSubComponents.push(bomData.parentComponent);
1306
+ }
1307
+ }
1308
+ }
1309
+ if (hasAnyProjectType(["oci", "clojure"], options)) {
1310
+ if (!hasAnyProjectType(["oci"], options, false)) {
1311
+ thoughtLog(
1312
+ "**CLOJURE**: Looking for Clojure projects. Should I warn the user that the purl namespace 'clojars' isn't widely supported by tools like Dependency-Track?",
1313
+ );
1314
+ }
1315
+ setProjectTypeActivityContext("clojure", path);
1316
+ bomData = createClojureBom(path, options);
1317
+ if (bomData?.bomJson?.components?.length) {
1318
+ thoughtLog(
1319
+ `I found ${bomData.bomJson.components.length} clojure packages.`,
1320
+ );
1321
+ if (DEBUG_MODE) {
1322
+ console.log(
1323
+ `Found ${bomData.bomJson.components.length} clojure packages at ${path}`,
1324
+ );
1325
+ }
1326
+ components = components.concat(bomData.bomJson.components);
1327
+ dependencies = mergeDependencies(
1328
+ dependencies,
1329
+ bomData.bomJson.dependencies,
1330
+ );
1331
+ if (
1332
+ bomData.parentComponent &&
1333
+ Object.keys(bomData.parentComponent).length
1334
+ ) {
1335
+ parentSubComponents.push(bomData.parentComponent);
1336
+ }
1337
+ }
1338
+ }
1339
+ if (hasAnyProjectType(["oci", "github"], options)) {
1340
+ if (!hasAnyProjectType(["oci"], options, false)) {
1341
+ thoughtLog(
1342
+ "**GITHUB**: Looking for any github packages and workflows.",
1343
+ );
1344
+ }
1345
+ setProjectTypeActivityContext("github", path);
1346
+ bomData = createGitHubBom(path, options);
1347
+ if (bomData?.bomJson?.components?.length) {
1348
+ thoughtLog(
1349
+ `I found ${bomData.bomJson.components.length} github action packages as well. Should I convert these to formulation instead 🤔`,
1350
+ );
1351
+ if (DEBUG_MODE) {
1352
+ console.log(
1353
+ `Found ${bomData.bomJson.components.length} GitHub action packages at ${path}`,
1354
+ );
1355
+ }
1356
+ components = components.concat(bomData.bomJson.components);
1357
+ dependencies = mergeDependencies(
1358
+ dependencies,
1359
+ bomData.bomJson.dependencies,
1360
+ );
1361
+ if (
1362
+ bomData.parentComponent &&
1363
+ Object.keys(bomData.parentComponent).length
1364
+ ) {
1365
+ parentSubComponents.push(bomData.parentComponent);
1366
+ }
1367
+ }
1368
+ }
1369
+ if (hasAnyProjectType(["oci", "cloudbuild"], options)) {
1370
+ if (!hasAnyProjectType(["oci"], options, false)) {
1371
+ thoughtLog(
1372
+ "**CLOUDBUILD**: Let's check for CloudBuild configuration files that include package dependencies.",
1373
+ );
1374
+ }
1375
+ setProjectTypeActivityContext("cloudbuild", path);
1376
+ bomData = createCloudBuildBom(path, options);
1377
+ if (bomData?.bomJson?.components?.length) {
1378
+ thoughtLog(
1379
+ `I found ${bomData.bomJson.components.length} cloudbuild packages.`,
1380
+ );
1381
+ if (DEBUG_MODE) {
1382
+ console.log(
1383
+ `Found ${bomData.bomJson.components.length} CloudBuild configuration at ${path}`,
1384
+ );
1385
+ }
1386
+ components = components.concat(bomData.bomJson.components);
1387
+ dependencies = mergeDependencies(
1388
+ dependencies,
1389
+ bomData.bomJson.dependencies,
1390
+ );
1391
+ if (
1392
+ bomData.parentComponent &&
1393
+ Object.keys(bomData.parentComponent).length
1394
+ ) {
1395
+ parentSubComponents.push(bomData.parentComponent);
1396
+ }
1397
+ }
1398
+ }
1399
+ if (hasAnyProjectType(["oci", "swift"], options)) {
1400
+ if (!hasAnyProjectType(["oci"], options, false)) {
1401
+ thoughtLog(
1402
+ "**SWIFT**: Now checking for Swift projects. We don't support CocoaPods, Objective-C, or pure Xcode projects, so the SBOM will be incomplete.",
1403
+ );
1404
+ }
1405
+ setProjectTypeActivityContext("swift", path);
1406
+ bomData = await createSwiftBom(path, options);
1407
+ if (bomData?.bomJson?.components?.length) {
1408
+ thoughtLog(
1409
+ `I found ${bomData.bomJson.components.length} swift packages here.`,
1410
+ );
1411
+ if (DEBUG_MODE) {
1412
+ console.log(
1413
+ `Found ${bomData.bomJson.components.length} Swift packages at ${path}`,
1414
+ );
1415
+ }
1416
+ components = components.concat(bomData.bomJson.components);
1417
+ dependencies = mergeDependencies(
1418
+ dependencies,
1419
+ bomData.bomJson.dependencies,
1420
+ );
1421
+ if (
1422
+ bomData.parentComponent &&
1423
+ Object.keys(bomData.parentComponent).length
1424
+ ) {
1425
+ parentSubComponents.push(bomData.parentComponent);
1426
+ }
1427
+ }
1428
+ }
1429
+ if (hasAnyProjectType(["oci", "jar", "war", "ear"], options)) {
1430
+ if (!hasAnyProjectType(["oci"], options, false)) {
1431
+ thoughtLog(
1432
+ "**JAR**: Let's check for any bundled jar/war/ear files to improve the SBOM accuracy.",
1433
+ );
1434
+ }
1435
+ setProjectTypeActivityContext("jar", path);
1436
+ bomData = await createJarBom(path, options);
1437
+ if (bomData?.bomJson?.components?.length) {
1438
+ thoughtLog(
1439
+ `I found ${bomData.bomJson.components.length} jar packages as well.`,
1440
+ );
1441
+ if (DEBUG_MODE) {
1442
+ console.log(
1443
+ `Found ${bomData.bomJson.components.length} jar packages at ${path}`,
1444
+ );
1445
+ }
1446
+ components = components.concat(bomData.bomJson.components);
1447
+ dependencies = mergeDependencies(
1448
+ dependencies,
1449
+ bomData.bomJson.dependencies,
1450
+ );
1451
+ if (
1452
+ bomData.parentComponent &&
1453
+ Object.keys(bomData.parentComponent).length
1454
+ ) {
1455
+ parentSubComponents.push(bomData.parentComponent);
1456
+ }
1457
+ }
1458
+ }
1459
+ if (hasAnyProjectType(["oci", "cocoa"], options)) {
1460
+ setProjectTypeActivityContext("cocoa", path);
1461
+ bomData = await createCocoaBom(path, options);
1462
+ if (bomData?.bomJson?.components?.length) {
1463
+ if (DEBUG_MODE) {
1464
+ console.log(
1465
+ `Found ${bomData.bomJson.components.length} Cocoa packages at ${path}`,
1466
+ );
1467
+ }
1468
+ components = components.concat(bomData.bomJson.components);
1469
+ dependencies = dependencies.concat(bomData.bomJson.dependencies);
1470
+ if (
1471
+ bomData.parentComponent &&
1472
+ Object.keys(bomData.parentComponent).length
1473
+ ) {
1474
+ parentSubComponents.push(bomData.parentComponent);
1475
+ }
1476
+ }
1477
+ }
1478
+ if (hasAnyProjectType(["oci", "nix"], options)) {
1479
+ setProjectTypeActivityContext("nix", path);
1480
+ bomData = await createNixBom(path, options);
1481
+ if (bomData?.bomJson?.components?.length) {
1482
+ if (DEBUG_MODE) {
1483
+ console.log(
1484
+ `Found ${bomData.bomJson.components.length} Nix flake packages at ${path}`,
1485
+ );
1486
+ }
1487
+ components = components.concat(bomData.bomJson.components);
1488
+ dependencies = mergeDependencies(
1489
+ dependencies,
1490
+ bomData.bomJson.dependencies,
1491
+ );
1492
+ if (
1493
+ bomData.parentComponent &&
1494
+ Object.keys(bomData.parentComponent).length
1495
+ ) {
1496
+ parentSubComponents.push(bomData.parentComponent);
1497
+ }
1498
+ }
1499
+ }
1500
+ if (hasAnyProjectType(["caxa"], options, false)) {
1501
+ setProjectTypeActivityContext("caxa", path);
1502
+ bomData = await createCaxaBom(path, options);
1503
+ if (bomData?.bomJson?.components?.length) {
1504
+ if (DEBUG_MODE) {
1505
+ console.log(
1506
+ `Found ${bomData.bomJson.components.length} caxa packages at ${path}`,
1507
+ );
1508
+ }
1509
+ components = components.concat(bomData.bomJson.components);
1510
+ dependencies = mergeDependencies(
1511
+ dependencies,
1512
+ bomData.bomJson.dependencies,
1513
+ );
1514
+ if (
1515
+ bomData.parentComponent &&
1516
+ Object.keys(bomData.parentComponent).length
1517
+ ) {
1518
+ parentSubComponents.push(bomData.parentComponent);
1519
+ }
1520
+ }
1521
+ }
1522
+ if (hasAnyProjectType(["asar"], options, false)) {
1523
+ setProjectTypeActivityContext("asar", path);
1524
+ bomData = await createAsarBom(path, options);
1525
+ if (bomData?.bomJson?.components?.length) {
1526
+ if (DEBUG_MODE) {
1527
+ console.log(
1528
+ `Found ${bomData.bomJson.components.length} ASAR component(s) at ${path}`,
1529
+ );
1530
+ }
1531
+ components = components.concat(bomData.bomJson.components);
1532
+ dependencies = mergeDependencies(
1533
+ dependencies,
1534
+ bomData.bomJson.dependencies,
1535
+ );
1536
+ if (
1537
+ bomData.parentComponent &&
1538
+ Object.keys(bomData.parentComponent).length
1539
+ ) {
1540
+ parentSubComponents.push(bomData.parentComponent);
1541
+ }
1542
+ }
1543
+ }
1544
+ if (hasAnyProjectType(["vscode-extension"], options, false)) {
1545
+ setProjectTypeActivityContext("vscode-extension", path);
1546
+ bomData = await createVscodeExtensionBom(path, options);
1547
+ if (bomData?.bomJson?.components?.length) {
1548
+ if (DEBUG_MODE) {
1549
+ console.log(
1550
+ `Found ${bomData.bomJson.components.length} VS Code extension(s) at ${path}`,
1551
+ );
1552
+ }
1553
+ components = components.concat(bomData.bomJson.components);
1554
+ dependencies = mergeDependencies(
1555
+ dependencies,
1556
+ bomData.bomJson.dependencies,
1557
+ );
1558
+ if (
1559
+ bomData.parentComponent &&
1560
+ Object.keys(bomData.parentComponent).length
1561
+ ) {
1562
+ parentSubComponents.push(bomData.parentComponent);
1563
+ }
1564
+ }
1565
+ }
1566
+ if (hasAnyProjectType(["chrome-extension"], options, false)) {
1567
+ let isExplicitChromeExtensionPath = false;
1568
+ if (safeExistsSync(path)) {
1569
+ if (basename(path) === "manifest.json") {
1570
+ isExplicitChromeExtensionPath = true;
1571
+ } else {
1572
+ try {
1573
+ isExplicitChromeExtensionPath =
1574
+ statSync(path).isDirectory() &&
1575
+ safeExistsSync(join(path, "manifest.json"));
1576
+ } catch (_err) {
1577
+ isExplicitChromeExtensionPath = false;
1578
+ }
1579
+ }
1580
+ }
1581
+ if (
1582
+ isExplicitChromeExtensionPath ||
1583
+ !sharedOptions.__didScanChromeExtensions
1584
+ ) {
1585
+ if (!isExplicitChromeExtensionPath) {
1586
+ sharedOptions.__didScanChromeExtensions = true;
1587
+ }
1588
+ setProjectTypeActivityContext("chrome-extension", path);
1589
+ bomData = await createChromeExtensionBom(path, options);
1590
+ if (bomData?.bomJson?.components?.length) {
1591
+ if (DEBUG_MODE) {
1592
+ console.log(
1593
+ `Found ${bomData.bomJson.components.length} Chrome extension(s) on this host`,
1594
+ );
1595
+ }
1596
+ components = components.concat(bomData.bomJson.components);
1597
+ dependencies = mergeDependencies(
1598
+ dependencies,
1599
+ bomData.bomJson.dependencies,
1600
+ );
1601
+ if (
1602
+ bomData.parentComponent &&
1603
+ Object.keys(bomData.parentComponent).length
1604
+ ) {
1605
+ parentSubComponents.push(bomData.parentComponent);
1606
+ }
1607
+ }
1608
+ }
1609
+ }
1610
+ // Collect any crypto keys
1611
+ if (
1612
+ options.specVersion >= 1.6 &&
1613
+ options.includeCrypto &&
1614
+ isCycloneDxComponentTypeEnabled("cryptographic-asset", options)
1615
+ ) {
1616
+ if (!hasAnyProjectType(["oci"], options, false)) {
1617
+ thoughtLog(
1618
+ "**CBOM**: Wait, the user wants me to look for cryptographic assets. Let's check thoroughly.",
1619
+ );
1620
+ }
1621
+ setProjectTypeActivityContext("cbom", path);
1622
+ bomData = await createCryptoCertsBom(path, options);
1623
+ if (bomData?.bomJson?.components?.length) {
1624
+ thoughtLog(
1625
+ `I found ${bomData.bomJson.components.length} crypto assets.`,
1626
+ );
1627
+ if (DEBUG_MODE) {
1628
+ console.log(
1629
+ `Found ${bomData.bomJson.components.length} crypto assets at ${path}`,
1630
+ );
1631
+ }
1632
+ components = components.concat(bomData.bomJson.components);
1633
+ }
1634
+ }
1635
+ return { components, dependencies, options, parentSubComponents };
1636
+ };
1637
+ const pathResults = [];
1638
+ // A container scan walks hundreds of paths, so the phase carries a bar and
1639
+ // names the path in flight rather than sitting silent for minutes.
1640
+ const scanPhase = ui.phase(
1641
+ `Scanning ${pathList.length} ${pathList.length === 1 ? "path" : "paths"}`,
1642
+ );
1643
+ let scannedPaths = 0;
1644
+ let foundComponents = 0;
1645
+ // Layer paths live under a temp directory whose name carries no information.
1646
+ // Reporting them relative to the exploded root shows the path as it exists
1647
+ // inside the image.
1648
+ const explodedRoot = options.allLayersExplodedDir;
1649
+ const displayPath = (path) =>
1650
+ explodedRoot && path.startsWith(explodedRoot)
1651
+ ? path.slice(explodedRoot.length) || "/"
1652
+ : path;
1653
+ const trackedScanOnePath = async (path) => {
1654
+ scanPhase.detail(displayPath(path));
1655
+ try {
1656
+ const result = await scanOnePath(path);
1657
+ // Paths that yielded nothing stay silent, so the scrollback above the
1658
+ // live region reads as a running list of what was actually found.
1659
+ if (result.components.length) {
1660
+ foundComponents += result.components.length;
1661
+ ui.print(
1662
+ ` ${summarizePurlTypes(result.components)} in ${displayPath(path)}`,
1663
+ );
1664
+ }
1665
+ return result;
1666
+ } finally {
1667
+ scannedPaths += 1;
1668
+ scanPhase.progress(scannedPaths, pathList.length);
1669
+ }
1670
+ };
1671
+ if (pathScanConcurrency(pathList) > 1) {
1672
+ pathResults.push(
1673
+ ...(await mapWithConcurrency(
1674
+ pathList,
1675
+ trackedScanOnePath,
1676
+ pathScanConcurrency(pathList),
1677
+ )),
1678
+ );
1679
+ } else {
1680
+ for (const path of pathList) {
1681
+ pathResults.push(await trackedScanOnePath(path));
1682
+ }
1683
+ }
1684
+ scanPhase.succeed(
1685
+ summarizeCounts([[foundComponents, "component", "components"]]),
1686
+ );
1687
+ setDirWalkCacheRoot(undefined);
1688
+ for (const pathResult of pathResults) {
1689
+ components = components.concat(pathResult.components);
1690
+ dependencies = mergeDependencies(
1691
+ dependencies,
1692
+ pathResult.dependencies,
1693
+ parentComponent,
1694
+ );
1695
+ parentSubComponents = parentSubComponents.concat(
1696
+ pathResult.parentSubComponents,
1697
+ );
1698
+ if (pathResult.options.services?.length) {
1699
+ sharedOptions.services = mergeServices(
1700
+ sharedOptions.services || [],
1701
+ pathResult.options.services,
1702
+ );
1703
+ }
1704
+ }
1705
+ if (
1706
+ options.lastWorkingDir &&
1707
+ options.lastWorkingDir !== "" &&
1708
+ options.lastWorkingDir !== "/" &&
1709
+ !options.lastWorkingDir.includes("/opt/") &&
1710
+ !options.lastWorkingDir.includes("/home/")
1711
+ ) {
1712
+ setProjectTypeActivityContext("jar", options.lastWorkingDir);
1713
+ bomData = createJarBom(options.lastWorkingDir, options);
1714
+ if (bomData?.bomJson?.components?.length) {
1715
+ if (DEBUG_MODE) {
1716
+ console.log(
1717
+ `Found ${bomData.bomJson.components.length} jar packages at ${options.lastWorkingDir}`,
1718
+ );
1719
+ }
1720
+ components = components.concat(bomData.bomJson.components);
1721
+ dependencies = mergeDependencies(
1722
+ dependencies,
1723
+ bomData.bomJson.dependencies,
1724
+ );
1725
+ if (
1726
+ bomData.parentComponent &&
1727
+ Object.keys(bomData.parentComponent).length
1728
+ ) {
1729
+ parentSubComponents.push(bomData.parentComponent);
1730
+ }
1731
+ }
1732
+ }
1733
+ // Retain the components of parent component
1734
+ if (parentSubComponents.length) {
1735
+ if (!hasAnyProjectType(["oci"], options, false)) {
1736
+ thoughtLog("**METADATA**: Tweaking the parent component hierarchy.");
1737
+ }
1738
+ if (!parentComponent || !Object.keys(parentComponent).length) {
1739
+ parentComponent = parentSubComponents[0];
1740
+ }
1741
+ // Our naive approach to appending to sub-components could result in same parent being included as a child
1742
+ // This is filtered out here
1743
+ parentSubComponents = parentSubComponents.filter(
1744
+ (c) => c["bom-ref"] !== parentComponent["bom-ref"],
1745
+ );
1746
+ parentComponent.components = trimComponents(parentSubComponents);
1747
+ if (
1748
+ parentComponent.components.length === 1 &&
1749
+ parentComponent.components[0].name === parentComponent.name &&
1750
+ !parentComponent.purl.startsWith("pkg:container")
1751
+ ) {
1752
+ parentComponent = parentComponent.components[0];
1753
+ delete parentComponent.components;
1754
+ }
1755
+ // Add references between the multiple sub-boms
1756
+ let parentDependencies = dependencies.find(
1757
+ (d) => d["ref"] === parentComponent["bom-ref"],
1758
+ );
1759
+ if (!parentDependencies) {
1760
+ parentDependencies = {
1761
+ ref: parentComponent["bom-ref"],
1762
+ };
1763
+ dependencies = mergeDependencies(dependencies, parentDependencies);
1764
+ }
1765
+ if (!parentDependencies["dependsOn"]) {
1766
+ parentDependencies["dependsOn"] = [];
1767
+ }
1768
+ for (const parentSub of parentSubComponents) {
1769
+ // Issue: 1622. We might have already captured this parent component dependency
1770
+ if (!parentDependencies["dependsOn"].includes(parentSub["bom-ref"])) {
1771
+ parentDependencies["dependsOn"].push(parentSub["bom-ref"]);
1772
+ }
1773
+ }
1774
+ }
1775
+ // some cleanup, but not complete
1776
+ for (const path of pathList) {
1777
+ if (path.startsWith(join(getTmpDir(), "docker-images-"))) {
1778
+ safeRmSync(path, { recursive: true, force: true });
1779
+ }
1780
+ }
1781
+ const multiResult = dedupeBom(
1782
+ options,
1783
+ components,
1784
+ parentComponent,
1785
+ dependencies,
1786
+ );
1787
+ if (formulationList.length) {
1788
+ multiResult.formulationList = formulationList;
1789
+ }
1790
+ return multiResult;
1791
+ }
1792
+
1793
+ /**
1794
+ * Function to create a dynamic SBOM by executing a command and tracing the
1795
+ * shared libraries it loads at runtime via instrumentation.
1796
+ *
1797
+ * Components receive scope=required, evidence.identity[].methods[].technique=
1798
+ * instrumentation, and confidence 0.8 (version known) or 0.5 (version unknown).
1799
+ *
1800
+ * @param {string} path - Target path (used as working directory fallback)
1801
+ * @param {Object} options - CLI options; must include options.traceCmd
1802
+ * @returns {Promise<Object>} Promise resolving to BOM data object
1803
+ */
1804
+ export async function createDynamicBom(path, options) {
1805
+ const commandStr = options.traceCmd;
1806
+ const workingDir = options.traceWorkingDir || path || process.cwd();
1807
+
1808
+ if (!commandStr) {
1809
+ console.error(
1810
+ "Missing required --trace-cmd option for dynamic project type.",
1811
+ );
1812
+ return buildBomNSData(options, [], "generic", {
1813
+ src: workingDir,
1814
+ projectType: "dynamic",
1815
+ });
1816
+ }
1817
+
1818
+ const traceOptions = {
1819
+ readPaths: options.traceReadPaths,
1820
+ writePaths: options.traceWritePaths,
1821
+ maxMemoryMB: options.traceMaxMemoryMB,
1822
+ maxCPUCores: options.traceMaxCPUCores,
1823
+ maxProcesses: options.traceMaxProcesses,
1824
+ timeoutMs: options.traceTimeoutMs,
1825
+ disableNetwork: options.traceDisableNetwork ?? true,
1826
+ traceHTTPURLs: options.traceHTTPURLs,
1827
+ tracePeriod: options.tracePeriod,
1828
+ allowEnvs: options.traceAllowEnvs,
1829
+ allowHidden: options.traceAllowHidden,
1830
+ allowListen: options.traceAllowListen,
1831
+ cryptoProbeMode: options.traceCryptoProbeMode,
1832
+ enableDiff: options.traceEnableDiff,
1833
+ strict: options.traceStrict,
1834
+ allowHosts: options.traceAllowHosts,
1835
+ allowPorts: options.traceAllowPorts,
1836
+ allowUrls: options.traceAllowUrls,
1837
+ blockFork: options.traceBlockFork,
1838
+ traceExec: options.traceTraceExec,
1839
+ allowExec: options.traceAllowExec,
1840
+ blockExec: options.traceBlockExec,
1841
+ traceCrypto: options.traceCrypto,
1842
+ cbom: options.cbom,
1843
+ };
1844
+
1845
+ const { components: pkgList, services: traceServices } =
1846
+ await buildDynamicComponents(commandStr, workingDir, traceOptions);
1847
+
1848
+ return buildBomNSData(options, pkgList, "generic", {
1849
+ src: workingDir,
1850
+ projectType: "dynamic",
1851
+ filename: commandStr,
1852
+ services: traceServices,
1853
+ });
1854
+ }
1855
+
1856
+ /**
1857
+ * Function to create bom string for various languages
1858
+ *
1859
+ * @param {string} path to the project
1860
+ * @param {Object} options Parse options from the cli
1861
+ * @returns {Promise<Object|undefined>} Promise resolving to BOM object, or undefined if path is not readable
1862
+ */
1863
+ export async function createXBom(path, options) {
1864
+ try {
1865
+ accessSync(path, constants.R_OK);
1866
+ } catch (_err) {
1867
+ return undefined;
1868
+ }
1869
+ if (
1870
+ safeExistsSync(join(path, "package.json")) ||
1871
+ safeExistsSync(join(path, "rush.json")) ||
1872
+ safeExistsSync(join(path, "yarn.lock")) ||
1873
+ safeExistsSync(join(path, "bun.lock")) ||
1874
+ safeExistsSync(join(path, "bun.lockb")) ||
1875
+ safeExistsSync(join(path, "deno.lock")) ||
1876
+ safeExistsSync(join(path, "deno.json")) ||
1877
+ safeExistsSync(join(path, "deno.jsonc"))
1878
+ ) {
1879
+ return await createNodejsBom(path, options);
1880
+ }
1881
+ // maven - pom.xml
1882
+ const pomFiles = getAllFiles(
1883
+ path,
1884
+ `${options.multiProject ? "**/" : ""}pom.xml`,
1885
+ options,
1886
+ );
1887
+ // gradle
1888
+ const gradleFiles = getAllFiles(
1889
+ path,
1890
+ `${options.multiProject ? "**/" : ""}build.gradle*`,
1891
+ options,
1892
+ );
1893
+ // scala sbt
1894
+ const sbtFiles = getAllFiles(
1895
+ path,
1896
+ `${options.multiProject ? "**/" : ""}{build.sbt,Build.scala}*`,
1897
+ options,
1898
+ );
1899
+ if (pomFiles.length || gradleFiles.length || sbtFiles.length) {
1900
+ return await createJavaBom(path, options);
1901
+ }
1902
+ // python
1903
+ const pipenvMode = safeExistsSync(join(path, "Pipfile"));
1904
+ const poetryMode = safeExistsSync(join(path, "poetry.lock"));
1905
+ const pyLockFiles = getAllFiles(
1906
+ path,
1907
+ `${options.multiProject ? "**/" : ""}pylock*.toml`,
1908
+ options,
1909
+ ).filter((f) => isPyLockFile(f));
1910
+ const pyLockMode = pyLockFiles.length > 0;
1911
+ const pyProjectMode =
1912
+ !poetryMode && !pyLockMode && safeExistsSync(join(path, "pyproject.toml"));
1913
+ const setupPyMode = safeExistsSync(join(path, "setup.py"));
1914
+ if (pipenvMode || poetryMode || pyLockMode || pyProjectMode || setupPyMode) {
1915
+ return await createPythonBom(path, options);
1916
+ }
1917
+ const reqFiles = getAllFiles(
1918
+ path,
1919
+ `${options.multiProject ? "**/" : ""}*requirements*.txt`,
1920
+ options,
1921
+ );
1922
+ const reqDirFiles = getAllFiles(
1923
+ path,
1924
+ `${options.multiProject ? "**/" : ""}requirements/*.txt`,
1925
+ options,
1926
+ );
1927
+ const requirementsMode = reqFiles?.length || reqDirFiles?.length;
1928
+ const whlFiles = getAllFiles(
1929
+ path,
1930
+ `${options.multiProject ? "**/" : ""}*.whl`,
1931
+ options,
1932
+ );
1933
+ if (requirementsMode || whlFiles.length) {
1934
+ return await createPythonBom(path, options);
1935
+ }
1936
+ // go
1937
+ const gosumFiles = getAllFiles(
1938
+ path,
1939
+ `${options.multiProject ? "**/" : ""}go.sum`,
1940
+ options,
1941
+ );
1942
+ const gomodFiles = getAllFiles(
1943
+ path,
1944
+ `${options.multiProject ? "**/" : ""}go.mod`,
1945
+ options,
1946
+ );
1947
+ const gopkgLockFiles = getAllFiles(
1948
+ path,
1949
+ `${options.multiProject ? "**/" : ""}Gopkg.lock`,
1950
+ options,
1951
+ );
1952
+ if (gomodFiles.length || gosumFiles.length || gopkgLockFiles.length) {
1953
+ return await createGoBom(path, options);
1954
+ }
1955
+
1956
+ // rust
1957
+ const cargoLockFiles = getAllFiles(
1958
+ path,
1959
+ `${options.multiProject ? "**/" : ""}Cargo.lock`,
1960
+ options,
1961
+ );
1962
+ const cargoFiles = getAllFiles(
1963
+ path,
1964
+ `${options.multiProject ? "**/" : ""}Cargo.toml`,
1965
+ options,
1966
+ );
1967
+ if (cargoLockFiles.length || cargoFiles.length) {
1968
+ return await createRustBom(path, options);
1969
+ }
1970
+
1971
+ // php
1972
+ const composerJsonFiles = getAllFiles(
1973
+ path,
1974
+ `${options.multiProject ? "**/" : ""}composer.json`,
1975
+ options,
1976
+ );
1977
+ const composerLockFiles = getAllFiles(
1978
+ path,
1979
+ `${options.multiProject ? "**/" : ""}composer.lock`,
1980
+ options,
1981
+ );
1982
+ if (composerJsonFiles.length || composerLockFiles.length) {
1983
+ return createPHPBom(path, options);
1984
+ }
1985
+
1986
+ // Ruby
1987
+ const gemFiles = getAllFiles(
1988
+ path,
1989
+ `${options.multiProject ? "**/" : ""}Gemfile`,
1990
+ options,
1991
+ );
1992
+ const gemLockFiles = getAllFiles(
1993
+ path,
1994
+ `${options.multiProject ? "**/" : ""}Gemfile*.lock`,
1995
+ options,
1996
+ );
1997
+ if (gemFiles.length || gemLockFiles.length) {
1998
+ return await createRubyBom(path, options);
1999
+ }
2000
+
2001
+ // .Net
2002
+ const csProjFiles = getAllFiles(
2003
+ path,
2004
+ `${options.multiProject ? "**/" : ""}*.{cs,vb,fs,ts,hmi,plc}proj`,
2005
+ options,
2006
+ );
2007
+ if (csProjFiles.length) {
2008
+ return await createCsharpBom(path, options);
2009
+ }
2010
+
2011
+ // Dart
2012
+ const pubFiles = getAllFiles(
2013
+ path,
2014
+ `${options.multiProject ? "**/" : ""}pubspec.lock`,
2015
+ options,
2016
+ );
2017
+ const pubSpecFiles = getAllFiles(
2018
+ path,
2019
+ `${options.multiProject ? "**/" : ""}pubspec.yaml`,
2020
+ options,
2021
+ );
2022
+ if (pubFiles.length || pubSpecFiles.length) {
2023
+ return await createDartBom(path, options);
2024
+ }
2025
+
2026
+ // Haskell
2027
+ const hackageFiles = getAllFiles(
2028
+ path,
2029
+ `${options.multiProject ? "**/" : ""}cabal.project.freeze`,
2030
+ options,
2031
+ );
2032
+ if (hackageFiles.length) {
2033
+ return createHaskellBom(path, options);
2034
+ }
2035
+
2036
+ // Elixir
2037
+ const mixFiles = getAllFiles(
2038
+ path,
2039
+ `${options.multiProject ? "**/" : ""}mix.lock`,
2040
+ options,
2041
+ );
2042
+ if (mixFiles.length) {
2043
+ return createElixirBom(path, options);
2044
+ }
2045
+
2046
+ // cpp
2047
+ const conanLockFiles = getAllFiles(
2048
+ path,
2049
+ `${options.multiProject ? "**/" : ""}conan.lock`,
2050
+ options,
2051
+ );
2052
+ const colliderLockFiles = getAllFiles(
2053
+ path,
2054
+ `${options.multiProject ? "**/" : ""}collider.lock`,
2055
+ options,
2056
+ );
2057
+ const conanFiles = getAllFiles(
2058
+ path,
2059
+ `${options.multiProject ? "**/" : ""}conanfile.txt`,
2060
+ options,
2061
+ );
2062
+ const cmakeListFiles = getAllFiles(
2063
+ path,
2064
+ `${options.multiProject ? "**/" : ""}CMakeLists.txt`,
2065
+ options,
2066
+ );
2067
+ const mesonBuildFiles = getAllFiles(
2068
+ path,
2069
+ `${options.multiProject ? "**/" : ""}meson.build`,
2070
+ options,
2071
+ );
2072
+ if (
2073
+ colliderLockFiles.length ||
2074
+ conanLockFiles.length ||
2075
+ conanFiles.length ||
2076
+ cmakeListFiles.length ||
2077
+ mesonBuildFiles.length
2078
+ ) {
2079
+ return createCppBom(path, options);
2080
+ }
2081
+
2082
+ // clojure
2083
+ const ednFiles = getAllFiles(
2084
+ path,
2085
+ `${options.multiProject ? "**/" : ""}deps.edn`,
2086
+ options,
2087
+ );
2088
+ const leinFiles = getAllFiles(
2089
+ path,
2090
+ `${options.multiProject ? "**/" : ""}project.clj`,
2091
+ options,
2092
+ );
2093
+ if (ednFiles.length || leinFiles.length) {
2094
+ return createClojureBom(path, options);
2095
+ }
2096
+
2097
+ // GitHub actions
2098
+ const ghactionFiles = getAllFiles(
2099
+ path,
2100
+ ".github/workflows/" + "*.{yml,yaml}",
2101
+ options,
2102
+ );
2103
+ if (ghactionFiles.length) {
2104
+ return createGitHubBom(path, options);
2105
+ }
2106
+
2107
+ // Jenkins plugins
2108
+ const hpiFiles = getAllFiles(
2109
+ path,
2110
+ `${options.multiProject ? "**/" : ""}*.hpi`,
2111
+ options,
2112
+ );
2113
+ if (hpiFiles.length) {
2114
+ return await createJenkinsBom(path, options);
2115
+ }
2116
+
2117
+ // VS Code extensions (.vsix files)
2118
+ const vsixFiles = getAllFiles(
2119
+ path,
2120
+ `${options.multiProject ? "**/" : ""}*.vsix`,
2121
+ options,
2122
+ );
2123
+ if (vsixFiles.length) {
2124
+ return await createVscodeExtensionBom(path, options);
2125
+ }
2126
+
2127
+ // Electron ASAR archives
2128
+ const asarFiles = getAllFiles(
2129
+ path,
2130
+ `${options.multiProject ? "**/" : ""}*.asar`,
2131
+ options,
2132
+ );
2133
+ if (asarFiles.length) {
2134
+ return await createAsarBom(path, options);
2135
+ }
2136
+
2137
+ // Helm charts
2138
+ const chartFiles = getAllFiles(
2139
+ path,
2140
+ `${options.multiProject ? "**/" : ""}Chart.yaml`,
2141
+ options,
2142
+ );
2143
+ const yamlFiles = getAllFiles(
2144
+ path,
2145
+ `${options.multiProject ? "**/" : ""}values.yaml`,
2146
+ options,
2147
+ );
2148
+ if (chartFiles.length || yamlFiles.length) {
2149
+ return createHelmBom(path, options);
2150
+ }
2151
+
2152
+ // Docker compose, dockerfile, containerfile, kubernetes and skaffold
2153
+ const dcFiles = getAllFiles(
2154
+ path,
2155
+ `${options.multiProject ? "**/" : ""}docker-compose*.yml`,
2156
+ options,
2157
+ );
2158
+ const dfFiles = getAllFiles(
2159
+ path,
2160
+ `${options.multiProject ? "**/" : ""}*Dockerfile*`,
2161
+ options,
2162
+ );
2163
+ const cfFiles = getAllFiles(
2164
+ path,
2165
+ `${options.multiProject ? "**/" : ""}*Containerfile*`,
2166
+ options,
2167
+ );
2168
+ const skFiles = getAllFiles(
2169
+ path,
2170
+ `${options.multiProject ? "**/" : ""}skaffold.yaml`,
2171
+ options,
2172
+ );
2173
+ const deplFiles = getAllFiles(
2174
+ path,
2175
+ `${options.multiProject ? "**/" : ""}deployment.yaml`,
2176
+ options,
2177
+ );
2178
+ if (
2179
+ dcFiles.length ||
2180
+ dfFiles.length ||
2181
+ cfFiles.length ||
2182
+ skFiles.length ||
2183
+ deplFiles.length
2184
+ ) {
2185
+ return await createContainerSpecLikeBom(path, options);
2186
+ }
2187
+
2188
+ // Google CloudBuild
2189
+ const cbFiles = getAllFiles(
2190
+ path,
2191
+ `${options.multiProject ? "**/" : ""}cloudbuild.yaml`,
2192
+ options,
2193
+ );
2194
+ if (cbFiles.length) {
2195
+ return createCloudBuildBom(path, options);
2196
+ }
2197
+
2198
+ // Swift
2199
+ const swiftFiles = getAllFiles(
2200
+ path,
2201
+ `${options.multiProject ? "**/" : ""}Package*.swift`,
2202
+ options,
2203
+ );
2204
+ const pkgResolvedFiles = getAllFiles(
2205
+ path,
2206
+ `${options.multiProject ? "**/" : ""}Package.resolved`,
2207
+ options,
2208
+ );
2209
+ if (swiftFiles.length || pkgResolvedFiles.length) {
2210
+ return await createSwiftBom(path, options);
2211
+ }
2212
+
2213
+ // Cocoa
2214
+ const cocoaFiles = getAllFiles(
2215
+ path,
2216
+ `${options.multiProject ? "**/" : ""}Podfile`,
2217
+ options,
2218
+ );
2219
+ if (cocoaFiles.length) {
2220
+ return await createCocoaBom(path, options);
2221
+ }
2222
+
2223
+ // Nix flakes
2224
+ const flakeNixFiles = getAllFiles(
2225
+ path,
2226
+ `${options.multiProject ? "**/" : ""}flake.nix`,
2227
+ options,
2228
+ );
2229
+ const flakeLockFiles = getAllFiles(
2230
+ path,
2231
+ `${options.multiProject ? "**/" : ""}flake.lock`,
2232
+ options,
2233
+ );
2234
+ if (flakeNixFiles.length || flakeLockFiles.length) {
2235
+ return await createNixBom(path, options);
2236
+ }
2237
+
2238
+ // Zig
2239
+ const zigZonFiles = getAllFiles(
2240
+ path,
2241
+ `${options.multiProject ? "**/" : ""}build.zig.zon`,
2242
+ options,
2243
+ );
2244
+ if (zigZonFiles.length) {
2245
+ return await createZigBom(path, options);
2246
+ }
2247
+
2248
+ // Gleam
2249
+ const gleamTomlFiles = getAllFiles(
2250
+ path,
2251
+ `${options.multiProject ? "**/" : ""}gleam.toml`,
2252
+ options,
2253
+ );
2254
+ if (gleamTomlFiles.length) {
2255
+ return await createGleamBom(path, options);
2256
+ }
2257
+ }
2258
+
2259
+ /**
2260
+ * Function to create a hardware BOM for the current host.
2261
+ *
2262
+ * @param {string} _path Source path (unused for live host HBOM generation)
2263
+ * @param {Object} options Parse options from the cli
2264
+ * @returns {Promise<Object>} Promise resolving to BOM object
2265
+ */
2266
+ export async function createHBom(_path, options) {
2267
+ ensureHbomRuntimeSupport(options, options.commandName || "hbom");
2268
+ let bomJson = await createHbomDocument(options);
2269
+ if (options.includeRuntime) {
2270
+ const runtimeOptions = {
2271
+ ...options,
2272
+ includeRuntime: false,
2273
+ multiProject: false,
2274
+ projectType: ["os"],
2275
+ };
2276
+ const obomData = await createOSBom(_path, runtimeOptions);
2277
+ bomJson = mergeHostInventoryBoms(bomJson, obomData);
2278
+ } else {
2279
+ bomJson = mergeHostInventoryBoms(bomJson);
2280
+ }
2281
+ return {
2282
+ bomJson,
2283
+ dependencies: bomJson.dependencies || [],
2284
+ parentComponent: bomJson.metadata?.component,
2285
+ };
2286
+ }
2287
+
2288
+ /**
2289
+ * Function to create bom string for various languages
2290
+ *
2291
+ * @param {string} path to the project
2292
+ * @param {Object} options Parse options from the cli
2293
+ * @returns {Promise<Object>} Promise resolving to BOM object
2294
+ */
2295
+ export async function createBom(path, options) {
2296
+ clearFileDiscoveryCache();
2297
+ let { projectType } = options;
2298
+ if (!projectType) {
2299
+ projectType = [];
2300
+ }
2301
+ ensureNoMixedHbomProjectTypes(projectType);
2302
+ if (hasHbomProjectType(projectType)) {
2303
+ const selectedHbomProjectType = Array.isArray(projectType)
2304
+ ? projectType[0]
2305
+ : `${projectType}`.split(",")[0];
2306
+ options.projectType = [selectedHbomProjectType];
2307
+ setActivityContext({
2308
+ projectType: selectedHbomProjectType,
2309
+ sourcePath: path,
2310
+ });
2311
+ thoughtLog(
2312
+ "The user wants a Hardware Bill-of-Materials (HBOM) for the current host. Let's use the dedicated hardware collector.",
2313
+ );
2314
+ return await createHBom(path, options);
2315
+ }
2316
+ let exportData;
2317
+ let isContainerMode = false;
2318
+ const isLocalDirectoryInput =
2319
+ !options.projectType?.includes("universal") &&
2320
+ safeExistsSync(path) &&
2321
+ lstatSync(path).isDirectory();
2322
+ // Docker and image archive support
2323
+ // TODO: Support any source archive
2324
+ if (path.endsWith(".tar") || path.endsWith(".tar.gz")) {
2325
+ exportData = await exportArchive(path, options);
2326
+ if (!exportData) {
2327
+ console.log(
2328
+ `OS BOM generation has failed due to problems with exporting the image ${path}`,
2329
+ );
2330
+ options.failOnError && process.exit(1);
2331
+ return {};
2332
+ }
2333
+ isContainerMode = true;
2334
+ } else if (
2335
+ isLocalDirectoryInput &&
2336
+ (hasAnyProjectType(["oci-dir"], options, false) ||
2337
+ hasAnyProjectType(["oci"], options, false))
2338
+ ) {
2339
+ isContainerMode = true;
2340
+ exportData = {
2341
+ inspectData: undefined,
2342
+ lastWorkingDir: "",
2343
+ allLayersDir: path,
2344
+ allLayersExplodedDir: path,
2345
+ };
2346
+ if (safeExistsSync(join(path, "all-layers"))) {
2347
+ exportData.allLayersExplodedDir = join(path, "all-layers");
2348
+ }
2349
+ exportData.pkgPathList = getPkgPathList(exportData, undefined);
2350
+ } else if (
2351
+ (options.projectType &&
2352
+ !options.projectType?.includes("universal") &&
2353
+ hasAnyProjectType(["oci"], options, false)) ||
2354
+ path.startsWith("docker.io") ||
2355
+ path.startsWith("quay.io") ||
2356
+ path.startsWith("ghcr.io") ||
2357
+ path.startsWith("mcr.microsoft.com") ||
2358
+ path.includes("@sha256") ||
2359
+ path.includes(":latest")
2360
+ ) {
2361
+ exportData = await exportImage(path, options);
2362
+ if (exportData) {
2363
+ isContainerMode = true;
2364
+ } else {
2365
+ // Fail early for oci types
2366
+ if (hasAnyProjectType(["oci"], options, false)) {
2367
+ console.log(
2368
+ `OCI BOM generation has failed due to problems with exporting the image ${path}.`,
2369
+ );
2370
+ options.failOnError && process.exit(1);
2371
+ return {};
2372
+ }
2373
+ if (DEBUG_MODE) {
2374
+ console.log(path, "doesn't appear to be a valid container image.");
2375
+ }
2376
+ }
2377
+ }
2378
+ if (isContainerMode) {
2379
+ options.multiProject = true;
2380
+ options.installDeps = false;
2381
+ // Force the project type to oci
2382
+ options.projectType = ["oci"];
2383
+ // Pass the original path
2384
+ options.path = path;
2385
+ options.parentComponent = {};
2386
+ // Create parent component based on the inspect config
2387
+ const inspectData = exportData?.inspectData;
2388
+ if (
2389
+ inspectData?.RepoDigests &&
2390
+ inspectData.RepoTags &&
2391
+ Array.isArray(inspectData.RepoDigests) &&
2392
+ Array.isArray(inspectData.RepoTags) &&
2393
+ inspectData.RepoDigests.length &&
2394
+ inspectData.RepoTags.length
2395
+ ) {
2396
+ const repoTag = inspectData.RepoTags[0];
2397
+ if (repoTag) {
2398
+ const tmpA = repoTag.split(":");
2399
+ if (tmpA && tmpA.length === 2) {
2400
+ options.parentComponent = {
2401
+ name: tmpA[0],
2402
+ version: tmpA[1],
2403
+ type: "container",
2404
+ _integrity: inspectData.RepoDigests[0].replace(
2405
+ "sha256:",
2406
+ "sha256-",
2407
+ ),
2408
+ };
2409
+ applyPurl(
2410
+ options.parentComponent,
2411
+ ociPurl(inspectData.RepoDigests[0], tmpA[1]),
2412
+ );
2413
+ }
2414
+ } else if (inspectData.Id) {
2415
+ options.parentComponent = {
2416
+ name: inspectData.RepoDigests[0].split("@")[0],
2417
+ version: inspectData.RepoDigests[0]
2418
+ .split("@")[1]
2419
+ .replace("sha256:", ""),
2420
+ type: "container",
2421
+ _integrity: inspectData.RepoDigests[0].replace("sha256:", "sha256-"),
2422
+ };
2423
+ applyPurl(options.parentComponent, ociPurl(inspectData.RepoDigests[0]));
2424
+ }
2425
+ } else {
2426
+ options.parentComponent = createDefaultParentComponent(
2427
+ path,
2428
+ "container",
2429
+ options,
2430
+ );
2431
+ }
2432
+ // Pass the entire export data about the image layers
2433
+ options.exportData = exportData;
2434
+ if (exportData?.binPaths) {
2435
+ options.binPaths = exportData.binPaths;
2436
+ }
2437
+ options.lastWorkingDir = exportData?.lastWorkingDir;
2438
+ options.allLayersExplodedDir = exportData?.allLayersExplodedDir;
2439
+ return await createMultiXBom(
2440
+ [...new Set(exportData?.pkgPathList)],
2441
+ options,
2442
+ );
2443
+ }
2444
+ if (path.endsWith(".war")) {
2445
+ projectType = ["java"];
2446
+ }
2447
+ if (!projectType.length && path.endsWith(".asar")) {
2448
+ projectType = ["asar"];
2449
+ }
2450
+ if (projectType.length > 1) {
2451
+ setActivityContext({
2452
+ projectType: projectType.join(","),
2453
+ sourcePath: path,
2454
+ });
2455
+ thoughtLog(
2456
+ `The user has specified multiple project types: ${projectType.join(", ")}. Let's focus on the types one at a time.`,
2457
+ );
2458
+ console.log("Generate BOM for project types:", projectType.join(", "));
2459
+ return await createMultiXBom(path, options);
2460
+ }
2461
+ if (projectType.length === 1) {
2462
+ setActivityContext({ projectType: projectType[0], sourcePath: path });
2463
+ if (hasAnyProjectType(["oci"], options, false)) {
2464
+ thoughtLog(
2465
+ "Okay, we're generating an SBOM for the OCI type. We'll need a compatible tool like Docker, Podman, or Nerdctl, along with the binary plugins.",
2466
+ );
2467
+ } else {
2468
+ thoughtLog(
2469
+ `The user wants me to focus on a single type, '${projectType}'.`,
2470
+ );
2471
+ }
2472
+ }
2473
+ // Use the project type alias to return any singular BOM
2474
+ if (PROJECT_TYPE_ALIASES["java"].includes(projectType[0])) {
2475
+ return await createJavaBom(path, options);
2476
+ }
2477
+ if (PROJECT_TYPE_ALIASES["android"].includes(projectType[0])) {
2478
+ return createAndroidBom(path, options);
2479
+ }
2480
+ if (
2481
+ PROJECT_TYPE_ALIASES["js"].includes(projectType[0]) ||
2482
+ projectType?.[0]?.startsWith("node")
2483
+ ) {
2484
+ return await createNodejsBom(path, options);
2485
+ }
2486
+ if (PROJECT_TYPE_ALIASES["mcp"].includes(projectType[0])) {
2487
+ return await createNodejsBom(path, options);
2488
+ }
2489
+ if (PROJECT_TYPE_ALIASES["ai-skill"].includes(projectType[0])) {
2490
+ return await createNodejsBom(path, options);
2491
+ }
2492
+ if (optionIncludesAiInventoryProjectType(projectType, "ai")) {
2493
+ return await createNodejsBom(path, options);
2494
+ }
2495
+ if (
2496
+ PROJECT_TYPE_ALIASES["py"].includes(projectType[0]) ||
2497
+ projectType?.[0]?.startsWith("python")
2498
+ ) {
2499
+ return await createPythonBom(path, options);
2500
+ }
2501
+ if (PROJECT_TYPE_ALIASES["go"].includes(projectType[0])) {
2502
+ return await createGoBom(path, options);
2503
+ }
2504
+ if (PROJECT_TYPE_ALIASES["rust"].includes(projectType[0])) {
2505
+ return await createRustBom(path, options);
2506
+ }
2507
+ if (PROJECT_TYPE_ALIASES["cargo-cache"].includes(projectType[0])) {
2508
+ return await createCargoCacheBom(getCargoCacheDir(), options);
2509
+ }
2510
+ if (PROJECT_TYPE_ALIASES["php"].includes(projectType[0])) {
2511
+ return createPHPBom(path, options);
2512
+ }
2513
+ if (
2514
+ PROJECT_TYPE_ALIASES["ruby"].includes(projectType[0]) ||
2515
+ projectType?.[0]?.startsWith("ruby")
2516
+ ) {
2517
+ return await createRubyBom(path, options);
2518
+ }
2519
+ if (PROJECT_TYPE_ALIASES["csharp"].includes(projectType[0])) {
2520
+ return await createCsharpBom(path, options);
2521
+ }
2522
+ if (PROJECT_TYPE_ALIASES["dart"].includes(projectType[0])) {
2523
+ return await createDartBom(path, options);
2524
+ }
2525
+ if (PROJECT_TYPE_ALIASES["haskell"].includes(projectType[0])) {
2526
+ return createHaskellBom(path, options);
2527
+ }
2528
+ if (PROJECT_TYPE_ALIASES["elixir"].includes(projectType[0])) {
2529
+ return createElixirBom(path, options);
2530
+ }
2531
+ if (PROJECT_TYPE_ALIASES["c"].includes(projectType[0])) {
2532
+ return createCppBom(path, options);
2533
+ }
2534
+ if (PROJECT_TYPE_ALIASES["clojure"].includes(projectType[0])) {
2535
+ return createClojureBom(path, options);
2536
+ }
2537
+ if (PROJECT_TYPE_ALIASES["github"].includes(projectType[0])) {
2538
+ return createGitHubBom(path, options);
2539
+ }
2540
+ if (PROJECT_TYPE_ALIASES["os"].includes(projectType[0])) {
2541
+ return await createOSBom(path, options);
2542
+ }
2543
+ if (PROJECT_TYPE_ALIASES["jenkins"].includes(projectType[0])) {
2544
+ return await createJenkinsBom(path, options);
2545
+ }
2546
+ if (PROJECT_TYPE_ALIASES["helm"].includes(projectType[0])) {
2547
+ return createHelmBom(path, options);
2548
+ }
2549
+ if (PROJECT_TYPE_ALIASES["helm-index"].includes(projectType[0])) {
2550
+ return createHelmBom(
2551
+ join(homedir(), ".cache", "helm", "repository"),
2552
+ options,
2553
+ );
2554
+ }
2555
+ if (PROJECT_TYPE_ALIASES["universal"].includes(projectType[0])) {
2556
+ return await createContainerSpecLikeBom(path, options);
2557
+ }
2558
+ if (PROJECT_TYPE_ALIASES["cloudbuild"].includes(projectType[0])) {
2559
+ return createCloudBuildBom(path, options);
2560
+ }
2561
+ if (PROJECT_TYPE_ALIASES["swift"].includes(projectType[0])) {
2562
+ return await createSwiftBom(path, options);
2563
+ }
2564
+ if (PROJECT_TYPE_ALIASES["binary"].includes(projectType[0])) {
2565
+ return createBinaryBom(path, options);
2566
+ }
2567
+ if (PROJECT_TYPE_ALIASES["cocoa"].includes(projectType[0])) {
2568
+ return await createCocoaBom(path, options);
2569
+ }
2570
+ if (PROJECT_TYPE_ALIASES["nix"].includes(projectType[0])) {
2571
+ return await createNixBom(path, options);
2572
+ }
2573
+ if (PROJECT_TYPE_ALIASES["zig"].includes(projectType[0])) {
2574
+ return await createZigBom(path, options);
2575
+ }
2576
+ if (PROJECT_TYPE_ALIASES["gleam"].includes(projectType[0])) {
2577
+ return await createGleamBom(path, options);
2578
+ }
2579
+ if (PROJECT_TYPE_ALIASES["caxa"].includes(projectType[0])) {
2580
+ return await createCaxaBom(path, options);
2581
+ }
2582
+ if (PROJECT_TYPE_ALIASES["asar"].includes(projectType[0])) {
2583
+ return await createAsarBom(path, options);
2584
+ }
2585
+ if (PROJECT_TYPE_ALIASES["vscode-extension"].includes(projectType[0])) {
2586
+ return await createVscodeExtensionBom(path, options);
2587
+ }
2588
+ if (PROJECT_TYPE_ALIASES["chrome-extension"].includes(projectType[0])) {
2589
+ return await createChromeExtensionBom(path, options);
2590
+ }
2591
+ if (PROJECT_TYPE_ALIASES["dynamic"].includes(projectType[0])) {
2592
+ return await createDynamicBom(path, options);
2593
+ }
2594
+ if (PROJECT_TYPE_ALIASES["ai-provenance"].includes(projectType[0])) {
2595
+ return buildBomNSData(options, [], "ai-provenance", { src: path });
2596
+ }
2597
+ switch (projectType[0]) {
2598
+ case "jar":
2599
+ return createJarBom(path, options);
2600
+ case "gradle-index":
2601
+ case "gradle-cache":
2602
+ options.useGradleCache = true;
2603
+ return createJarBom(GRADLE_CACHE_DIR, options);
2604
+ case "sbt-index":
2605
+ case "sbt-cache":
2606
+ options.useSbtCache = true;
2607
+ return createJarBom(SBT_CACHE_DIR, options);
2608
+ case "maven-index":
2609
+ case "maven-cache":
2610
+ case "maven-repo":
2611
+ options.useMavenCache = true;
2612
+ return createJarBom(
2613
+ readEnvironmentVariable("MAVEN_CACHE_DIR") ||
2614
+ join(homedir(), ".m2", "repository"),
2615
+ options,
2616
+ );
2617
+ default:
2618
+ // In recurse mode return multi-language Bom
2619
+ // https://github.com/cdxgen/cdxgen/issues/95
2620
+ if (options.multiProject) {
2621
+ return await createMultiXBom(path, options);
2622
+ }
2623
+ return await createXBom(path, options);
2624
+ }
2625
+ }
2626
+
2627
+ /**
2628
+ * Method to submit the generated bom to dependency-track or cyclonedx server
2629
+ *
2630
+ * @param {Object} args CLI args
2631
+ * @param {Object} bomContents BOM Json
2632
+ * @return {Promise<{ token: string } | undefined>} a promise with a token (if request was successful) or undefined (in case of invalid arguments)
2633
+ * @throws {Error} if the request fails
2634
+ */
2635
+ export async function submitBom(args, bomContents) {
2636
+ const dependencyTrackApiUrl = getDependencyTrackBomApiUrl(args.serverUrl);
2637
+ const serverUrl = dependencyTrackApiUrl?.toString();
2638
+ if (!dependencyTrackApiUrl || !serverUrl) {
2639
+ console.log(
2640
+ "Invalid Dependency-Track server URL. Provide an absolute http(s) URL without dangerous characters.",
2641
+ );
2642
+ args.failOnError && process.exit(1);
2643
+ return undefined;
2644
+ }
2645
+ const serverHost = dependencyTrackApiUrl.hostname;
2646
+ if (!isAllowedHttpHost(serverHost)) {
2647
+ console.log(
2648
+ `Dependency-Track server host '${serverHost}' is not allowed by CDXGEN_ALLOWED_HOSTS.`,
2649
+ );
2650
+ args.failOnError && process.exit(1);
2651
+ return undefined;
2652
+ }
2653
+ if (isDryRun) {
2654
+ recordActivity({
2655
+ kind: "network",
2656
+ reason:
2657
+ "Dry run mode blocks Dependency-Track submission and reports the request instead.",
2658
+ status: "blocked",
2659
+ target: serverUrl,
2660
+ });
2661
+ return undefined;
2662
+ }
2663
+ const bomPayload = buildDependencyTrackBomPayload(args, bomContents);
2664
+ if (!bomPayload) {
2665
+ console.log(
2666
+ "Invalid Dependency-Track submission arguments. Provide projectId or projectName (projectVersion defaults to main) and specify parent project either by UUID or by parent project name + version.",
2667
+ );
2668
+ args.failOnError && process.exit(1);
2669
+ return;
2670
+ }
2671
+ if (DEBUG_MODE) {
2672
+ console.log(
2673
+ "Submitting BOM to",
2674
+ serverUrl,
2675
+ "params",
2676
+ args.projectName,
2677
+ bomPayload.projectVersion,
2678
+ );
2679
+ }
2680
+ try {
2681
+ const requestOptions = {
2682
+ method: "PUT",
2683
+ followRedirect: false,
2684
+ https: {
2685
+ rejectUnauthorized: !args.skipDtTlsCheck,
2686
+ },
2687
+ headers: {
2688
+ "X-Api-Key": (args.apiKey || "").replace(/[\r\n]/g, ""),
2689
+ "Content-Type": "application/json",
2690
+ },
2691
+ json: bomPayload,
2692
+ responseType: "json",
2693
+ context: {
2694
+ activityIntent: "bom-submit",
2695
+ },
2696
+ };
2697
+ if (DEBUG_MODE && args.skipDtTlsCheck) {
2698
+ console.log(
2699
+ "Calling ",
2700
+ serverUrl,
2701
+ "with --skip-dt-tls-check argument: Skip DT TLS check.",
2702
+ );
2703
+ }
2704
+ // See issue #1963 regarding CRLF hardening
2705
+ return await cdxgenAgent(dependencyTrackApiUrl, requestOptions).json();
2706
+ } catch (error) {
2707
+ if (error.response && error.response.statusCode === 401) {
2708
+ // Unauthorized
2709
+ console.log(
2710
+ "Received Unauthorized error. Check the API key used is valid and has necessary permissions to create projects and upload bom.",
2711
+ );
2712
+ } else if (error.response && error.response.statusCode === 405) {
2713
+ console.log(
2714
+ "Method PUT not allowed on Dependency-Track server. Trying with POST ...",
2715
+ );
2716
+ // Method not allowed errors
2717
+ try {
2718
+ return await cdxgenAgent(dependencyTrackApiUrl, {
2719
+ method: "POST",
2720
+ followRedirect: false,
2721
+ https: {
2722
+ rejectUnauthorized: !args.skipDtTlsCheck,
2723
+ },
2724
+ headers: {
2725
+ "X-Api-Key": (args.apiKey || "").replace(/[\r\n]/g, ""),
2726
+ "Content-Type": "application/json",
2727
+ },
2728
+ json: bomPayload,
2729
+ responseType: "json",
2730
+ context: {
2731
+ activityIntent: "bom-submit",
2732
+ },
2733
+ }).json();
2734
+ } catch (error) {
2735
+ if (DEBUG_MODE) {
2736
+ console.log(
2737
+ "Unable to submit the SBOM to the Dependency-Track server using POST method",
2738
+ error,
2739
+ );
2740
+ } else {
2741
+ console.log(
2742
+ "Unable to submit the SBOM to the Dependency-Track server using POST method",
2743
+ );
2744
+ }
2745
+ }
2746
+ } else {
2747
+ if (DEBUG_MODE) {
2748
+ console.log(
2749
+ "Unable to submit the SBOM to the Dependency-Track server using POST method",
2750
+ error,
2751
+ );
2752
+ } else {
2753
+ console.log("Unable to submit the SBOM to the Dependency-Track server");
2754
+ }
2755
+ }
2756
+ // rethrow error as function is async and we should try to catch it in the caller
2757
+ throw error;
2758
+ }
2759
+ }