@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,1882 @@
1
+ import { Buffer } from "node:buffer";
2
+ import { randomUUID as uuidv4 } from "node:crypto";
3
+ import { lstatSync, readFileSync } from "node:fs";
4
+ import { basename, dirname, join, relative, resolve, sep } from "node:path";
5
+
6
+ import { build, Purl } from "@cdxgen/cdx-purl";
7
+ import { parse } from "ssri";
8
+
9
+ import {
10
+ DEBUG_MODE,
11
+ recordActivity,
12
+ resetActivityContext,
13
+ setActivityContext,
14
+ } from "../core/activity.js";
15
+ import { PROJECT_TYPE_ALIASES } from "../core/env.js";
16
+ import {
17
+ getTimestamp,
18
+ getTmpDir,
19
+ safeExistsSync,
20
+ safeMkdtempSync,
21
+ } from "../core/fs.js";
22
+ import {
23
+ CDXGEN_TOOL_GROUP,
24
+ CDXGEN_TOOL_NAME,
25
+ CDXGEN_VERSION,
26
+ frameworksList,
27
+ } from "../core/state.js";
28
+ import { isPkgTypeOnlyImport } from "../ecosystems/npmutils.js";
29
+ import { parsePackageJsonName } from "../ecosystems/parsers-js.js";
30
+ import {
31
+ AI_INSTRUCTION_FILE_KINDS,
32
+ AI_INVENTORY_PROJECT_TYPES,
33
+ AI_SKILL_FILE_KIND,
34
+ inventoryPropertyValue,
35
+ MCP_CONFIG_FILE_KIND,
36
+ optionIncludesAiInventoryProjectType,
37
+ summarizeAiInventory,
38
+ } from "../inventory/aiInventory.js";
39
+ import { expandBomAuditCategories } from "../inventory/auditCategories.js";
40
+ import {
41
+ DEFAULT_CDX_SPEC_VERSION,
42
+ setCycloneDxFormat,
43
+ toCycloneDxSpecVersionString,
44
+ } from "../inventory/bomUtils.js";
45
+ import { mergeServices, trimComponents } from "../inventory/depsUtils.js";
46
+ import {
47
+ attachIdentityTools,
48
+ extractToolRefs,
49
+ } from "../inventory/evidenceUtils.js";
50
+ import { enrichComponentWithMcpMetadata } from "../inventory/mcp.js";
51
+ import {
52
+ applyPurl,
53
+ encodeForPurl,
54
+ isValidPurl,
55
+ npmPurl,
56
+ tryBuildPurl,
57
+ } from "../inventory/purl.js";
58
+ import { repairPurl } from "../inventory/sbomDocument.js";
59
+ import { getLicenses } from "../inventory/spdx.js";
60
+ import { getBinaryBom } from "../managers/binary.js";
61
+ import { isValidIriReference } from "../parsers/iri.js";
62
+
63
+ /**
64
+ * Determines whether the `node_modules` directory should be scanned for the
65
+ * current run. Scanning is always performed in deep mode or when no project
66
+ * type is selected; otherwise the selected types must include at least one of
67
+ * the requested base project types.
68
+ *
69
+ * @param {object} options CLI options
70
+ * @param {string[]} baseProjectTypes Base project types that require the scan
71
+ * @returns {boolean} True when `node_modules` should be included in the scan
72
+ */
73
+ export const shouldIncludeNodeModulesDir = (
74
+ options = {},
75
+ baseProjectTypes = [],
76
+ ) => {
77
+ if (options.deep) {
78
+ return true;
79
+ }
80
+ const projectTypes = Array.isArray(options.projectType)
81
+ ? options.projectType
82
+ : options.projectType
83
+ ? [options.projectType]
84
+ : [];
85
+ if (!projectTypes.length) {
86
+ return true;
87
+ }
88
+ return baseProjectTypes.some((projectType) =>
89
+ projectTypes.every((selectedProjectType) =>
90
+ PROJECT_TYPE_ALIASES[projectType]?.includes(selectedProjectType),
91
+ ),
92
+ );
93
+ };
94
+
95
+ /**
96
+ * Regex source string that matches hex digests of common lengths
97
+ * (32, 40, 64, 96, or 128 characters) used for integrity validation.
98
+ *
99
+ * @type {string}
100
+ */
101
+ export const HASH_PATTERN =
102
+ "^([a-fA-F0-9]{32}|[a-fA-F0-9]{40}|[a-fA-F0-9]{64}|[a-fA-F0-9]{96}|[a-fA-F0-9]{128})$";
103
+
104
+ /**
105
+ * Creates a default parent component based on the directory name.
106
+ *
107
+ * @param {String} path Directory or file name
108
+ * @param {String} type Package type
109
+ * @param {Object} options CLI options
110
+ * @returns component object
111
+ */
112
+ export const createDefaultParentComponent = (
113
+ path,
114
+ type = "application",
115
+ options = {},
116
+ ) => {
117
+ // Expands any relative path such as dot
118
+ path = resolve(path);
119
+ // Create a parent component based on the directory name
120
+ let dirNameStr =
121
+ safeExistsSync(path) && lstatSync(path).isDirectory()
122
+ ? basename(path)
123
+ : dirname(path);
124
+ const tmpA = dirNameStr.split(sep);
125
+ dirNameStr = tmpA[tmpA.length - 1];
126
+ const compName = "project-name" in options ? options.projectName : dirNameStr;
127
+ const parentComponent = {
128
+ group: options.projectGroup || "",
129
+ name: compName,
130
+ version: `${options.projectVersion || "latest"}`,
131
+ type:
132
+ type === "container" || compName.endsWith(".tar")
133
+ ? "container"
134
+ : "application",
135
+ };
136
+ // Strict purl validation (swift requires a namespace, maven a groupId)
137
+ // rejects root application components that have no group. applyPurl then
138
+ // omits the purl rather than inventing one, and derives a unique bom-ref.
139
+ applyPurl(
140
+ parentComponent,
141
+ tryBuildPurl({
142
+ type: type,
143
+ namespace: parentComponent.group || null,
144
+ name: parentComponent.name,
145
+ version: parentComponent.version || null,
146
+ }),
147
+ );
148
+ return parentComponent;
149
+ };
150
+
151
+ /**
152
+ * Builds the parent (metadata.component) for the BOM from the
153
+ * `--project-name`/`--project-version`/`--project-group` CLI options,
154
+ * constructing a purl and bom-ref. Returns the caller-supplied
155
+ * `options.parentComponent` unchanged when present.
156
+ *
157
+ * @param {object} options CLI options
158
+ * @returns {object|undefined} Parent component object, or undefined when no
159
+ * project name/version is available
160
+ */
161
+ export const determineParentComponent = (options) => {
162
+ let parentComponent;
163
+ if (options.parentComponent && Object.keys(options.parentComponent).length) {
164
+ return options.parentComponent;
165
+ }
166
+ if (options.projectName && options.projectVersion) {
167
+ parentComponent = {
168
+ group: options.projectGroup || "",
169
+ name: options.projectName,
170
+ version: `${options.projectVersion}` || "",
171
+ type: "application",
172
+ };
173
+ const ppurl = build({
174
+ type: parentComponent.type,
175
+ namespace: parentComponent.group || null,
176
+ name: parentComponent.name,
177
+ version: parentComponent.version || null,
178
+ });
179
+ parentComponent["bom-ref"] = decodeURIComponent(ppurl);
180
+ parentComponent["purl"] = ppurl;
181
+ }
182
+ return parentComponent;
183
+ };
184
+
185
+ /**
186
+ * Re-anchor a dependency graph onto a caller-supplied parent component.
187
+ *
188
+ * A generator builds its `dependencies[]` around the parent it detected from
189
+ * the manifest it read. `--project-name`/`--project-version` and an explicit
190
+ * `parentComponent` replace that parent in `metadata.component`, which leaves
191
+ * the graph rooted at a `bom-ref` that appears nowhere in the document — every
192
+ * edge the generator produced hangs off a dangling ref.
193
+ *
194
+ * The detected parent is real: it is the project the manifest describes, and
195
+ * the supplied parent is the larger thing that contains it. So it is kept as a
196
+ * component and an edge is drawn from the supplied parent to it, which is the
197
+ * CycloneDX way to express a subproject and preserves every edge below it.
198
+ *
199
+ * @param {object|undefined} overrideParent Parent supplied through the options
200
+ * @param {object|undefined} detectedParent Parent the generator derived
201
+ * @param {object[]} components The component list, appended to in place
202
+ * @param {object[]} dependencies Edges the generator produced
203
+ * @returns {object[]} Edges to emit, re-anchored when an override applies
204
+ */
205
+ function anchorDetectedParent(
206
+ overrideParent,
207
+ detectedParent,
208
+ components,
209
+ dependencies,
210
+ ) {
211
+ const detectedRef = detectedParent?.["bom-ref"];
212
+ const overrideRef = overrideParent?.["bom-ref"];
213
+ if (!detectedRef || !overrideRef || detectedRef === overrideRef) {
214
+ return dependencies;
215
+ }
216
+ if (!dependencies.some((dep) => dep.ref === detectedRef)) {
217
+ return dependencies;
218
+ }
219
+ if (
220
+ Array.isArray(components) &&
221
+ !components.some((comp) => comp["bom-ref"] === detectedRef)
222
+ ) {
223
+ // The detected parent carries transient keys (`license`, `evidence`,
224
+ // `_integrity`, `qualifiers`, `repository`, `homepage`) that only
225
+ // `metadata.component` is cleaned of. As a regular component it must go
226
+ // through the same conversion or schema validation rejects the document
227
+ // (issue #4320). The copy keeps the caller's context object untouched.
228
+ components.push(cleanParentComponent({ ...detectedParent }));
229
+ }
230
+ // The caller owns the array it passed, and postProcess merges these edges
231
+ // across generators, so the re-anchoring is returned rather than spliced in.
232
+ const anchored = [];
233
+ let linked = false;
234
+ for (const dep of dependencies) {
235
+ if (dep.ref !== overrideRef) {
236
+ anchored.push(dep);
237
+ continue;
238
+ }
239
+ linked = true;
240
+ anchored.push({
241
+ ...dep,
242
+ dependsOn: Array.from(new Set([...(dep.dependsOn || []), detectedRef])),
243
+ });
244
+ }
245
+ if (!linked) {
246
+ anchored.unshift({ ref: overrideRef, dependsOn: [detectedRef] });
247
+ }
248
+ return anchored;
249
+ }
250
+
251
+ /**
252
+ * Assembles the `metadata.tools` block, including the cdxgen tool entry and,
253
+ * for spec versions prior to 1.5, the legacy tools array. For spec version
254
+ * 1.6+ the author field is converted to the authors array.
255
+ *
256
+ * @param {object} options CLI options
257
+ * @param {object} [context={}] Additional context carrying existing components
258
+ * @returns {{ components?: object[], tools?: object[] }} Object containing the
259
+ * tools array (1.4) or a components array with tool components (1.5+)
260
+ */
261
+ export const addToolsSection = (options, context = {}) => {
262
+ if (options.specVersion === 1.4) {
263
+ return [
264
+ {
265
+ vendor: "cyclonedx",
266
+ name: "cdxgen",
267
+ version: CDXGEN_VERSION,
268
+ },
269
+ ];
270
+ }
271
+ let components = [];
272
+ const tools = options.tools || context.tools || [];
273
+ // tools can be an object or array
274
+ if (Array.isArray(tools) && tools.length) {
275
+ // cyclonedx-maven-plugin has the legacy tools metadata which needs to be patched
276
+ for (const tool of tools) {
277
+ if (!tool.type) {
278
+ tool.type = "application";
279
+ if (tool.vendor) {
280
+ tool.publisher = tool.vendor;
281
+ delete tool.vendor;
282
+ }
283
+ }
284
+ }
285
+ components = components.concat(tools);
286
+ } else if (tools && Object.keys(tools).length && tools.components) {
287
+ components = components.concat(tools.components);
288
+ }
289
+ const cdxToolComponent = {
290
+ group: CDXGEN_TOOL_GROUP,
291
+ name: CDXGEN_TOOL_NAME,
292
+ version: CDXGEN_VERSION,
293
+ purl: npmPurl(`${CDXGEN_TOOL_GROUP}/${CDXGEN_TOOL_NAME}`, CDXGEN_VERSION),
294
+ type: "application",
295
+ "bom-ref": `pkg:npm/${CDXGEN_TOOL_GROUP}/${CDXGEN_TOOL_NAME}@${CDXGEN_VERSION}`,
296
+ author: "OWASP Foundation",
297
+ publisher: "OWASP Foundation",
298
+ };
299
+ if (options.specVersion >= 1.6) {
300
+ cdxToolComponent.authors = [{ name: "OWASP Foundation" }];
301
+ delete cdxToolComponent.author;
302
+ }
303
+ components.push(cdxToolComponent);
304
+ return { components };
305
+ };
306
+
307
+ /**
308
+ * Renders a component's group/name@version as a simple display string.
309
+ *
310
+ * @param {object} comp Component object
311
+ * @returns {string} `group/name@version`, `name@version`, or `name`
312
+ */
313
+ export const componentToSimpleFullName = (comp) => {
314
+ let fullName = comp.group?.length ? `${comp.group}/${comp.name}` : comp.name;
315
+ if (comp.version?.length) {
316
+ fullName = `${fullName}@${comp.version}`;
317
+ }
318
+ return fullName;
319
+ };
320
+
321
+ /**
322
+ * Strips transient keys (`evidence`, `_integrity`, `license`, `qualifiers`,
323
+ * `repository`, `homepage`) from a parent component while preserving licenses
324
+ * and external references (bug #1519).
325
+ *
326
+ * @param {object} comp Parent component to clean in place
327
+ * @returns {object} The cleaned parent component
328
+ */
329
+ // Remove unwanted properties from parent component
330
+ // Bug #1519 - Retain licenses and external references
331
+ export const cleanParentComponent = (comp) => {
332
+ delete comp.evidence;
333
+ delete comp._integrity;
334
+ if (comp.license) {
335
+ const licenses = getLicenses(comp);
336
+ if (licenses?.length) {
337
+ comp.licenses = licenses;
338
+ }
339
+ }
340
+ delete comp.license;
341
+ delete comp.qualifiers;
342
+ if (comp.repository || comp.homepage) {
343
+ const externalReferences = addExternalReferences(comp);
344
+ if (externalReferences?.length) {
345
+ comp.externalReferences = externalReferences;
346
+ }
347
+ }
348
+ delete comp.repository;
349
+ delete comp.homepage;
350
+ return comp;
351
+ };
352
+
353
+ /**
354
+ * Builds the `metadata.authors` array from `options.author`, which may be a
355
+ * single string or an array of author strings. Entries shorter than two
356
+ * characters are ignored.
357
+ *
358
+ * @param {object} options CLI options
359
+ * @returns {object[]} Author objects of the form `{ name }`
360
+ */
361
+ export const addAuthorsSection = (options) => {
362
+ const authors = [];
363
+ if (options.author) {
364
+ const oauthors = Array.isArray(options.author)
365
+ ? options.author
366
+ : [options.author];
367
+ for (const aauthor of oauthors) {
368
+ if (aauthor.trim().length < 2) {
369
+ continue;
370
+ }
371
+ authors.push({ name: aauthor });
372
+ }
373
+ }
374
+ return authors;
375
+ };
376
+
377
+ /**
378
+ * Method to generate metadata.lifecycles section. We assume that we operate during "build"
379
+ * most of the time and under "post-build" for containers.
380
+ *
381
+ * @param {Object} options
382
+ * @returns {Array} Lifecycles array
383
+ */
384
+ export const addLifecyclesSection = (options) => {
385
+ // If lifecycle was set via CLI arguments, reuse the value
386
+ if (options.lifecycle) {
387
+ return [{ phase: options.lifecycle }];
388
+ }
389
+ const lifecycles = [{ phase: options.installDeps ? "build" : "pre-build" }];
390
+ if (options.exportData) {
391
+ const inspectData = options.exportData.inspectData;
392
+ if (inspectData) {
393
+ lifecycles.push({ phase: "post-build" });
394
+ }
395
+ } else if (
396
+ options?.projectType?.length &&
397
+ options?.projectType?.includes("binary")
398
+ ) {
399
+ lifecycles.push({ phase: "post-build" });
400
+ }
401
+ if (options.projectType?.includes("os")) {
402
+ lifecycles.push({ phase: "operations" });
403
+ }
404
+ return lifecycles;
405
+ };
406
+
407
+ /**
408
+ * Function to create metadata block
409
+ *
410
+ */
411
+ export function addMetadata(parentComponent = {}, options = {}, context = {}) {
412
+ // DO NOT fork this project to just change the vendor or author's name
413
+ // Try to contribute to this project by sending PR or filing issues
414
+ const tools = addToolsSection(options, context);
415
+ const authors = addAuthorsSection(options);
416
+ const lifecycles =
417
+ options.specVersion >= 1.5 ? addLifecyclesSection(options) : undefined;
418
+ const metadata = {
419
+ timestamp: getTimestamp(),
420
+ tools,
421
+ authors,
422
+ supplier: undefined,
423
+ };
424
+ if (lifecycles) {
425
+ metadata.lifecycles = lifecycles;
426
+ }
427
+ // TLP classification
428
+ if (options.specVersion >= 1.7 && options?.tlpClassification) {
429
+ metadata.distributionConstraints = { tlp: options.tlpClassification };
430
+ }
431
+ if (parentComponent && Object.keys(parentComponent).length) {
432
+ if (parentComponent) {
433
+ cleanParentComponent(parentComponent);
434
+ // Recover a purl from the bom-ref only when the bom-ref genuinely is
435
+ // one. Parsers that cannot build a valid purl (a swift package with no
436
+ // remote URL, a maven module with no groupId) deliberately fall back to a
437
+ // name-based bom-ref, and blindly copying that here manufactured invalid
438
+ // purls such as `"purl": "swift-smoke"`. CycloneDX requires `purl` to be
439
+ // a valid Package URL when present, so absent is the only correct answer.
440
+ if (!parentComponent["purl"] && parentComponent["bom-ref"]) {
441
+ const candidate = encodeForPurl(parentComponent["bom-ref"]);
442
+ if (isValidPurl(candidate)) {
443
+ parentComponent["purl"] = candidate;
444
+ }
445
+ }
446
+ }
447
+ if (parentComponent?.components) {
448
+ parentComponent.components = listComponents(
449
+ options,
450
+ {},
451
+ parentComponent.components,
452
+ );
453
+ const parentFullName = componentToSimpleFullName(parentComponent);
454
+ const subComponents = [];
455
+ const addedSubComponents = {};
456
+ for (const comp of parentComponent.components) {
457
+ cleanParentComponent(comp);
458
+ if (comp.name && comp.type) {
459
+ const fullName = componentToSimpleFullName(comp);
460
+ // Fixes #479
461
+ // Prevent the parent component from also appearing as a sub-component
462
+ // We cannot use purl or bom-ref here since they would not match
463
+ // purl - could have application on one side and a different type
464
+ // bom-ref could have qualifiers on one side
465
+ if (fullName !== parentFullName) {
466
+ if (!comp["bom-ref"]) {
467
+ comp["bom-ref"] = `pkg:${comp.type}/${decodeURIComponent(
468
+ fullName,
469
+ )}`;
470
+ }
471
+ if (!addedSubComponents[comp["bom-ref"]]) {
472
+ subComponents.push(comp);
473
+ addedSubComponents[comp["bom-ref"]] = true;
474
+ }
475
+ }
476
+ }
477
+ } // for
478
+ // Avoid creating empty component.components attribute
479
+ if (subComponents.length) {
480
+ parentComponent.components = subComponents;
481
+ } else {
482
+ parentComponent.components = undefined;
483
+ }
484
+ }
485
+ // Convert authors to author for specVersion < 1.6
486
+ const parentComponentCopy = { ...parentComponent };
487
+
488
+ if (options.specVersion < 1.6 && parentComponent?.authors) {
489
+ parentComponentCopy.author = parentComponentCopy.authors
490
+ .map((a) => (a.email ? `${a.name} <${a.email}>` : a.name))
491
+ .join(",");
492
+ delete parentComponentCopy.authors;
493
+ }
494
+
495
+ metadata.component = parentComponent;
496
+ }
497
+ // Have we already captured the oci properties
498
+ if (metadata?.properties?.some((prop) => prop.name === "oci:image:Id")) {
499
+ return metadata;
500
+ }
501
+ if (options) {
502
+ const mproperties = [];
503
+ if (options.exportData) {
504
+ const inspectData = options.exportData.inspectData;
505
+ if (inspectData) {
506
+ if (inspectData.Id) {
507
+ mproperties.push({
508
+ name: "oci:image:Id",
509
+ value: inspectData.Id,
510
+ });
511
+ }
512
+ if (
513
+ inspectData.RepoTags &&
514
+ Array.isArray(inspectData.RepoTags) &&
515
+ inspectData.RepoTags.length
516
+ ) {
517
+ mproperties.push({
518
+ name: "oci:image:RepoTag",
519
+ value: inspectData.RepoTags[0],
520
+ });
521
+ }
522
+ if (
523
+ inspectData.RepoDigests &&
524
+ Array.isArray(inspectData.RepoDigests) &&
525
+ inspectData.RepoDigests.length
526
+ ) {
527
+ mproperties.push({
528
+ name: "oci:image:RepoDigest",
529
+ value: inspectData.RepoDigests[0],
530
+ });
531
+ }
532
+ if (inspectData.Created) {
533
+ mproperties.push({
534
+ name: "oci:image:Created",
535
+ value: inspectData.Created,
536
+ });
537
+ }
538
+ if (inspectData.Architecture) {
539
+ mproperties.push({
540
+ name: "oci:image:Architecture",
541
+ value: inspectData.Architecture,
542
+ });
543
+ }
544
+ if (inspectData.Os) {
545
+ mproperties.push({
546
+ name: "oci:image:Os",
547
+ value: inspectData.Os,
548
+ });
549
+ }
550
+ }
551
+ const manifestList = options.exportData.manifest;
552
+ if (manifestList && Array.isArray(manifestList) && manifestList.length) {
553
+ const manifest = manifestList[0] || {};
554
+ if (manifest.Config) {
555
+ mproperties.push({
556
+ name: "oci:image:manifest:Config",
557
+ value: manifest.Config,
558
+ });
559
+ }
560
+ if (
561
+ manifest.Layers &&
562
+ Array.isArray(manifest.Layers) &&
563
+ manifest.Layers.length
564
+ ) {
565
+ mproperties.push({
566
+ name: "oci:image:manifest:Layers",
567
+ value: manifest.Layers.join("\\n"),
568
+ });
569
+ }
570
+ }
571
+ const lastLayerConfig = options.exportData.lastLayerConfig;
572
+ if (lastLayerConfig) {
573
+ if (lastLayerConfig.id) {
574
+ mproperties.push({
575
+ name: "oci:image:lastLayer:Id",
576
+ value: lastLayerConfig.id,
577
+ });
578
+ }
579
+ if (lastLayerConfig.parent) {
580
+ mproperties.push({
581
+ name: "oci:image:lastLayer:ParentId",
582
+ value: lastLayerConfig.parent,
583
+ });
584
+ }
585
+ if (lastLayerConfig.created) {
586
+ mproperties.push({
587
+ name: "oci:image:lastLayer:Created",
588
+ value: lastLayerConfig.created,
589
+ });
590
+ }
591
+ }
592
+ const layerConfig =
593
+ lastLayerConfig?.config || options.exportData?.inspectData;
594
+ if (layerConfig) {
595
+ const env = layerConfig?.config?.Env || layerConfig?.Config?.Env;
596
+ if (env && Array.isArray(env) && env.length) {
597
+ mproperties.push({
598
+ name: "oci:image:lastLayer:Env",
599
+ value: env.join("\\n"),
600
+ });
601
+ // Does the image have any special packages that cdxgen cannot detect such as android-sdk and sdkman
602
+ const evalue = env.join(":");
603
+ if (
604
+ evalue.includes("android-sdk") ||
605
+ evalue.includes("commandlinetools")
606
+ ) {
607
+ mproperties.push({
608
+ name: "oci:image:bundles:AndroidSdk",
609
+ value: "true",
610
+ });
611
+ }
612
+ // Track the use of special environment variables that could influence the search paths for libraries
613
+ // This list was generated by repeatedly prompting ChatGPT with examples.
614
+ // FIXME: Move these to a config file
615
+ for (const senvValue of [
616
+ "LD_LIBRARY_PATH",
617
+ "DYLD_LIBRARY_PATH",
618
+ "LD_PRELOAD",
619
+ "PYTHONPATH",
620
+ "CLASSPATH",
621
+ "PERL5LIB",
622
+ "PERLLIB",
623
+ "RUBYLIB",
624
+ "NODE_PATH",
625
+ "LUA_PATH",
626
+ "JULIA_LOAD_PATH",
627
+ "R_LIBS",
628
+ "R_LIBS_USER",
629
+ "GEM_PATH",
630
+ "DOTNET_ROOT",
631
+ "DOTNET_ADDITIONAL_DEPS",
632
+ "DOTNET_SHARED_STORE",
633
+ "DOTNET_STARTUP_HOOKS",
634
+ "DOTNET_BUNDLE_EXTRACT_BASE_DIR",
635
+ "JAVA_OPTIONS",
636
+ "JAVA_TOOL_OPTIONS",
637
+ "NODE_OPTIONS",
638
+ "PYTHONSTARTUP",
639
+ "RUBYOPT",
640
+ "WGETRC",
641
+ "APT_CONFIG",
642
+ "NPM_CONFIG_PREFIX",
643
+ "NPM_CONFIG_REGISTRY",
644
+ "YARN_CACHE_FOLDER",
645
+ "PNPM_STORE_PATH",
646
+ "PNPM_HOME",
647
+ "PNPM_CONFIG_",
648
+ "GIO_MODULE_DIR",
649
+ "GST_PLUGIN_PATH",
650
+ "GST_PLUGIN_SYSTEM_PATH",
651
+ "APPDIR_LIBRARY_PATH", // appimage specific which gets prepended to LD_LIBRARY_PATH
652
+ ]) {
653
+ if (evalue.includes(senvValue)) {
654
+ mproperties.push({
655
+ name: `oci:image:env:${senvValue}`,
656
+ value: "true",
657
+ });
658
+ }
659
+ }
660
+ // This value represents a filtered and expanded path
661
+ if (options?.binPaths?.length) {
662
+ mproperties.push({
663
+ name: "oci:image:env:PATH",
664
+ value: options.binPaths.join(":"),
665
+ });
666
+ }
667
+ if (evalue.includes(".sdkman")) {
668
+ mproperties.push({
669
+ name: "oci:image:bundles:Sdkman",
670
+ value: "true",
671
+ });
672
+ }
673
+ if (evalue.includes(".nvm")) {
674
+ mproperties.push({
675
+ name: "oci:image:bundles:Nvm",
676
+ value: "true",
677
+ });
678
+ }
679
+ if (evalue.includes(".rbenv")) {
680
+ mproperties.push({
681
+ name: "oci:image:bundles:Rbenv",
682
+ value: "true",
683
+ });
684
+ }
685
+ }
686
+ const ccmd =
687
+ layerConfig?.config?.Cmd ||
688
+ layerConfig?.Config?.Cmd ||
689
+ layerConfig?.Config?.EntryPoint;
690
+ if (ccmd) {
691
+ if (Array.isArray(ccmd) && ccmd.length) {
692
+ const fullCommand = ccmd.join(" ");
693
+ mproperties.push({
694
+ name: "oci:image:lastLayer:Cmd",
695
+ value: fullCommand,
696
+ });
697
+ let appLanguage;
698
+ // TODO: Move these lists to a config file.
699
+ for (const lang in [
700
+ "java",
701
+ "node",
702
+ "dotnet",
703
+ "python",
704
+ "python3",
705
+ "ruby",
706
+ "php",
707
+ "php7",
708
+ "php8",
709
+ "perl",
710
+ ]) {
711
+ if (fullCommand.includes(`${lang} `)) {
712
+ appLanguage = lang;
713
+ break;
714
+ }
715
+ }
716
+ if (appLanguage) {
717
+ mproperties.push({
718
+ name: "oci:image:appLanguage",
719
+ value: appLanguage,
720
+ });
721
+ }
722
+ } else {
723
+ mproperties.push({
724
+ name: "oci:image:lastLayer:Cmd",
725
+ value: ccmd.toString(),
726
+ });
727
+ }
728
+ }
729
+ }
730
+ }
731
+ if (options.allOSComponentTypes?.length) {
732
+ mproperties.push({
733
+ name: "oci:image:componentTypes",
734
+ value: options.allOSComponentTypes.sort().join("\\n"),
735
+ });
736
+ }
737
+ if (Number.isInteger(options?.unpackagedExecutableCount)) {
738
+ mproperties.push({
739
+ name: "cdx:container:unpackagedExecutableCount",
740
+ value: String(options.unpackagedExecutableCount),
741
+ });
742
+ }
743
+ if (Number.isInteger(options?.unpackagedSharedLibraryCount)) {
744
+ mproperties.push({
745
+ name: "cdx:container:unpackagedSharedLibraryCount",
746
+ value: String(options.unpackagedSharedLibraryCount),
747
+ });
748
+ }
749
+ // Should we move these to formulation?
750
+ if (options?.bundledSdks?.length) {
751
+ for (const sdk of options.bundledSdks) {
752
+ try {
753
+ const purlObj = Purl.parse(sdk);
754
+ const sdkName = purlObj.name.split("-")[0].toLowerCase();
755
+ mproperties.push({
756
+ name: `oci:image:bundles:${sdkName}Sdk`,
757
+ value: "true",
758
+ });
759
+ } catch (_e) {
760
+ // ignore
761
+ }
762
+ }
763
+ }
764
+ if (options?.bundledRuntimes?.length) {
765
+ for (const runt of options.bundledRuntimes) {
766
+ mproperties.push({
767
+ name: `oci:image:bundles:${runt}Runtime`,
768
+ value: "true",
769
+ });
770
+ }
771
+ }
772
+ // AI provenance/oversight detection (`-t ai-provenance`) is injected into the
773
+ // BOM document root (bomJson.properties) after post-processing, not into
774
+ // metadata.properties. See ensureAiProvenanceProperties/ensureAiOversightProperties.
775
+ if (mproperties.length) {
776
+ metadata.properties = mproperties;
777
+ }
778
+ }
779
+ return metadata;
780
+ }
781
+
782
+ /**
783
+ * Method to create external references
784
+ *
785
+ * @param {Array | Object} opkg
786
+ * @returns {Array}
787
+ */
788
+ export function addExternalReferences(opkg) {
789
+ let externalReferences = [];
790
+ let pkgList;
791
+ if (Array.isArray(opkg)) {
792
+ pkgList = opkg;
793
+ } else {
794
+ pkgList = [opkg];
795
+ }
796
+ for (const pkg of pkgList) {
797
+ if (pkg.externalReferences) {
798
+ externalReferences = externalReferences.concat(pkg.externalReferences);
799
+ } else {
800
+ if (pkg.homepage?.url) {
801
+ externalReferences.push({
802
+ type: pkg.homepage.url.includes("git") ? "vcs" : "website",
803
+ url: pkg.homepage.url,
804
+ });
805
+ }
806
+ if (pkg.bugs?.url) {
807
+ externalReferences.push({
808
+ type: "issue-tracker",
809
+ url: pkg.bugs.url,
810
+ });
811
+ }
812
+ if (pkg.repository?.url) {
813
+ externalReferences.push({
814
+ type: "vcs",
815
+ url: pkg.repository.url,
816
+ });
817
+ }
818
+ if (pkg.distribution?.url) {
819
+ externalReferences.push({
820
+ type: "distribution",
821
+ url: pkg.distribution.url,
822
+ });
823
+ }
824
+ }
825
+ }
826
+ return externalReferences
827
+ .map((reference) => ({ ...reference, url: reference.url.trim() }))
828
+ .filter((reference) => isValidIriReference(reference.url));
829
+ }
830
+
831
+ /**
832
+ * For all modules in the specified package, creates a list of
833
+ * component objects from each one.
834
+ *
835
+ * @param {Object} options CLI options
836
+ * @param {Object} allImports All imports
837
+ * @param {Object} pkg Package object
838
+ * @param {string} ptype Package type
839
+ * @returns {Object[]} Array of component objects
840
+ */
841
+ export function listComponents(options, allImports, pkg, ptype = "npm") {
842
+ const compMap = {};
843
+ const isRootPkg = ptype === "npm";
844
+ if (Array.isArray(pkg)) {
845
+ pkg.forEach((p) => {
846
+ addComponent(options, allImports, p, ptype, compMap, false);
847
+ });
848
+ } else {
849
+ addComponent(options, allImports, pkg, ptype, compMap, isRootPkg);
850
+ }
851
+
852
+ return Object.keys(compMap).map((k) => compMap[k]);
853
+ }
854
+
855
+ /**
856
+ * Component types that never receive an ecosystem purl.
857
+ *
858
+ * @type {string[]}
859
+ */
860
+ // These component types do not have PURLs
861
+ export const NON_PURL_TYPES = ["cryptographic-asset", "file", "data"];
862
+
863
+ /**
864
+ * Property-name prefix used to key npm bin-command import evidence
865
+ * (`cdx:npm:bin/`).
866
+ *
867
+ * @type {string}
868
+ */
869
+ export const NPM_BIN_IMPORT_PREFIX = "cdx:npm:bin/";
870
+
871
+ /**
872
+ * Returns all non-empty property values for a given property name on a package.
873
+ *
874
+ * @param {object} pkg Package/component object with an optional `properties` array
875
+ * @param {string} propertyName Property name to match
876
+ * @returns {string[]} Matching property values as strings
877
+ */
878
+ export function getPackagePropertyValues(pkg, propertyName) {
879
+ if (!Array.isArray(pkg?.properties)) {
880
+ return [];
881
+ }
882
+ return pkg.properties
883
+ .filter((property) => property.name === propertyName && property.value)
884
+ .map((property) => String(property.value));
885
+ }
886
+
887
+ /**
888
+ * Splits a comma-separated property value into a trimmed, non-empty string array.
889
+ *
890
+ * @param {string} value Comma-separated value
891
+ * @returns {string[]} Trimmed list entries
892
+ */
893
+ export function splitPackagePropertyList(value) {
894
+ return String(value || "")
895
+ .split(",")
896
+ .map((item) => item.trim())
897
+ .filter(Boolean);
898
+ }
899
+
900
+ /**
901
+ * Collects the set of bin command names an npm package exposes, derived from
902
+ * the `bin` field and the `cdx:npm:bin` / `cdx:npm:binPaths` properties.
903
+ *
904
+ * @param {object} pkg Package object
905
+ * @returns {Set<string>} Bin command names
906
+ */
907
+ export function getPackageBinCommandNames(pkg) {
908
+ const binNames = new Set();
909
+ if (pkg?.bin && typeof pkg.bin === "object") {
910
+ for (const binName of Object.keys(pkg.bin)) {
911
+ binNames.add(binName);
912
+ }
913
+ } else if (typeof pkg?.bin === "string") {
914
+ binNames.add(pkg.name);
915
+ }
916
+ for (const binValue of getPackagePropertyValues(pkg, "cdx:npm:bin")) {
917
+ for (const binName of splitPackagePropertyList(binValue)) {
918
+ binNames.add(binName);
919
+ }
920
+ }
921
+ for (const binPathValue of getPackagePropertyValues(
922
+ pkg,
923
+ "cdx:npm:binPaths",
924
+ )) {
925
+ for (const binPath of splitPackagePropertyList(binPathValue)) {
926
+ const normalizedBinPath = binPath.replaceAll("\\", "/");
927
+ const binName = normalizedBinPath.split("/").filter(Boolean).pop();
928
+ if (binName) {
929
+ binNames.add(binName);
930
+ }
931
+ }
932
+ }
933
+ return binNames;
934
+ }
935
+
936
+ /**
937
+ * Checks whether any bin command of a package appears in the analyzer import
938
+ * evidence (keyed under `cdx:npm:bin/`).
939
+ *
940
+ * @param {object} allImports Map of import names to usage counts
941
+ * @param {object} pkg Package object
942
+ * @returns {boolean} True when at least one bin command is imported
943
+ */
944
+ export function hasNpmBinCommandEvidence(allImports, pkg) {
945
+ const binCommandNames = getPackageBinCommandNames(pkg);
946
+ if (!binCommandNames.size) {
947
+ return false;
948
+ }
949
+ for (const importName of Object.keys(allImports || {})) {
950
+ if (!importName.startsWith(NPM_BIN_IMPORT_PREFIX)) {
951
+ continue;
952
+ }
953
+ const commandName = importName.slice(NPM_BIN_IMPORT_PREFIX.length);
954
+ if (binCommandNames.has(commandName)) {
955
+ return true;
956
+ }
957
+ }
958
+ return false;
959
+ }
960
+
961
+ /**
962
+ * Given the specified package, create a CycloneDX component and add it to the list.
963
+ */
964
+ export function addComponent(
965
+ options,
966
+ allImports,
967
+ pkg,
968
+ ptype,
969
+ compMap,
970
+ isRootPkg = false,
971
+ ) {
972
+ if (!pkg || pkg.extraneous) {
973
+ return;
974
+ }
975
+ if (!isRootPkg) {
976
+ const pkgIdentifier = parsePackageJsonName(pkg.name);
977
+ const author = pkg.author || undefined;
978
+ const authors = pkg.authors || undefined;
979
+ const publisher = pkg.publisher || undefined;
980
+ let group = pkg.group || pkgIdentifier.scope;
981
+ // Create empty group
982
+ group = group || "";
983
+ const name = pkgIdentifier.fullName || pkg.name || "";
984
+ // name is mandatory
985
+ if (!name) {
986
+ return;
987
+ }
988
+ // Do we need this still?
989
+ if (
990
+ !ptype &&
991
+ ["jar", "war", "ear", "pom"].includes(pkg?.qualifiers?.type)
992
+ ) {
993
+ ptype = "maven";
994
+ }
995
+ const version = pkg.version || "";
996
+ const licenses = pkg.licenses || getLicenses(pkg);
997
+ let purl = pkg.purl;
998
+ if (!purl && ptype) {
999
+ try {
1000
+ purl = new Purl({
1001
+ type: ptype,
1002
+ namespace: encodeForPurl(group) || null,
1003
+ name: encodeForPurl(name),
1004
+ version: version || null,
1005
+ qualifiers: pkg.qualifiers || null,
1006
+ subpath: encodeForPurl(pkg.subpath) || null,
1007
+ });
1008
+ } catch {
1009
+ // purl construction may fail for types requiring a namespace (maven,
1010
+ // swift) when the component has no group; fall through without a purl.
1011
+ }
1012
+ }
1013
+ let purlString = purl?.toString();
1014
+ // These types get no purl derived from the ecosystem being scanned, since a
1015
+ // file or a crypto asset is not a package of that ecosystem. A collector
1016
+ // that set a purl itself — file components carry `pkg:generic/...` — is
1017
+ // taken at its word.
1018
+ if (
1019
+ !pkg.purl &&
1020
+ (NON_PURL_TYPES.includes(ptype) || NON_PURL_TYPES.includes(pkg.type))
1021
+ ) {
1022
+ purl = undefined;
1023
+ purlString = undefined;
1024
+ }
1025
+ // Some applications like github workflow steps and commands do not have purl
1026
+ if (
1027
+ pkg.purl === undefined &&
1028
+ !pkg?.["bom-ref"]?.startsWith("pkg:") &&
1029
+ pkg?.type === "application"
1030
+ ) {
1031
+ purl = undefined;
1032
+ purlString = undefined;
1033
+ }
1034
+ const description = pkg.description || undefined;
1035
+ let compScope = pkg.scope;
1036
+ let isTypeOnlyPkg = false;
1037
+ if (allImports) {
1038
+ const impPkgs = Object.keys(allImports);
1039
+ const hasBinCommandEvidence = hasNpmBinCommandEvidence(allImports, pkg);
1040
+ if (
1041
+ impPkgs.includes(name) ||
1042
+ impPkgs.includes(`${group}/${name}`) ||
1043
+ impPkgs.includes(`@${group}/${name}`) ||
1044
+ (group.length > 0 && impPkgs.includes(group)) ||
1045
+ (group.length > 0 && impPkgs.includes(`@${group}`)) ||
1046
+ hasBinCommandEvidence
1047
+ ) {
1048
+ if (
1049
+ !hasBinCommandEvidence &&
1050
+ isPkgTypeOnlyImport(allImports, group, name)
1051
+ ) {
1052
+ compScope = "excluded";
1053
+ isTypeOnlyPkg = true;
1054
+ } else {
1055
+ compScope = "required";
1056
+ }
1057
+ } else if (impPkgs.length && compScope !== "excluded") {
1058
+ compScope = "optional";
1059
+ }
1060
+ }
1061
+ let component = {
1062
+ author,
1063
+ authors,
1064
+ publisher,
1065
+ group,
1066
+ name,
1067
+ version,
1068
+ description,
1069
+ scope: compScope,
1070
+ hashes: [],
1071
+ licenses,
1072
+ purl: purlString,
1073
+ externalReferences: addExternalReferences(pkg),
1074
+ };
1075
+ if (options.specVersion >= 1.5) {
1076
+ component.pedigree = pkg.pedigree || undefined;
1077
+ }
1078
+ if (options.specVersion >= 1.6) {
1079
+ component.releaseNotes = pkg.releaseNotes || undefined;
1080
+ component.modelCard = pkg.modelCard || undefined;
1081
+ component.data = pkg.data || undefined;
1082
+ }
1083
+ component["type"] = determinePackageType(pkg);
1084
+ if (pkg["bom-ref"]) {
1085
+ component["bom-ref"] = pkg["bom-ref"];
1086
+ } else if (purlString) {
1087
+ component["bom-ref"] = decodeURIComponent(purlString);
1088
+ }
1089
+
1090
+ if (
1091
+ component.externalReferences === undefined ||
1092
+ component.externalReferences.length === 0
1093
+ ) {
1094
+ delete component.externalReferences;
1095
+ }
1096
+ if (options.specVersion < 1.6) {
1097
+ delete component.omniborId;
1098
+ delete component.swhid;
1099
+ }
1100
+ processHashes(pkg, component);
1101
+ // Upgrade authors section
1102
+ if (options.specVersion >= 1.6 && component.author) {
1103
+ const authorsList = [];
1104
+ for (const aauthor of component.author.split(",")) {
1105
+ authorsList.push({ name: aauthor });
1106
+ }
1107
+ component.authors = authorsList;
1108
+ delete component.author;
1109
+ }
1110
+ // Downgrade authors section for < 1.5 :(
1111
+ if (options.specVersion < 1.6) {
1112
+ if (component?.authors?.length) {
1113
+ component.author = component.authors
1114
+ .map((a) => (a.email ? `${a.name} <${a.email}>` : a.name))
1115
+ .join(",");
1116
+ }
1117
+ delete component.authors;
1118
+ }
1119
+ // Downgrade from 1.7
1120
+ if (options.specVersion < 1.7) {
1121
+ if (component.isExternal) {
1122
+ delete component.isExternal;
1123
+ }
1124
+ if (component.versionRange) {
1125
+ console.warn(
1126
+ `Version Range is not supported in ${options.specVersion} specifications. Please run cdxgen with --spec-version 1.7`,
1127
+ );
1128
+ delete component.versionRange;
1129
+ }
1130
+ }
1131
+ // Retain any tags
1132
+ if (
1133
+ options.specVersion >= 1.6 &&
1134
+ pkg.tags &&
1135
+ Object.keys(pkg.tags).length
1136
+ ) {
1137
+ component.tags = pkg.tags;
1138
+ }
1139
+ // Retain any component properties and crypto properties
1140
+ if (pkg.properties?.length) {
1141
+ component.properties = pkg.properties;
1142
+ }
1143
+ if (isTypeOnlyPkg) {
1144
+ component.properties = component.properties || [];
1145
+ if (
1146
+ !component.properties.some(
1147
+ (p) => p.name === "cdx:npm:package:type-only",
1148
+ )
1149
+ ) {
1150
+ component.properties.push({
1151
+ name: "cdx:npm:package:type-only",
1152
+ value: "true",
1153
+ });
1154
+ }
1155
+ }
1156
+ if (pkg.cryptoProperties && typeof pkg.cryptoProperties === "object") {
1157
+ component.cryptoProperties = pkg.cryptoProperties;
1158
+ }
1159
+ // Retain nested components
1160
+ if (pkg.components) {
1161
+ component.components = pkg.components;
1162
+ }
1163
+ component = enrichComponentWithMcpMetadata(component);
1164
+ const compMapKey = component.purl || component["bom-ref"];
1165
+ // Issue: 1353. We need to keep merging the properties
1166
+ if (compMap[compMapKey]) {
1167
+ const mergedComponents = trimComponents([compMap[compMapKey], component]);
1168
+ if (mergedComponents?.length === 1) {
1169
+ component = mergedComponents[0];
1170
+ }
1171
+ }
1172
+ // Retain evidence
1173
+ if (
1174
+ options.specVersion >= 1.5 &&
1175
+ pkg.evidence &&
1176
+ Object.keys(pkg.evidence).length
1177
+ ) {
1178
+ component.evidence = pkg.evidence;
1179
+ // Convert evidence.identity section to an array for 1.6 and above
1180
+ if (
1181
+ options.specVersion >= 1.6 &&
1182
+ pkg.evidence &&
1183
+ pkg.evidence.identity &&
1184
+ !Array.isArray(pkg.evidence.identity)
1185
+ ) {
1186
+ // Automatically add concludedValue
1187
+ if (pkg.evidence.identity?.methods?.length === 1) {
1188
+ pkg.evidence.identity.concludedValue =
1189
+ pkg.evidence.identity.methods[0].value;
1190
+ }
1191
+ component.evidence.identity = [pkg.evidence.identity];
1192
+ }
1193
+ // Convert evidence.identity section to an object for 1.5
1194
+ if (
1195
+ options.specVersion === 1.5 &&
1196
+ pkg.evidence &&
1197
+ pkg.evidence.identity &&
1198
+ Array.isArray(pkg.evidence.identity)
1199
+ ) {
1200
+ component.evidence.identity = pkg.evidence.identity[0];
1201
+ }
1202
+ }
1203
+ compMap[compMapKey] = component;
1204
+ }
1205
+ if (pkg.dependencies) {
1206
+ Object.keys(pkg.dependencies)
1207
+ .map((x) => pkg.dependencies[x])
1208
+ .filter((x) => typeof x !== "string") //remove cycles
1209
+ .map((x) => addComponent(options, allImports, x, ptype, compMap, false));
1210
+ }
1211
+ }
1212
+
1213
+ /**
1214
+ * If the author has described the module as a 'framework', the take their
1215
+ * word for it, otherwise, identify the module as a 'library'.
1216
+ */
1217
+ export function determinePackageType(pkg) {
1218
+ // Retain the exact component type in certain cases.
1219
+ if (
1220
+ [
1221
+ "container",
1222
+ "platform",
1223
+ "operating-system",
1224
+ "device",
1225
+ "device-driver",
1226
+ "firmware",
1227
+ "file",
1228
+ "machine-learning-model",
1229
+ "data",
1230
+ "cryptographic-asset",
1231
+ ].includes(pkg.type)
1232
+ ) {
1233
+ return pkg.type;
1234
+ }
1235
+ if (pkg.type === "application") {
1236
+ if (pkg?.name?.endsWith(".tar")) {
1237
+ return "container";
1238
+ }
1239
+ return pkg.type;
1240
+ }
1241
+ if (pkg.purl) {
1242
+ try {
1243
+ const purl = Purl.parse(pkg.purl);
1244
+ if (purl.type) {
1245
+ if (["docker", "oci", "container"].includes(purl.type)) {
1246
+ return "container";
1247
+ }
1248
+ if (["github"].includes(purl.type)) {
1249
+ return "application";
1250
+ }
1251
+ }
1252
+ // See #1760
1253
+ if (
1254
+ purl.namespace?.startsWith("@types") ||
1255
+ (purl.namespace?.includes("-types") && pkg?.type === "npm")
1256
+ ) {
1257
+ return "library";
1258
+ }
1259
+ for (const cf of frameworksList.all) {
1260
+ if (
1261
+ pkg.purl.startsWith(cf) ||
1262
+ purl.namespace?.includes(cf) ||
1263
+ purl.name.toLowerCase().startsWith(cf)
1264
+ ) {
1265
+ return "framework";
1266
+ }
1267
+ }
1268
+ } catch (_e) {
1269
+ // continue regardless of error
1270
+ }
1271
+ } else if (pkg.group) {
1272
+ if (["actions"].includes(pkg.group)) {
1273
+ return "application";
1274
+ }
1275
+ }
1276
+ if (Object.hasOwn(pkg, "description")) {
1277
+ if (pkg.description?.toLowerCase().includes("framework")) {
1278
+ return "framework";
1279
+ }
1280
+ }
1281
+ if (Object.hasOwn(pkg, "keywords")) {
1282
+ for (const keyword of pkg.keywords) {
1283
+ if (keyword && keyword.toLowerCase() === "framework") {
1284
+ return "framework";
1285
+ }
1286
+ }
1287
+ }
1288
+ if (Object.hasOwn(pkg, "tags")) {
1289
+ for (const tag of pkg.tags) {
1290
+ if (tag && tag.toLowerCase() === "framework") {
1291
+ return "framework";
1292
+ }
1293
+ }
1294
+ }
1295
+ return "library";
1296
+ }
1297
+
1298
+ /**
1299
+ * Uses the SHA1 shasum (if present) otherwise utilizes Subresource Integrity
1300
+ * of the package with support for multiple hashing algorithms.
1301
+ */
1302
+ export function processHashes(pkg, component) {
1303
+ if (pkg.hashes) {
1304
+ // This attribute would be available when we read a bom json directly
1305
+ // Eg: cyclonedx-maven-plugin. See: Bugs: #172, #175
1306
+ for (const ahash of pkg.hashes) {
1307
+ addComponentHash(ahash.alg, ahash.content, component);
1308
+ }
1309
+ } else if (pkg._shasum) {
1310
+ addComponentHash("SHA-1", pkg._shasum, component);
1311
+ } else if (pkg._integrity) {
1312
+ const integrity = parse(pkg._integrity) || {};
1313
+ // Components may have multiple hashes with various lengths. Check each one
1314
+ // that is supported by the CycloneDX specification.
1315
+ if (Object.hasOwn(integrity, "sha512")) {
1316
+ addComponentHash("SHA-512", integrity.sha512[0].digest, component);
1317
+ }
1318
+ if (Object.hasOwn(integrity, "sha384")) {
1319
+ addComponentHash("SHA-384", integrity.sha384[0].digest, component);
1320
+ }
1321
+ if (Object.hasOwn(integrity, "sha256")) {
1322
+ addComponentHash("SHA-256", integrity.sha256[0].digest, component);
1323
+ }
1324
+ if (Object.hasOwn(integrity, "sha1")) {
1325
+ addComponentHash("SHA-1", integrity.sha1[0].digest, component);
1326
+ }
1327
+ }
1328
+ if (component.hashes.length === 0) {
1329
+ delete component.hashes; // If no hashes exist, delete the hashes node (it's optional)
1330
+ }
1331
+ }
1332
+
1333
+ // Digest length in hex characters for each algorithm CycloneDX names. A digest
1334
+ // that decodes to the wrong length for its algorithm is corrupt, whatever
1335
+ // encoding it arrived in.
1336
+ const HASH_HEX_LENGTHS = {
1337
+ MD5: 32,
1338
+ "SHA-1": 40,
1339
+ "SHA-256": 64,
1340
+ "SHA-384": 96,
1341
+ "SHA-512": 128,
1342
+ "SHA3-256": 64,
1343
+ "SHA3-384": 96,
1344
+ "SHA3-512": 128,
1345
+ "BLAKE2b-256": 64,
1346
+ "BLAKE2b-384": 96,
1347
+ "BLAKE2b-512": 128,
1348
+ };
1349
+
1350
+ // Lengths the CycloneDX hash-content pattern accepts, for algorithms not in the
1351
+ // table above.
1352
+ const HASH_HEX_LENGTHS_ANY = new Set([32, 40, 64, 96, 128]);
1353
+
1354
+ /**
1355
+ * Adds a hash to component.
1356
+ *
1357
+ * Registries hand out digests in hex or in the base64 form npm uses for
1358
+ * `integrity`, and both are accepted. A digest that is neither, or that decodes
1359
+ * to the wrong length for its algorithm, is dropped rather than copied through:
1360
+ * CycloneDX constrains `hash.content` to a hex digest, so emitting it anyway
1361
+ * fails schema validation for the whole document over one bad package.
1362
+ */
1363
+ export function addComponentHash(alg, digest, component) {
1364
+ const hash = normalizeHashContent(alg, digest);
1365
+ if (!hash) {
1366
+ return;
1367
+ }
1368
+ component.hashes.push({ alg: alg, content: hash });
1369
+ }
1370
+
1371
+ /**
1372
+ * Normalize a digest to the lower-case hex form CycloneDX requires.
1373
+ *
1374
+ * @param {string} alg Hash algorithm name
1375
+ * @param {string} digest Digest in hex or base64
1376
+ * @returns {string|undefined} Hex digest, or undefined when it cannot be trusted
1377
+ */
1378
+ export function normalizeHashContent(alg, digest) {
1379
+ if (!digest || typeof digest !== "string") {
1380
+ return undefined;
1381
+ }
1382
+ const expectedLength = HASH_HEX_LENGTHS[alg];
1383
+ const isExpectedLength = (value) =>
1384
+ expectedLength
1385
+ ? value.length === expectedLength
1386
+ : HASH_HEX_LENGTHS_ANY.has(value.length);
1387
+
1388
+ if (new RegExp(HASH_PATTERN).test(digest)) {
1389
+ return isExpectedLength(digest) ? digest : undefined;
1390
+ }
1391
+ // npm and friends carry the digest base64-encoded. Node decodes leniently, so
1392
+ // the decoded length is the check that matters: a truncated or invented value
1393
+ // decodes to something, just not to a digest of the right size.
1394
+ const decoded = Buffer.from(digest, "base64").toString("hex");
1395
+ return isExpectedLength(decoded) ? decoded : undefined;
1396
+ }
1397
+
1398
+ /**
1399
+ * Return the BOM in json format including any namespace mapping
1400
+ *
1401
+ * @param {Object} options Options
1402
+ * @param {Object} pkgInfo Package information
1403
+ * @param {string} ptype Package type
1404
+ * @param {Object} context Context
1405
+ *
1406
+ * @returns {Object} BOM with namespace mapping
1407
+ */
1408
+ export const buildBomNSData = (options, pkgInfo, ptype, context) => {
1409
+ // Many create*Bom call sites provide only a source directory (`src`) when
1410
+ // there is no single manifest/lock file to report, so activity records must
1411
+ // fall back to that directory to keep the target populated.
1412
+ const sourcePath =
1413
+ context?.srcDir || context?.src || options.path || options.filePath;
1414
+ const activityProjectType =
1415
+ context?.projectType ||
1416
+ (Array.isArray(options.projectType)
1417
+ ? options.projectType.length === 1
1418
+ ? options.projectType[0]
1419
+ : undefined
1420
+ : options.projectType);
1421
+ setActivityContext({
1422
+ packageType: ptype,
1423
+ sourcePath,
1424
+ ...(activityProjectType ? { projectType: activityProjectType } : {}),
1425
+ });
1426
+ const bomNSData = {
1427
+ bomJson: undefined,
1428
+ bomJsonFiles: undefined,
1429
+ nsMapping: undefined,
1430
+ dependencies: undefined,
1431
+ parentComponent: undefined,
1432
+ };
1433
+ const serialNum = `urn:uuid:${uuidv4()}`;
1434
+ let allImports = {};
1435
+ if (context?.allImports) {
1436
+ allImports = context.allImports;
1437
+ }
1438
+ const nsMapping = context.nsMapping || {};
1439
+ const services = context.services || [];
1440
+ const overrideParent = determineParentComponent(options);
1441
+ const parentComponent = overrideParent || context.parentComponent;
1442
+ const metadata = addMetadata(parentComponent, options, context);
1443
+ const components = listComponents(options, allImports, pkgInfo, ptype);
1444
+ const dependencies = anchorDetectedParent(
1445
+ overrideParent,
1446
+ context.parentComponent,
1447
+ components,
1448
+ context.dependencies || [],
1449
+ );
1450
+ if (
1451
+ components &&
1452
+ (components.length ||
1453
+ parentComponent ||
1454
+ options.projectType?.includes("dynamic") ||
1455
+ options.projectType?.includes("ai-provenance"))
1456
+ ) {
1457
+ // CycloneDX Json Template
1458
+ const jsonTpl = {
1459
+ bomFormat: "CycloneDX",
1460
+ specVersion: toCycloneDxSpecVersionString(
1461
+ options.specVersion || DEFAULT_CDX_SPEC_VERSION,
1462
+ ),
1463
+ serialNumber: serialNum,
1464
+ version: 1,
1465
+ metadata: metadata,
1466
+ components,
1467
+ dependencies,
1468
+ };
1469
+ setCycloneDxFormat(jsonTpl, jsonTpl.specVersion, {
1470
+ preserveLegacyBomFormat: true,
1471
+ });
1472
+ if (services.length) {
1473
+ jsonTpl.services = mergeServices([], services);
1474
+ }
1475
+ bomNSData.bomJson = jsonTpl;
1476
+ bomNSData.nsMapping = nsMapping;
1477
+ bomNSData.dependencies = dependencies;
1478
+ bomNSData.parentComponent = parentComponent;
1479
+ // Carry language-specific formulation data (e.g. Pixi) so that
1480
+ // postProcess can merge it when building the final formulation section.
1481
+ if (context?.formulationList?.length) {
1482
+ bomNSData.formulationList = context.formulationList;
1483
+ }
1484
+ // Carry language-specific provenance citations (e.g. PEP 770 embedded
1485
+ // SBOMs) so postProcess can attach them in the single root-level citations
1486
+ // section it builds.
1487
+ if (Array.isArray(context?.citations) && context.citations.length) {
1488
+ bomNSData.citations = context.citations;
1489
+ }
1490
+ }
1491
+ recordActivity({
1492
+ kind: "read",
1493
+ reason: `Collected ${ptype || "generic"} component metadata.`,
1494
+ status: components?.length || parentComponent ? "completed" : "failed",
1495
+ target: context?.filename || sourcePath,
1496
+ });
1497
+ resetActivityContext();
1498
+ return bomNSData;
1499
+ };
1500
+
1501
+ /**
1502
+ * Function to create bom string for Android apps using blint
1503
+ *
1504
+ * @param {string} path to the project
1505
+ * @param {Object} options Parse options from the cli
1506
+ * @returns {Object|undefined} BOM object
1507
+ */
1508
+ export function createAndroidBom(path, options) {
1509
+ return createBinaryBom(path, options);
1510
+ }
1511
+
1512
+ /**
1513
+ * Escape the purls of a blint BOM and carry the change through its graph.
1514
+ *
1515
+ * blint composes purls by string interpolation, so a name holding a character
1516
+ * a purl reserves — `libstdc++.so.6` and its kin — arrives unescaped. blint
1517
+ * also uses the purl as the bom-ref, so every ref that quoted the old string,
1518
+ * in `dependencies` and in the parent component alike, moves with it.
1519
+ *
1520
+ * @param {Object} binaryBom BOM read from blint, rewritten in place
1521
+ */
1522
+ function repairBinaryBomPurls(binaryBom) {
1523
+ const renamed = new Map();
1524
+ const repair = (component) => {
1525
+ const before = component?.purl;
1526
+ if (!before) {
1527
+ return;
1528
+ }
1529
+ repairPurl(component);
1530
+ if (component.purl === before) {
1531
+ return;
1532
+ }
1533
+ renamed.set(before, component.purl);
1534
+ if (component["bom-ref"] === before) {
1535
+ component["bom-ref"] = component.purl;
1536
+ }
1537
+ };
1538
+ for (const component of binaryBom?.components || []) {
1539
+ repair(component);
1540
+ }
1541
+ repair(binaryBom?.parentComponent);
1542
+ repair(binaryBom?.metadata?.component);
1543
+ if (!renamed.size) {
1544
+ return;
1545
+ }
1546
+ const rename = (ref) => renamed.get(ref) || ref;
1547
+ for (const dependency of binaryBom?.dependencies || []) {
1548
+ if (dependency?.ref) {
1549
+ dependency.ref = rename(dependency.ref);
1550
+ }
1551
+ for (const key of ["dependsOn", "provides"]) {
1552
+ if (Array.isArray(dependency?.[key])) {
1553
+ dependency[key] = dependency[key].map(rename);
1554
+ }
1555
+ }
1556
+ }
1557
+ }
1558
+
1559
+ /**
1560
+ * Function to create bom string for binaries using blint
1561
+ *
1562
+ * @param {string} path to the project
1563
+ * @param {Object} options Parse options from the cli
1564
+ * @returns {Object|undefined} BOM object
1565
+ */
1566
+ export function createBinaryBom(path, options) {
1567
+ const tempDir = safeMkdtempSync(join(getTmpDir(), "blint-tmp-"));
1568
+ const binaryBomFile = join(tempDir, "bom.json");
1569
+ getBinaryBom(path, binaryBomFile, options.deep);
1570
+ if (safeExistsSync(binaryBomFile)) {
1571
+ const binaryBom = JSON.parse(
1572
+ readFileSync(binaryBomFile, { encoding: "utf-8" }),
1573
+ );
1574
+ repairBinaryBomPurls(binaryBom);
1575
+ attachIdentityTools(
1576
+ binaryBom?.components,
1577
+ extractToolRefs(
1578
+ binaryBom?.metadata?.tools,
1579
+ (tool) => tool?.name !== "cdxgen",
1580
+ ),
1581
+ );
1582
+ return {
1583
+ bomJson: binaryBom,
1584
+ dependencies: binaryBom.dependencies,
1585
+ parentComponent: binaryBom.parentComponent,
1586
+ };
1587
+ }
1588
+ return undefined;
1589
+ }
1590
+
1591
+ /**
1592
+ * Identify the requested AI inventory project types.
1593
+ *
1594
+ * @param {Object} options Parse options from the cli
1595
+ * @returns {string[]} Requested AI inventory types
1596
+ */
1597
+ export function getRequestedAiInventoryTypes(options) {
1598
+ return AI_INVENTORY_PROJECT_TYPES.filter((type) =>
1599
+ optionIncludesAiInventoryProjectType(options?.projectType, type),
1600
+ );
1601
+ }
1602
+
1603
+ /**
1604
+ * Returns the AI inventory types excluded via `--exclude-type`.
1605
+ *
1606
+ * @param {object} options CLI options
1607
+ * @returns {string[]} Excluded AI inventory types
1608
+ */
1609
+ export function getExcludedAiInventoryTypes(options) {
1610
+ return AI_INVENTORY_PROJECT_TYPES.filter((type) =>
1611
+ optionIncludesAiInventoryProjectType(options?.excludeType, type),
1612
+ );
1613
+ }
1614
+
1615
+ /**
1616
+ * Removes the excluded AI inventory types from the included list.
1617
+ *
1618
+ * @param {string[]} includedAiInventoryTypes Types selected for collection
1619
+ * @param {string[]} excludedAiInventoryTypes Types excluded by the user
1620
+ * @returns {string[]} Filtered list of AI inventory types
1621
+ */
1622
+ export function filterIncludedAiInventoryTypes(
1623
+ includedAiInventoryTypes,
1624
+ excludedAiInventoryTypes,
1625
+ ) {
1626
+ return [...new Set(includedAiInventoryTypes)].filter(
1627
+ (type) => !excludedAiInventoryTypes.includes(type),
1628
+ );
1629
+ }
1630
+
1631
+ /**
1632
+ * Determine which AI inventory types should be collected for a scan.
1633
+ *
1634
+ * This combines explicit project-type opt-ins with BOM audit category-driven
1635
+ * opt-ins, then removes any explicitly excluded inventory types.
1636
+ *
1637
+ * @param {Object} options Parse options from the CLI
1638
+ * @returns {string[]} AI inventory types to collect
1639
+ */
1640
+ export function getIncludedAiInventoryTypes(options) {
1641
+ const requestedAiInventoryTypes = getRequestedAiInventoryTypes(options);
1642
+ const excludedAiInventoryTypes = getExcludedAiInventoryTypes(options);
1643
+ const exactAiInventoryType = getExactAiInventoryType(options);
1644
+ if (exactAiInventoryType) {
1645
+ return filterIncludedAiInventoryTypes(
1646
+ requestedAiInventoryTypes,
1647
+ excludedAiInventoryTypes,
1648
+ );
1649
+ }
1650
+ const auditCategories = expandBomAuditCategories(options?.bomAuditCategories);
1651
+ const includedAiInventoryTypes = [...requestedAiInventoryTypes];
1652
+ if (auditCategories.includes("ai-agent")) {
1653
+ includedAiInventoryTypes.push("ai-skill");
1654
+ includedAiInventoryTypes.push("ai");
1655
+ }
1656
+ if (auditCategories.includes("mcp-server")) {
1657
+ includedAiInventoryTypes.push("mcp");
1658
+ }
1659
+ return filterIncludedAiInventoryTypes(
1660
+ includedAiInventoryTypes,
1661
+ excludedAiInventoryTypes,
1662
+ );
1663
+ }
1664
+
1665
+ /**
1666
+ * Returns the single AI inventory type when exactly one project type alias is
1667
+ * selected, otherwise undefined.
1668
+ *
1669
+ * @param {object} options CLI options
1670
+ * @returns {string|undefined} The exact AI inventory type or undefined
1671
+ */
1672
+ export function getExactAiInventoryType(options) {
1673
+ const requestedAiInventoryTypes = getRequestedAiInventoryTypes(options);
1674
+ return requestedAiInventoryTypes.length === 1 &&
1675
+ Array.isArray(options?.projectType) &&
1676
+ options.projectType.length === 1
1677
+ ? requestedAiInventoryTypes[0]
1678
+ : undefined;
1679
+ }
1680
+
1681
+ /**
1682
+ * Determine whether MCP source-code analysis should run for the current scan.
1683
+ *
1684
+ * @param {string[]} includedAiInventoryTypes AI inventory types selected for collection
1685
+ * @returns {boolean} True when MCP inventory collection is enabled
1686
+ */
1687
+ export function shouldDetectMcpInventory(includedAiInventoryTypes) {
1688
+ return includedAiInventoryTypes.includes("mcp");
1689
+ }
1690
+
1691
+ /**
1692
+ * Collects sorted, unique relative file names for AI inventory subjects whose
1693
+ * `cdx:file:kind` property matches one of the given kinds.
1694
+ *
1695
+ * @param {object[]} subjects Component or service subjects to inspect
1696
+ * @param {string} discoveryPath Base path used to compute relative file names
1697
+ * @param {Set<string>} kindSet Accepted kind values
1698
+ * @returns {string[]} Sorted unique relative file names
1699
+ */
1700
+ export function summarizeAiInventoryNames(subjects, discoveryPath, kindSet) {
1701
+ return [
1702
+ ...new Set(
1703
+ (subjects || [])
1704
+ .filter((subject) =>
1705
+ kindSet.has(inventoryPropertyValue(subject, "cdx:file:kind")),
1706
+ )
1707
+ .map((subject) => inventoryPropertyValue(subject, "internal:SrcFile"))
1708
+ .filter(Boolean)
1709
+ .map(
1710
+ (filePath) => relative(discoveryPath, filePath) || basename(filePath),
1711
+ ),
1712
+ ),
1713
+ ].sort();
1714
+ }
1715
+
1716
+ /**
1717
+ * Collects sorted unique service names from an AI inventory services list.
1718
+ *
1719
+ * @param {object[]} services Services with a `name` property
1720
+ * @returns {string[]} Sorted unique service names
1721
+ */
1722
+ export function summarizeAiInventoryServiceNames(services) {
1723
+ return [
1724
+ ...new Set(
1725
+ (services || []).map((service) => service?.name).filter(Boolean),
1726
+ ),
1727
+ ].sort();
1728
+ }
1729
+
1730
+ /**
1731
+ * Formats one padded summary line for the AI inventory console output.
1732
+ *
1733
+ * @param {string} label Left-aligned label (padded to 20 chars)
1734
+ * @param {number} count Item count
1735
+ * @param {string[]} nameList Optional list of names to append in parentheses
1736
+ * @returns {string} The formatted summary line
1737
+ */
1738
+ export function formatAiInventorySummaryLine(label, count, nameList) {
1739
+ return ` ${label.padEnd(20)} ${count}${nameList.length ? ` (${nameList.join(", ")})` : ""}`;
1740
+ }
1741
+
1742
+ /**
1743
+ * Prints a human-readable AI inventory summary to stderr, including counts and
1744
+ * names for instruction files, skill files, MCP configs, and MCP services.
1745
+ * Returns without printing when the inventory is empty.
1746
+ *
1747
+ * @param {object} aiInventory AI inventory object with components and services
1748
+ * @param {string} discoveryPath Base path used to compute relative file names
1749
+ * @returns {void}
1750
+ */
1751
+ export function emitAiInventorySummary(aiInventory, discoveryPath) {
1752
+ const summary = summarizeAiInventory(aiInventory);
1753
+ const totalInventory =
1754
+ summary.instructionCount +
1755
+ summary.skillCount +
1756
+ summary.mcpConfigCount +
1757
+ summary.mcpServiceCount;
1758
+ if (!totalInventory) {
1759
+ return;
1760
+ }
1761
+ const instructionNames = summarizeAiInventoryNames(
1762
+ aiInventory.components,
1763
+ discoveryPath,
1764
+ AI_INSTRUCTION_FILE_KINDS,
1765
+ );
1766
+ const skillNames = summarizeAiInventoryNames(
1767
+ aiInventory.components,
1768
+ discoveryPath,
1769
+ new Set([AI_SKILL_FILE_KIND]),
1770
+ );
1771
+ const mcpConfigNames = summarizeAiInventoryNames(
1772
+ aiInventory.components,
1773
+ discoveryPath,
1774
+ new Set([MCP_CONFIG_FILE_KIND]),
1775
+ );
1776
+ const mcpServiceNames = summarizeAiInventoryServiceNames(
1777
+ aiInventory.services,
1778
+ );
1779
+ console.warn(
1780
+ [
1781
+ "AI Inventory Summary:",
1782
+ formatAiInventorySummaryLine(
1783
+ "AI instruction files:",
1784
+ summary.instructionCount,
1785
+ instructionNames,
1786
+ ),
1787
+ formatAiInventorySummaryLine(
1788
+ "Skill files:",
1789
+ summary.skillCount,
1790
+ skillNames,
1791
+ ),
1792
+ formatAiInventorySummaryLine(
1793
+ "MCP configs:",
1794
+ summary.mcpConfigCount,
1795
+ mcpConfigNames,
1796
+ ),
1797
+ formatAiInventorySummaryLine(
1798
+ "MCP services:",
1799
+ summary.mcpServiceCount,
1800
+ mcpServiceNames,
1801
+ ),
1802
+ "",
1803
+ "Run --bom-audit --bom-audit-categories ai-inventory to audit these surfaces.",
1804
+ ].join("\n"),
1805
+ );
1806
+ }
1807
+
1808
+ /**
1809
+ * Dedupe components
1810
+ *
1811
+ * @param {Object} options Options
1812
+ * @param {Array} components Components
1813
+ * @param {Object} parentComponent Parent component
1814
+ * @param {Array} dependencies Dependencies
1815
+ *
1816
+ * @returns {Object} Object including BOM Json
1817
+ */
1818
+ export function dedupeBom(options, components, parentComponent, dependencies) {
1819
+ if (!components) {
1820
+ return {};
1821
+ }
1822
+ if (!dependencies) {
1823
+ dependencies = [];
1824
+ }
1825
+ components = trimComponents(components);
1826
+ // Let's apply some common tweaks
1827
+ // Convert evidence.identity section to an object for 1.5
1828
+ if (options.specVersion === 1.5) {
1829
+ for (const comp of components) {
1830
+ if (comp?.evidence?.identity && Array.isArray(comp.evidence.identity)) {
1831
+ comp.evidence.identity = comp.evidence.identity[0];
1832
+ delete comp.evidence.identity.concludedValue;
1833
+ }
1834
+ }
1835
+ }
1836
+ if (DEBUG_MODE) {
1837
+ console.log(
1838
+ `Obtained ${components.length} components and ${dependencies.length} dependencies after dedupe.`,
1839
+ );
1840
+ }
1841
+ const serialNum = `urn:uuid:${uuidv4()}`;
1842
+ return {
1843
+ options,
1844
+ parentComponent,
1845
+ components,
1846
+ bomJson: setCycloneDxFormat(
1847
+ {
1848
+ specVersion: toCycloneDxSpecVersionString(
1849
+ options.specVersion || DEFAULT_CDX_SPEC_VERSION,
1850
+ ),
1851
+ serialNumber: serialNum,
1852
+ version: 1,
1853
+ metadata: addMetadata(parentComponent, options, {}),
1854
+ components,
1855
+ services: options.services || [],
1856
+ dependencies,
1857
+ },
1858
+ options.specVersion || DEFAULT_CDX_SPEC_VERSION,
1859
+ { preserveLegacyBomFormat: true },
1860
+ ),
1861
+ };
1862
+ }
1863
+
1864
+ /**
1865
+ * Checks whether the user explicitly selected a project type alias that
1866
+ * belongs to the given base project type.
1867
+ *
1868
+ * @param {object} options CLI options
1869
+ * @param {string} baseProjectType Base project type to check against
1870
+ * @returns {boolean} True when an explicit alias selection matches
1871
+ */
1872
+ export const hasExplicitProjectTypeSelection = (options, baseProjectType) => {
1873
+ options = options || {};
1874
+ const projectTypes = Array.isArray(options.projectType)
1875
+ ? options.projectType
1876
+ : options.projectType
1877
+ ? [options.projectType]
1878
+ : [];
1879
+ return projectTypes.some((selectedProjectType) =>
1880
+ PROJECT_TYPE_ALIASES[baseProjectType]?.includes(selectedProjectType),
1881
+ );
1882
+ };