@cdxgen/cdxgen 13.5.0 → 13.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. package/README.md +17 -10
  2. package/bin/audit.js +7 -4
  3. package/bin/cdxgen.js +260 -37
  4. package/bin/convert.js +146 -22
  5. package/bin/evinse.js +28 -3
  6. package/bin/repl.js +47 -3
  7. package/bin/sign.js +211 -34
  8. package/bin/tracebom.js +18 -6
  9. package/bin/validate.js +24 -3
  10. package/bin/verify.js +113 -5
  11. package/data/behavior-taxonomy.schema.json +1491 -0
  12. package/data/cyclonedx-2.0-bundled.schema.json +18606 -5528
  13. package/data/cyclonedx-2.0-cryptography-defs.schema.json +857 -0
  14. package/data/license-aliases.json +24 -2
  15. package/data/pqc-migration.json +239 -0
  16. package/data/remediations.json +176 -0
  17. package/data/rules/ai-bom.yaml +1 -1
  18. package/data/rules/brotli-decoder.yaml +107 -0
  19. package/data/rules/cbom-security.yaml +4 -3
  20. package/data/rules/package-integrity.yaml +28 -0
  21. package/data/rules/vscode-extensions.yaml +75 -0
  22. package/data/spdx-license-list.json +121 -7
  23. package/data/spdx-licenses.json +69 -0
  24. package/data/spdx.schema.json +845 -2
  25. package/lib/audit/index.js +25 -3
  26. package/lib/cli/bomAssembly.js +172 -4
  27. package/lib/cli/cliOptions.js +121 -17
  28. package/lib/cli/index.js +720 -902
  29. package/lib/cli/jsBom.js +156 -64
  30. package/lib/cli/jvmBom.js +602 -86
  31. package/lib/cli/managedBom.js +161 -19
  32. package/lib/cli/nativeBom.js +52 -5
  33. package/lib/core/boundedFile.js +344 -0
  34. package/lib/core/brotliProbe.js +182 -0
  35. package/lib/core/env.js +34 -0
  36. package/lib/core/fs.js +138 -3
  37. package/lib/core/globPatterns.js +218 -0
  38. package/lib/core/httpClient.js +98 -1
  39. package/lib/core/lockPaths.js +38 -0
  40. package/lib/core/paths.js +24 -1
  41. package/lib/core/processTree.js +100 -8
  42. package/lib/core/projectConfig.js +332 -25
  43. package/lib/core/toolRegistry.js +184 -0
  44. package/lib/ecosystems/cppEvidence.js +263 -106
  45. package/lib/ecosystems/cppIncludeResolver.js +16 -5
  46. package/lib/ecosystems/denoutils.js +2 -2
  47. package/lib/ecosystems/ecosystems.js +25 -10
  48. package/lib/ecosystems/gemHostProbe.js +301 -0
  49. package/lib/ecosystems/golem.js +3 -8
  50. package/lib/ecosystems/gradleutils.js +1909 -229
  51. package/lib/ecosystems/jsEvidence.js +90 -38
  52. package/lib/ecosystems/kosi.js +3 -5
  53. package/lib/ecosystems/npmVersionResolution.js +376 -0
  54. package/lib/ecosystems/parsers-bazel.js +107 -6
  55. package/lib/ecosystems/parsers-js.js +505 -22
  56. package/lib/ecosystems/parsers-misc.js +209 -20
  57. package/lib/ecosystems/parsers-python.js +178 -30
  58. package/lib/ecosystems/parsers-rust.js +117 -15
  59. package/lib/ecosystems/pythonutils.js +128 -2
  60. package/lib/ecosystems/remote/huggingface.js +22 -0
  61. package/lib/ecosystems/rubyutils.js +538 -31
  62. package/lib/ecosystems/rusi.js +2 -4
  63. package/lib/ecosystems/scalacliutils.js +2 -0
  64. package/lib/ecosystems/scalasem.js +798 -152
  65. package/lib/ecosystems/vendoredCode.js +237 -3
  66. package/lib/ecosystems/venvProbe.js +360 -0
  67. package/lib/evinser/evinser.js +536 -71
  68. package/lib/evinser/scalasem.js +5 -1
  69. package/lib/helpers/agenticToolutils.js +525 -94
  70. package/lib/helpers/bomSigner.js +43 -9
  71. package/lib/helpers/jssSigner.js +1276 -0
  72. package/lib/helpers/vsixutils.js +1574 -315
  73. package/lib/inventory/agentBlueprint.js +193 -0
  74. package/lib/inventory/agentToolNames.js +145 -0
  75. package/lib/inventory/aiCollector.js +153 -7
  76. package/lib/inventory/aiInventory.js +44 -8
  77. package/lib/inventory/aiProviders.js +324 -0
  78. package/lib/inventory/atomUtils.js +77 -0
  79. package/lib/inventory/bomUtils.js +8 -1
  80. package/lib/inventory/brotliDecoder.js +142 -0
  81. package/lib/inventory/buildToolRateLimit.js +1 -1
  82. package/lib/inventory/cbomutils.js +56 -7
  83. package/lib/inventory/ciParsers/githubActionsLock.js +821 -0
  84. package/lib/inventory/citations.js +31 -2
  85. package/lib/inventory/communityAiConfigParser.js +978 -80
  86. package/lib/inventory/cyclonedx20.js +152 -0
  87. package/lib/inventory/cyclonedx20Common.js +286 -0
  88. package/lib/inventory/cyclonedx20Derived.js +159 -0
  89. package/lib/inventory/cyclonedx20Parties.js +552 -0
  90. package/lib/inventory/cyclonedx20Read.js +768 -0
  91. package/lib/inventory/cyclonedx20ReadCommon.js +374 -0
  92. package/lib/inventory/cyclonedx20ReadComponents.js +692 -0
  93. package/lib/inventory/cyclonedx20ReadContext.js +380 -0
  94. package/lib/inventory/cyclonedx20ReadEvidence.js +466 -0
  95. package/lib/inventory/cyclonedx20ReadSections.js +599 -0
  96. package/lib/inventory/cyclonedx20Render.js +766 -0
  97. package/lib/inventory/cyclonedx20RenderComponents.js +716 -0
  98. package/lib/inventory/cyclonedx20RenderDefinitions.js +405 -0
  99. package/lib/inventory/cyclonedx20RenderEvidence.js +726 -0
  100. package/lib/inventory/cyclonedx20RenderHardware.js +203 -0
  101. package/lib/inventory/cyclonedx20RenderPatents.js +174 -0
  102. package/lib/inventory/cyclonedx20RenderRefIds.js +314 -0
  103. package/lib/inventory/cyclonedx20RenderSections.js +499 -0
  104. package/lib/inventory/cyclonedx20Tables.js +594 -0
  105. package/lib/inventory/deps.js +141 -13
  106. package/lib/inventory/dosai.js +375 -6
  107. package/lib/inventory/dosaiParsers.js +3 -6
  108. package/lib/inventory/dotnetRuntime.js +367 -0
  109. package/lib/inventory/ecosystemFormulationParsers.js +979 -0
  110. package/lib/inventory/envcontext.js +436 -48
  111. package/lib/inventory/evidenceUtils.js +13 -1
  112. package/lib/inventory/fetchBatch.js +1 -1
  113. package/lib/inventory/formulationParsers.js +124 -14
  114. package/lib/inventory/gtfobins.js +13 -0
  115. package/lib/inventory/hbom.js +45 -6
  116. package/lib/inventory/hbomLoader.js +166 -0
  117. package/lib/inventory/hostRuntimeProbe.js +686 -0
  118. package/lib/inventory/jvmLocalRepos.js +9 -2
  119. package/lib/inventory/jvmToolEnv.js +29 -0
  120. package/lib/inventory/licenseEnhancer.js +12 -0
  121. package/lib/inventory/mavenCentralMirror.js +534 -0
  122. package/lib/inventory/mcpConfigParser.js +5 -0
  123. package/lib/inventory/nodeBuildInfo.js +218 -0
  124. package/lib/inventory/nodeHostProbe.js +202 -0
  125. package/lib/inventory/occurrenceKey.js +90 -0
  126. package/lib/inventory/osPackageResolver.js +182 -0
  127. package/lib/inventory/phpBuildInfo.js +10 -59
  128. package/lib/inventory/phpHostProbe.js +32 -488
  129. package/lib/inventory/pqcMigration.js +426 -0
  130. package/lib/inventory/rubyBuildInfo.js +972 -0
  131. package/lib/inventory/rubyHostProbe.js +218 -0
  132. package/lib/inventory/rustFormulationParser.js +21 -10
  133. package/lib/inventory/scalaCoords.js +4 -3
  134. package/lib/inventory/scalaDedupe.js +440 -0
  135. package/lib/inventory/source.js +114 -8
  136. package/lib/managers/binary.js +337 -3
  137. package/lib/managers/docker.js +79 -0
  138. package/lib/parsers/huggingfaceManifest.js +9 -1
  139. package/lib/parsers/huggingfaceUtils.js +18 -0
  140. package/lib/parsers/kiroPermissions.js +166 -0
  141. package/lib/parsers/largeJson.js +28 -11
  142. package/lib/parsers/vscodeExtensionId.js +183 -0
  143. package/lib/server/server.js +48 -35
  144. package/lib/stages/postgen/postgen.js +41 -1
  145. package/lib/stages/postgen/ruleEngine.js +13 -5
  146. package/lib/stages/postgen/specVersionCompat.js +76 -0
  147. package/lib/stages/pregen/envAudit.js +1 -0
  148. package/lib/stages/pregen/pregen.js +114 -57
  149. package/lib/validator/bomValidator.js +14 -2
  150. package/lib/validator/complianceEngine.js +30 -3
  151. package/lib/validator/complianceRules.js +1416 -4
  152. package/lib/validator/generated/validate-1.6.mjs +1 -1
  153. package/lib/validator/generated/validate-1.7.mjs +1 -1
  154. package/lib/validator/generated/validate-2.0.mjs +57554 -13851
  155. package/lib/validator/index.js +49 -8
  156. package/lib/validator/reporters/json.js +6 -0
  157. package/package.json +11 -10
  158. package/types/bin/repl.d.ts.map +1 -1
  159. package/types/lib/audit/index.d.ts +6 -2
  160. package/types/lib/audit/index.d.ts.map +1 -1
  161. package/types/lib/cli/bomAssembly.d.ts +29 -1
  162. package/types/lib/cli/bomAssembly.d.ts.map +1 -1
  163. package/types/lib/cli/cliOptions.d.ts +6 -0
  164. package/types/lib/cli/cliOptions.d.ts.map +1 -1
  165. package/types/lib/cli/index.d.ts.map +1 -1
  166. package/types/lib/cli/jsBom.d.ts +3 -18
  167. package/types/lib/cli/jsBom.d.ts.map +1 -1
  168. package/types/lib/cli/jvmBom.d.ts +15 -0
  169. package/types/lib/cli/jvmBom.d.ts.map +1 -1
  170. package/types/lib/cli/managedBom.d.ts.map +1 -1
  171. package/types/lib/cli/nativeBom.d.ts.map +1 -1
  172. package/types/lib/core/boundedFile.d.ts +100 -0
  173. package/types/lib/core/boundedFile.d.ts.map +1 -0
  174. package/types/lib/core/brotliProbe.d.ts +37 -0
  175. package/types/lib/core/brotliProbe.d.ts.map +1 -0
  176. package/types/lib/core/env.d.ts +14 -0
  177. package/types/lib/core/env.d.ts.map +1 -1
  178. package/types/lib/core/fs.d.ts +4 -0
  179. package/types/lib/core/fs.d.ts.map +1 -1
  180. package/types/lib/core/globPatterns.d.ts +70 -0
  181. package/types/lib/core/globPatterns.d.ts.map +1 -0
  182. package/types/lib/core/httpClient.d.ts +24 -0
  183. package/types/lib/core/httpClient.d.ts.map +1 -1
  184. package/types/lib/core/lockPaths.d.ts +19 -0
  185. package/types/lib/core/lockPaths.d.ts.map +1 -0
  186. package/types/lib/core/paths.d.ts +9 -0
  187. package/types/lib/core/paths.d.ts.map +1 -1
  188. package/types/lib/core/processTree.d.ts +17 -4
  189. package/types/lib/core/processTree.d.ts.map +1 -1
  190. package/types/lib/core/projectConfig.d.ts +47 -8
  191. package/types/lib/core/projectConfig.d.ts.map +1 -1
  192. package/types/lib/core/toolRegistry.d.ts +36 -0
  193. package/types/lib/core/toolRegistry.d.ts.map +1 -0
  194. package/types/lib/ecosystems/cppEvidence.d.ts +40 -13
  195. package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
  196. package/types/lib/ecosystems/cppIncludeResolver.d.ts +2 -1
  197. package/types/lib/ecosystems/cppIncludeResolver.d.ts.map +1 -1
  198. package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
  199. package/types/lib/ecosystems/gemHostProbe.d.ts +28 -0
  200. package/types/lib/ecosystems/gemHostProbe.d.ts.map +1 -0
  201. package/types/lib/ecosystems/golem.d.ts.map +1 -1
  202. package/types/lib/ecosystems/gradleutils.d.ts +294 -20
  203. package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
  204. package/types/lib/ecosystems/jsEvidence.d.ts +14 -1
  205. package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
  206. package/types/lib/ecosystems/kosi.d.ts.map +1 -1
  207. package/types/lib/ecosystems/npmVersionResolution.d.ts +119 -0
  208. package/types/lib/ecosystems/npmVersionResolution.d.ts.map +1 -0
  209. package/types/lib/ecosystems/parsers-bazel.d.ts.map +1 -1
  210. package/types/lib/ecosystems/parsers-js.d.ts +17 -20
  211. package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
  212. package/types/lib/ecosystems/parsers-misc.d.ts +19 -0
  213. package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
  214. package/types/lib/ecosystems/parsers-python.d.ts +10 -0
  215. package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
  216. package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
  217. package/types/lib/ecosystems/pythonutils.d.ts +19 -1
  218. package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
  219. package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -1
  220. package/types/lib/ecosystems/rubyutils.d.ts +144 -12
  221. package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
  222. package/types/lib/ecosystems/rusi.d.ts.map +1 -1
  223. package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -1
  224. package/types/lib/ecosystems/scalasem.d.ts +58 -16
  225. package/types/lib/ecosystems/scalasem.d.ts.map +1 -1
  226. package/types/lib/ecosystems/vendoredCode.d.ts +26 -0
  227. package/types/lib/ecosystems/vendoredCode.d.ts.map +1 -1
  228. package/types/lib/ecosystems/venvProbe.d.ts +40 -0
  229. package/types/lib/ecosystems/venvProbe.d.ts.map +1 -0
  230. package/types/lib/evinser/evinser.d.ts +120 -13
  231. package/types/lib/evinser/evinser.d.ts.map +1 -1
  232. package/types/lib/evinser/scalasem.d.ts.map +1 -1
  233. package/types/lib/helpers/agenticToolutils.d.ts +53 -19
  234. package/types/lib/helpers/agenticToolutils.d.ts.map +1 -1
  235. package/types/lib/helpers/bomSigner.d.ts +20 -3
  236. package/types/lib/helpers/bomSigner.d.ts.map +1 -1
  237. package/types/lib/helpers/jssSigner.d.ts +288 -0
  238. package/types/lib/helpers/jssSigner.d.ts.map +1 -0
  239. package/types/lib/helpers/vsixutils.d.ts +303 -19
  240. package/types/lib/helpers/vsixutils.d.ts.map +1 -1
  241. package/types/lib/inventory/agentBlueprint.d.ts +70 -0
  242. package/types/lib/inventory/agentBlueprint.d.ts.map +1 -0
  243. package/types/lib/inventory/agentToolNames.d.ts +51 -0
  244. package/types/lib/inventory/agentToolNames.d.ts.map +1 -0
  245. package/types/lib/inventory/aiCollector.d.ts.map +1 -1
  246. package/types/lib/inventory/aiInventory.d.ts.map +1 -1
  247. package/types/lib/inventory/aiProviders.d.ts +85 -0
  248. package/types/lib/inventory/aiProviders.d.ts.map +1 -0
  249. package/types/lib/inventory/atomUtils.d.ts +19 -0
  250. package/types/lib/inventory/atomUtils.d.ts.map +1 -1
  251. package/types/lib/inventory/bomUtils.d.ts.map +1 -1
  252. package/types/lib/inventory/brotliDecoder.d.ts +58 -0
  253. package/types/lib/inventory/brotliDecoder.d.ts.map +1 -0
  254. package/types/lib/inventory/cbomutils.d.ts +17 -0
  255. package/types/lib/inventory/cbomutils.d.ts.map +1 -1
  256. package/types/lib/inventory/ciParsers/githubActionsLock.d.ts +101 -0
  257. package/types/lib/inventory/ciParsers/githubActionsLock.d.ts.map +1 -0
  258. package/types/lib/inventory/citations.d.ts +5 -0
  259. package/types/lib/inventory/citations.d.ts.map +1 -1
  260. package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
  261. package/types/lib/inventory/cyclonedx20.d.ts +99 -0
  262. package/types/lib/inventory/cyclonedx20.d.ts.map +1 -0
  263. package/types/lib/inventory/cyclonedx20Common.d.ts +102 -0
  264. package/types/lib/inventory/cyclonedx20Common.d.ts.map +1 -0
  265. package/types/lib/inventory/cyclonedx20Derived.d.ts +74 -0
  266. package/types/lib/inventory/cyclonedx20Derived.d.ts.map +1 -0
  267. package/types/lib/inventory/cyclonedx20Parties.d.ts +91 -0
  268. package/types/lib/inventory/cyclonedx20Parties.d.ts.map +1 -0
  269. package/types/lib/inventory/cyclonedx20Read.d.ts +51 -0
  270. package/types/lib/inventory/cyclonedx20Read.d.ts.map +1 -0
  271. package/types/lib/inventory/cyclonedx20ReadCommon.d.ts +69 -0
  272. package/types/lib/inventory/cyclonedx20ReadCommon.d.ts.map +1 -0
  273. package/types/lib/inventory/cyclonedx20ReadComponents.d.ts +77 -0
  274. package/types/lib/inventory/cyclonedx20ReadComponents.d.ts.map +1 -0
  275. package/types/lib/inventory/cyclonedx20ReadContext.d.ts +118 -0
  276. package/types/lib/inventory/cyclonedx20ReadContext.d.ts.map +1 -0
  277. package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts +40 -0
  278. package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts.map +1 -0
  279. package/types/lib/inventory/cyclonedx20ReadSections.d.ts +45 -0
  280. package/types/lib/inventory/cyclonedx20ReadSections.d.ts.map +1 -0
  281. package/types/lib/inventory/cyclonedx20Render.d.ts +53 -0
  282. package/types/lib/inventory/cyclonedx20Render.d.ts.map +1 -0
  283. package/types/lib/inventory/cyclonedx20RenderComponents.d.ts +73 -0
  284. package/types/lib/inventory/cyclonedx20RenderComponents.d.ts.map +1 -0
  285. package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts +29 -0
  286. package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts.map +1 -0
  287. package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts +110 -0
  288. package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts.map +1 -0
  289. package/types/lib/inventory/cyclonedx20RenderHardware.d.ts +42 -0
  290. package/types/lib/inventory/cyclonedx20RenderHardware.d.ts.map +1 -0
  291. package/types/lib/inventory/cyclonedx20RenderPatents.d.ts +26 -0
  292. package/types/lib/inventory/cyclonedx20RenderPatents.d.ts.map +1 -0
  293. package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts +55 -0
  294. package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts.map +1 -0
  295. package/types/lib/inventory/cyclonedx20RenderSections.d.ts +45 -0
  296. package/types/lib/inventory/cyclonedx20RenderSections.d.ts.map +1 -0
  297. package/types/lib/inventory/cyclonedx20Tables.d.ts +134 -0
  298. package/types/lib/inventory/cyclonedx20Tables.d.ts.map +1 -0
  299. package/types/lib/inventory/deps.d.ts +35 -2
  300. package/types/lib/inventory/deps.d.ts.map +1 -1
  301. package/types/lib/inventory/dosai.d.ts +36 -1
  302. package/types/lib/inventory/dosai.d.ts.map +1 -1
  303. package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
  304. package/types/lib/inventory/dotnetRuntime.d.ts +91 -0
  305. package/types/lib/inventory/dotnetRuntime.d.ts.map +1 -0
  306. package/types/lib/inventory/ecosystemFormulationParsers.d.ts +73 -0
  307. package/types/lib/inventory/ecosystemFormulationParsers.d.ts.map +1 -0
  308. package/types/lib/inventory/envcontext.d.ts +74 -12
  309. package/types/lib/inventory/envcontext.d.ts.map +1 -1
  310. package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
  311. package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
  312. package/types/lib/inventory/gtfobins.d.ts.map +1 -1
  313. package/types/lib/inventory/hbom.d.ts +11 -0
  314. package/types/lib/inventory/hbom.d.ts.map +1 -1
  315. package/types/lib/inventory/hbomLoader.d.ts +54 -0
  316. package/types/lib/inventory/hbomLoader.d.ts.map +1 -1
  317. package/types/lib/inventory/hostRuntimeProbe.d.ts +44 -0
  318. package/types/lib/inventory/hostRuntimeProbe.d.ts.map +1 -0
  319. package/types/lib/inventory/jvmLocalRepos.d.ts +5 -1
  320. package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -1
  321. package/types/lib/inventory/jvmToolEnv.d.ts +12 -0
  322. package/types/lib/inventory/jvmToolEnv.d.ts.map +1 -1
  323. package/types/lib/inventory/licenseEnhancer.d.ts.map +1 -1
  324. package/types/lib/inventory/mavenCentralMirror.d.ts +170 -0
  325. package/types/lib/inventory/mavenCentralMirror.d.ts.map +1 -0
  326. package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
  327. package/types/lib/inventory/nodeBuildInfo.d.ts +95 -0
  328. package/types/lib/inventory/nodeBuildInfo.d.ts.map +1 -0
  329. package/types/lib/inventory/nodeHostProbe.d.ts +15 -0
  330. package/types/lib/inventory/nodeHostProbe.d.ts.map +1 -0
  331. package/types/lib/inventory/occurrenceKey.d.ts +52 -0
  332. package/types/lib/inventory/occurrenceKey.d.ts.map +1 -0
  333. package/types/lib/inventory/osPackageResolver.d.ts +38 -0
  334. package/types/lib/inventory/osPackageResolver.d.ts.map +1 -1
  335. package/types/lib/inventory/phpBuildInfo.d.ts.map +1 -1
  336. package/types/lib/inventory/phpHostProbe.d.ts.map +1 -1
  337. package/types/lib/inventory/pqcMigration.d.ts +84 -0
  338. package/types/lib/inventory/pqcMigration.d.ts.map +1 -0
  339. package/types/lib/inventory/rubyBuildInfo.d.ts +271 -0
  340. package/types/lib/inventory/rubyBuildInfo.d.ts.map +1 -0
  341. package/types/lib/inventory/rubyHostProbe.d.ts +47 -0
  342. package/types/lib/inventory/rubyHostProbe.d.ts.map +1 -0
  343. package/types/lib/inventory/rustFormulationParser.d.ts +7 -2
  344. package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
  345. package/types/lib/inventory/scalaCoords.d.ts.map +1 -1
  346. package/types/lib/inventory/scalaDedupe.d.ts +43 -0
  347. package/types/lib/inventory/scalaDedupe.d.ts.map +1 -0
  348. package/types/lib/inventory/source.d.ts +25 -0
  349. package/types/lib/inventory/source.d.ts.map +1 -1
  350. package/types/lib/managers/binary.d.ts.map +1 -1
  351. package/types/lib/managers/docker.d.ts +12 -0
  352. package/types/lib/managers/docker.d.ts.map +1 -1
  353. package/types/lib/parsers/huggingfaceManifest.d.ts +10 -1
  354. package/types/lib/parsers/huggingfaceManifest.d.ts.map +1 -1
  355. package/types/lib/parsers/huggingfaceUtils.d.ts +12 -0
  356. package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -1
  357. package/types/lib/parsers/kiroPermissions.d.ts +62 -0
  358. package/types/lib/parsers/kiroPermissions.d.ts.map +1 -0
  359. package/types/lib/parsers/largeJson.d.ts +4 -3
  360. package/types/lib/parsers/largeJson.d.ts.map +1 -1
  361. package/types/lib/parsers/vscodeExtensionId.d.ts +48 -0
  362. package/types/lib/parsers/vscodeExtensionId.d.ts.map +1 -0
  363. package/types/lib/server/server.d.ts.map +1 -1
  364. package/types/lib/stages/postgen/postgen.d.ts +7 -0
  365. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  366. package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
  367. package/types/lib/stages/postgen/specVersionCompat.d.ts +25 -0
  368. package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
  369. package/types/lib/stages/pregen/envAudit.d.ts.map +1 -1
  370. package/types/lib/stages/pregen/pregen.d.ts +12 -8
  371. package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
  372. package/types/lib/validator/bomValidator.d.ts +5 -1
  373. package/types/lib/validator/bomValidator.d.ts.map +1 -1
  374. package/types/lib/validator/complianceEngine.d.ts +4 -4
  375. package/types/lib/validator/complianceEngine.d.ts.map +1 -1
  376. package/types/lib/validator/complianceRules.d.ts +14 -2
  377. package/types/lib/validator/complianceRules.d.ts.map +1 -1
  378. package/types/lib/validator/index.d.ts +10 -0
  379. package/types/lib/validator/index.d.ts.map +1 -1
  380. package/types/lib/validator/reporters/json.d.ts.map +1 -1
@@ -0,0 +1,726 @@
1
+ /**
2
+ * Render-side conversion of 1.x component evidence and cryptoProperties to
3
+ * the CycloneDX 2.0 shapes (#/$defs/cyclonedx-component-2.0/$defs/componentEvidence,
4
+ * #/$defs/cyclonedx-cryptography-2.0/$defs/cryptoProperties).
5
+ */
6
+
7
+ import { thoughtLog } from "../core/logger.js";
8
+ import { collectToolBomRefs } from "./citations.js";
9
+ import {
10
+ clone,
11
+ copyDefined,
12
+ countDrop,
13
+ countRewrite,
14
+ countUnmapped,
15
+ isNonEmptyString,
16
+ isObjectRecord,
17
+ peekShadow,
18
+ } from "./cyclonedx20Common.js";
19
+ import {
20
+ ALGORITHM_FAMILY_ENUM,
21
+ ANALYSIS_TECHNIQUE_ENUM,
22
+ CDXGEN_PARTY_REF_ID,
23
+ FORBIDDEN_IDENTITY_TECHNIQUES,
24
+ IDENTITY_SCHEME_ENUM,
25
+ LICENSE_EVIDENCE_DETAIL_FIELDS,
26
+ PROTOCOL_FAMILY_ENUM,
27
+ } from "./cyclonedx20Tables.js";
28
+
29
+ /**
30
+ * Convert 1.x `evidence.identity[].field` into the 2.0 `scheme`
31
+ * (#/$defs/cyclonedx-component-2.0/$defs/identityScheme). Predefined schemes
32
+ * pass through; anything else uses the custom `{name}` branch when it
33
+ * validates, and is counted for the report either way.
34
+ */
35
+ function toIdentityScheme(field, stats) {
36
+ if (typeof field !== "string" || field.length === 0) {
37
+ return undefined;
38
+ }
39
+ if (IDENTITY_SCHEME_ENUM.has(field)) {
40
+ return field;
41
+ }
42
+ stats.customSchemes.add(field);
43
+ // identityScheme oneOf: predefined enum or a custom object with a name.
44
+ return { name: field };
45
+ }
46
+
47
+ /**
48
+ * Convert one identity-evidence method to the 2.0 identificationMethod shape.
49
+ * analysisMethod requires `[technique, confidence]`; a method without its own
50
+ * confidence inherits the identity entry's, and one with neither is dropped
51
+ * (never given an invented number).
52
+ */
53
+ function convertIdentityMethod(method, identityConfidence, attributed, stats) {
54
+ if (!isObjectRecord(method)) {
55
+ return undefined;
56
+ }
57
+ let technique = method.technique;
58
+ if (technique === "other") {
59
+ technique = "unknown";
60
+ }
61
+ let reason;
62
+ if (!ANALYSIS_TECHNIQUE_ENUM.has(technique)) {
63
+ reason = "technique not in the 2.0 analysisTechnique enum";
64
+ } else if (FORBIDDEN_IDENTITY_TECHNIQUES.has(technique)) {
65
+ reason = "technique forbidden for identificationMethod";
66
+ }
67
+ const confidence =
68
+ typeof method.confidence === "number"
69
+ ? method.confidence
70
+ : typeof identityConfidence === "number"
71
+ ? identityConfidence
72
+ : undefined;
73
+ if (!reason && confidence === undefined) {
74
+ reason = "method has no confidence and the identity entry has none";
75
+ }
76
+ if (reason) {
77
+ stats.droppedMethods.push({ reason, technique: method.technique });
78
+ countDrop(stats, "evidence.identity.methods");
79
+ return undefined;
80
+ }
81
+ const converted = { technique, confidence };
82
+ if (typeof method.value === "string") {
83
+ converted.value = method.value;
84
+ if (attributed) {
85
+ // A method of cdxgen's own analysis that names its matched value found
86
+ // the subject (#/$defs/cyclonedx-evidence-2.0/$defs/analysisResult:
87
+ // "detected"). For another tool's entry the result is not cdxgen's to
88
+ // claim.
89
+ converted.result = "detected";
90
+ }
91
+ }
92
+ if (typeof method.description === "string") {
93
+ converted.description = method.description;
94
+ }
95
+ return converted;
96
+ }
97
+
98
+ /**
99
+ * The refId prefix of the party derived for a tool other than cdxgen. Any
100
+ * refId that starts with it is a valid refIdType
101
+ * (#/$defs/cyclonedx-common-2.0/$defs/refIdType: non-empty and not starting
102
+ * with the BOM-Link intro `urn:cdx:`), whatever the tool's own refId is, so
103
+ * the tool refId is appended unchanged and the party refId stays readable and
104
+ * deterministic.
105
+ */
106
+ export const TOOL_PARTY_REF_ID_PREFIX = "party-tool-";
107
+
108
+ /**
109
+ * What the claims cdxgen writes at 2.0 are attributed with (#4591). cdxgen
110
+ * claims only analysis it did:
111
+ *
112
+ * - `toolRefId` is the refId of the cdxgen tool component, present only when
113
+ * the BOM's `metadata.tools` lists cdxgen with a `bom-ref` (the tool named
114
+ * "cdxgen", the same match findCdxgenToolBomRef in
115
+ * lib/inventory/citations.js makes). Identity evidence carries cdxgen's
116
+ * assertion, its tool and method results only when this is set.
117
+ * - `assertingTool` is set only without `toolRefId`: the first other tool
118
+ * component with a `bom-ref` (`{refId, toolRefId, label?}`), whose party
119
+ * asserts the component identifiers (`identifiers[].party` is required).
120
+ * With neither, cdxgen, as the converting tool, asserts the identifiers it
121
+ * wrote.
122
+ * - `timestamp` is the BOM timestamp when it has one.
123
+ *
124
+ * Nothing is invented: absent members stay absent.
125
+ *
126
+ * @param {object} bom BOM in the 1.x shape (only `metadata` is read)
127
+ * @returns {{toolRefId?: string, assertingTool?: {refId: string, toolRefId: string, label?: string}, timestamp?: string}} Claim context
128
+ */
129
+ export function identityClaimContext(bom) {
130
+ const toolRefs = new Set(collectToolBomRefs(bom));
131
+ const tools = bom?.metadata?.tools;
132
+ const candidates = Array.isArray(tools) ? tools : tools?.components || [];
133
+ const declaredTools = candidates.filter(
134
+ (tool) =>
135
+ isObjectRecord(tool) &&
136
+ isNonEmptyString(tool["bom-ref"]) &&
137
+ toolRefs.has(tool["bom-ref"]),
138
+ );
139
+ const cdxgenTool = declaredTools.find((tool) => tool.name === "cdxgen");
140
+ const claims = {};
141
+ if (cdxgenTool) {
142
+ claims.toolRefId = cdxgenTool["bom-ref"];
143
+ } else {
144
+ const otherTool = declaredTools.find((tool) => tool.name !== "cdxgen");
145
+ if (otherTool) {
146
+ claims.assertingTool = {
147
+ refId: `${TOOL_PARTY_REF_ID_PREFIX}${otherTool["bom-ref"]}`,
148
+ toolRefId: otherTool["bom-ref"],
149
+ };
150
+ if (isNonEmptyString(otherTool.name)) {
151
+ claims.assertingTool.label = otherTool.name;
152
+ }
153
+ }
154
+ }
155
+ if (isNonEmptyString(bom?.metadata?.timestamp)) {
156
+ claims.timestamp = bom.metadata.timestamp;
157
+ }
158
+ return claims;
159
+ }
160
+
161
+ /**
162
+ * The refId of the party asserting the component identifiers: the cdxgen
163
+ * party when cdxgen is the listed tool or no tool is listed, else the party
164
+ * of the first other listed tool (see identityClaimContext).
165
+ *
166
+ * @param {object} claims Claim context from identityClaimContext
167
+ * @returns {string} Party refId
168
+ */
169
+ export function identifierPartyRefId(claims) {
170
+ return claims?.assertingTool?.refId || CDXGEN_PARTY_REF_ID;
171
+ }
172
+
173
+ /**
174
+ * The parties the renderer derives from the claim context, in the order it
175
+ * appends them: the cdxgen party, then the asserting tool's party when there
176
+ * is one. Each is a party (#/$defs/cyclonedx-party-2.0/$defs/party) with the
177
+ * `asserter` role and a system identity
178
+ * (#/$defs/cyclonedx-party-2.0/$defs/system, kind `automation`) whose `ref`
179
+ * names the tool component only when that refId is declared. The renderer
180
+ * declares one only when the document references it; the reader drops one
181
+ * that matches exactly, since the render derives it again.
182
+ *
183
+ * @param {object} claims Claim context from identityClaimContext
184
+ * @param {Set<string>} declared refIds declared in the document
185
+ * @returns {object[]} Party declarations
186
+ */
187
+ export function derivedPartyDeclarations(claims, declared) {
188
+ const cdxgenSystem = { kind: "automation", label: "cdxgen" };
189
+ if (claims?.toolRefId && declared.has(claims.toolRefId)) {
190
+ cdxgenSystem.ref = claims.toolRefId;
191
+ }
192
+ const parties = [
193
+ {
194
+ refId: CDXGEN_PARTY_REF_ID,
195
+ roles: [{ role: "asserter" }],
196
+ system: cdxgenSystem,
197
+ },
198
+ ];
199
+ const tool = claims?.assertingTool;
200
+ if (tool) {
201
+ const system = { kind: "automation" };
202
+ if (tool.label) {
203
+ system.label = tool.label;
204
+ }
205
+ if (declared.has(tool.toolRefId)) {
206
+ system.ref = tool.toolRefId;
207
+ }
208
+ parties.push({ refId: tool.refId, roles: [{ role: "asserter" }], system });
209
+ }
210
+ return parties;
211
+ }
212
+
213
+ /**
214
+ * Convert one 1.x identity entry to componentIdentityEvidence
215
+ * (#/$defs/cyclonedx-component-2.0/$defs/componentIdentityEvidence). When
216
+ * cdxgen is the listed tool (#4591), the entry is cdxgen's attributed claim:
217
+ * `tools` names the helper recorded on the entry or, failing that, the cdxgen
218
+ * tool; `assertion` credits the cdxgen party as asserter
219
+ * (#/$defs/cyclonedx-evidence-2.0/$defs/assertion); and a method with a
220
+ * matched value has the result `detected`. For another tool's BOM cdxgen did
221
+ * not do that analysis, so none of these is added; the entry's own `tools`
222
+ * are kept. `timestamp` is the BOM's own when it has one.
223
+ *
224
+ * @param {object} entry 1.x identity evidence entry
225
+ * @param {object} stats Render counters from createRenderStats
226
+ * @returns {object|undefined} The 2.0 entry, or undefined without a field
227
+ */
228
+ export function convertIdentityEntry(entry, stats) {
229
+ if (!isObjectRecord(entry)) {
230
+ return undefined;
231
+ }
232
+ const scheme = toIdentityScheme(entry.field, stats);
233
+ if (scheme === undefined) {
234
+ countDrop(stats, "evidence.identity (no field)");
235
+ return undefined;
236
+ }
237
+ const attributed = isNonEmptyString(stats.claims.toolRefId);
238
+ const converted = { scheme };
239
+ if (typeof entry.concludedValue === "string") {
240
+ converted.concludedValue = entry.concludedValue;
241
+ }
242
+ if (typeof entry.confidence === "number") {
243
+ converted.confidence = entry.confidence;
244
+ }
245
+ if (Array.isArray(entry.methods)) {
246
+ const methods = entry.methods
247
+ .map((method) =>
248
+ convertIdentityMethod(method, entry.confidence, attributed, stats),
249
+ )
250
+ .filter(Boolean);
251
+ if (methods.length) {
252
+ converted.methods = methods;
253
+ }
254
+ }
255
+ if (Array.isArray(entry.tools) && entry.tools.length) {
256
+ converted.tools = clone(entry.tools);
257
+ } else if (attributed) {
258
+ converted.tools = [stats.claims.toolRefId];
259
+ }
260
+ if (attributed) {
261
+ converted.assertion = {
262
+ parties: [
263
+ { party: { ref: CDXGEN_PARTY_REF_ID }, role: { role: "asserter" } },
264
+ ],
265
+ };
266
+ }
267
+ if (isNonEmptyString(stats.claims.timestamp)) {
268
+ converted.timestamp = stats.claims.timestamp;
269
+ }
270
+ return converted;
271
+ }
272
+
273
+ /**
274
+ * Convert 1.x `evidence.identity` (an array or a single 1.5 object). An
275
+ * entry read from 2.0 whose 1.x projection is unchanged gets its 2.0
276
+ * original back (a foreign assertion stays the foreign party's); an edited
277
+ * one renders from the 1.x model.
278
+ */
279
+ function convertIdentityEvidence(identity, stats) {
280
+ const identities = [];
281
+ for (const entry of Array.isArray(identity) ? identity : [identity]) {
282
+ const converted =
283
+ peekShadow(stats, "identity", entry) ??
284
+ convertIdentityEntry(entry, stats);
285
+ if (converted) {
286
+ identities.push(converted);
287
+ }
288
+ }
289
+ return identities;
290
+ }
291
+
292
+ /**
293
+ * Convert occurrences
294
+ * (#/$defs/cyclonedx-evidence-2.0/$defs/occurrence, required `[location]`):
295
+ * the 1.x `bom-ref` becomes `refId`, every other 1.x field keeps its name.
296
+ */
297
+ function convertOccurrences(occurrences, stats) {
298
+ const converted = [];
299
+ for (const occurrence of occurrences) {
300
+ if (!isObjectRecord(occurrence) || !isNonEmptyString(occurrence.location)) {
301
+ countDrop(stats, "evidence.occurrences (no location)");
302
+ continue;
303
+ }
304
+ const entry = clone(occurrence);
305
+ if (entry["bom-ref"] !== undefined) {
306
+ if (isNonEmptyString(entry["bom-ref"])) {
307
+ entry.refId = entry["bom-ref"];
308
+ }
309
+ delete entry["bom-ref"];
310
+ }
311
+ converted.push(entry);
312
+ }
313
+ return converted;
314
+ }
315
+
316
+ /**
317
+ * Convert 1.x call stacks: the `callstack` object (or an array of them)
318
+ * becomes the `callStacks` array, and frames need `module`
319
+ * (#/$defs/cyclonedx-evidence-2.0/$defs/frame, required `[module]`).
320
+ */
321
+ function convertCallStacks(callstack, stats) {
322
+ const callStacks = [];
323
+ for (const entry of Array.isArray(callstack) ? callstack : [callstack]) {
324
+ if (!isObjectRecord(entry)) {
325
+ continue;
326
+ }
327
+ const frames = [];
328
+ for (const frame of entry.frames || []) {
329
+ if (isObjectRecord(frame) && typeof frame.module === "string") {
330
+ frames.push(clone(frame));
331
+ } else {
332
+ countDrop(stats, "evidence.callstack.frames (no module)");
333
+ }
334
+ }
335
+ if (frames.length) {
336
+ callStacks.push({ frames });
337
+ }
338
+ }
339
+ return callStacks;
340
+ }
341
+
342
+ /** Carry the licenseEvidence details; a 1.x `bom-ref` becomes `refId`. */
343
+ function withLicenseEvidenceDetails(entry, choice, stats) {
344
+ const converted = { ...entry };
345
+ if (isNonEmptyString(choice["bom-ref"]) && choice.refId === undefined) {
346
+ converted.refId = choice["bom-ref"];
347
+ }
348
+ copyDefined(converted, choice, LICENSE_EVIDENCE_DETAIL_FIELDS);
349
+ countUnmapped(
350
+ stats,
351
+ "evidence.licenses",
352
+ choice,
353
+ new Set([
354
+ "license",
355
+ "expression",
356
+ "bom-ref",
357
+ ...LICENSE_EVIDENCE_DETAIL_FIELDS,
358
+ ]),
359
+ );
360
+ return converted;
361
+ }
362
+
363
+ /**
364
+ * Convert evidence licenses to licenseEvidence
365
+ * (#/$defs/cyclonedx-component-2.0/$defs/licenseEvidence): a license may
366
+ * carry only `id` or `name`, or the entry is an `expression`.
367
+ */
368
+ function convertEvidenceLicenses(licenses, stats) {
369
+ const converted = [];
370
+ for (const choice of licenses) {
371
+ if (isObjectRecord(choice?.license)) {
372
+ const { id, name } = choice.license;
373
+ const license = isNonEmptyString(id)
374
+ ? { id }
375
+ : isNonEmptyString(name)
376
+ ? { name }
377
+ : undefined;
378
+ if (!license) {
379
+ countDrop(stats, "evidence.licenses (no id or name)");
380
+ continue;
381
+ }
382
+ for (const key of Object.keys(choice.license)) {
383
+ if (!Object.hasOwn(license, key)) {
384
+ countDrop(stats, `evidence.licenses.license.${key}`);
385
+ }
386
+ }
387
+ converted.push(withLicenseEvidenceDetails({ license }, choice, stats));
388
+ } else if (isNonEmptyString(choice?.expression)) {
389
+ converted.push(
390
+ withLicenseEvidenceDetails(
391
+ { expression: choice.expression },
392
+ choice,
393
+ stats,
394
+ ),
395
+ );
396
+ } else {
397
+ countDrop(stats, "evidence.licenses (not a license or expression)");
398
+ }
399
+ }
400
+ return converted;
401
+ }
402
+
403
+ /**
404
+ * Convert component evidence
405
+ * (#/$defs/cyclonedx-component-2.0/$defs/componentEvidence). The 1.x
406
+ * `callstack` object becomes the `callStacks` array; identity `field` becomes
407
+ * `scheme`. Every nested object is cloned, so nothing is shared with the
408
+ * input.
409
+ */
410
+ export function convertComponentEvidence(evidence, stats) {
411
+ if (!isObjectRecord(evidence)) {
412
+ return undefined;
413
+ }
414
+ const converted = {};
415
+ if (evidence.identity !== undefined) {
416
+ const identities = convertIdentityEvidence(evidence.identity, stats);
417
+ if (identities.length) {
418
+ converted.identity = identities;
419
+ }
420
+ }
421
+ if (Array.isArray(evidence.occurrences)) {
422
+ const occurrences = convertOccurrences(evidence.occurrences, stats);
423
+ if (occurrences.length) {
424
+ converted.occurrences = occurrences;
425
+ }
426
+ }
427
+ if (evidence.callstack !== undefined) {
428
+ const callStacks = convertCallStacks(evidence.callstack, stats);
429
+ if (callStacks.length) {
430
+ converted.callStacks = callStacks;
431
+ }
432
+ }
433
+ if (Array.isArray(evidence.licenses) && evidence.licenses.length) {
434
+ const licenses = convertEvidenceLicenses(evidence.licenses, stats);
435
+ if (licenses.length) {
436
+ converted.licenses = licenses;
437
+ }
438
+ }
439
+ if (Array.isArray(evidence.copyright) && evidence.copyright.length) {
440
+ // copyrightEvidence requires `text`; drop entries without it.
441
+ const copyright = [];
442
+ for (const entry of evidence.copyright) {
443
+ if (isObjectRecord(entry) && typeof entry.text === "string") {
444
+ copyright.push(clone(entry));
445
+ } else {
446
+ countDrop(stats, "evidence.copyright (no text)");
447
+ }
448
+ }
449
+ if (copyright.length) {
450
+ converted.copyright = copyright;
451
+ }
452
+ }
453
+ countUnmapped(
454
+ stats,
455
+ "evidence",
456
+ evidence,
457
+ new Set(["identity", "occurrences", "callstack", "licenses", "copyright"]),
458
+ );
459
+ return Object.keys(converted).length ? converted : undefined;
460
+ }
461
+
462
+ // Members of each 2.0 cryptoProperties object
463
+ // (#/$defs/cyclonedx-cryptography-2.0/$defs/cryptoProperties); a 1.x member
464
+ // outside these that no conversion below maps is counted.
465
+ const CRYPTO_MEMBERS_20 = Object.freeze({
466
+ cryptoProperties: new Set([
467
+ "assetType",
468
+ "algorithmProperties",
469
+ "certificateProperties",
470
+ "relatedCryptoMaterialProperties",
471
+ "protocolProperties",
472
+ "oid",
473
+ ]),
474
+ algorithmProperties: new Set([
475
+ "primitive",
476
+ "algorithmFamily",
477
+ "parameterSetIdentifier",
478
+ "ellipticCurve",
479
+ "executionEnvironment",
480
+ "implementationPlatform",
481
+ "mode",
482
+ "padding",
483
+ "cryptoFunctions",
484
+ "classicalSecurityLevel",
485
+ "nistQuantumSecurityLevel",
486
+ "secProperties",
487
+ ]),
488
+ certificateProperties: new Set([
489
+ "serialNumber",
490
+ "subjectName",
491
+ "issuerName",
492
+ "notValidBefore",
493
+ "notValidAfter",
494
+ "certificateFormat",
495
+ "certificateFileExtension",
496
+ "fingerprint",
497
+ "certificateState",
498
+ "creationDate",
499
+ "activationDate",
500
+ "deactivationDate",
501
+ "revocationDate",
502
+ "destructionDate",
503
+ "renewal",
504
+ "certificateExtensions",
505
+ "relatedCryptographicAssets",
506
+ ]),
507
+ relatedCryptoMaterialProperties: new Set([
508
+ "type",
509
+ "id",
510
+ "state",
511
+ "rotation",
512
+ "creationDate",
513
+ "activationDate",
514
+ "updateDate",
515
+ "expirationDate",
516
+ "value",
517
+ "size",
518
+ "format",
519
+ "securedBy",
520
+ "fingerprint",
521
+ "relatedCryptographicAssets",
522
+ "keyUsage",
523
+ ]),
524
+ protocolProperties: new Set([
525
+ "type",
526
+ "version",
527
+ "cipherSuites",
528
+ "ikev2TransformTypes",
529
+ "relatedCryptographicAssets",
530
+ ]),
531
+ });
532
+
533
+ /**
534
+ * Move deprecated 1.x reference members into `relatedCryptographicAssets`
535
+ * (#/$defs/cyclonedx-cryptography-2.0/$defs/relatedCryptographicAsset), the
536
+ * list 1.7 names as their replacement. Each entry is [1.x member, asset
537
+ * type]; a member may hold one refType or a list of them. A reference the
538
+ * list already has is not repeated.
539
+ */
540
+ function moveToRelatedAssets(properties, members, label, stats) {
541
+ for (const [member, type] of members) {
542
+ if (properties[member] === undefined) {
543
+ continue;
544
+ }
545
+ const refs = [].concat(properties[member]);
546
+ delete properties[member];
547
+ const related = Array.isArray(properties.relatedCryptographicAssets)
548
+ ? properties.relatedCryptographicAssets
549
+ : [];
550
+ for (const ref of refs) {
551
+ if (!isNonEmptyString(ref)) {
552
+ countDrop(stats, `${label}.${member} (not a reference)`);
553
+ continue;
554
+ }
555
+ if (!related.some((asset) => asset?.ref === ref)) {
556
+ related.push({ type, ref });
557
+ }
558
+ countRewrite(
559
+ stats,
560
+ `${label}.${member} (moved to relatedCryptographicAssets)`,
561
+ );
562
+ }
563
+ if (related.length) {
564
+ properties.relatedCryptographicAssets = related;
565
+ }
566
+ }
567
+ }
568
+
569
+ /** Remove and count the members of `properties` 2.0 has no field for. */
570
+ function dropUnmapped(properties, kind, label, stats) {
571
+ for (const key of Object.keys(properties)) {
572
+ if (!CRYPTO_MEMBERS_20[kind].has(key)) {
573
+ if (properties[key] !== undefined) {
574
+ countDrop(stats, `${label}.${key}`);
575
+ }
576
+ delete properties[key];
577
+ }
578
+ }
579
+ }
580
+
581
+ /** algorithmProperties: enum and list-shape differences. */
582
+ function convertAlgorithmProperties(algorithmProperties, stats) {
583
+ if (algorithmProperties.curve !== undefined) {
584
+ countDrop(stats, "cryptoProperties.algorithmProperties.curve");
585
+ delete algorithmProperties.curve;
586
+ }
587
+ if (
588
+ algorithmProperties.algorithmFamily !== undefined &&
589
+ !ALGORITHM_FAMILY_ENUM.has(algorithmProperties.algorithmFamily)
590
+ ) {
591
+ countDrop(stats, "cryptoProperties.algorithmProperties.algorithmFamily");
592
+ thoughtLog(
593
+ `CycloneDX 2.0 render dropped the algorithm family '${algorithmProperties.algorithmFamily}', which the pinned 2.0 cryptography defs do not list.`,
594
+ );
595
+ delete algorithmProperties.algorithmFamily;
596
+ }
597
+ // algorithmProperties.implementationPlatform and cryptoFunctions are
598
+ // arrays at 2.0; tolerate a 1.x emitter that wrote a plain string.
599
+ for (const listField of ["implementationPlatform", "cryptoFunctions"]) {
600
+ if (typeof algorithmProperties[listField] === "string") {
601
+ algorithmProperties[listField] = [algorithmProperties[listField]];
602
+ }
603
+ }
604
+ dropUnmapped(
605
+ algorithmProperties,
606
+ "algorithmProperties",
607
+ "cryptoProperties.algorithmProperties",
608
+ stats,
609
+ );
610
+ }
611
+
612
+ /**
613
+ * certificateProperties: the deprecated signature algorithm and subject
614
+ * public key references become related assets, and the deprecated
615
+ * `certificateExtension` (the file extension) becomes
616
+ * `certificateFileExtension` unless that is set already.
617
+ */
618
+ function convertCertificateProperties(certificateProperties, stats) {
619
+ const label = "cryptoProperties.certificateProperties";
620
+ moveToRelatedAssets(
621
+ certificateProperties,
622
+ [
623
+ ["signatureAlgorithmRef", "algorithm"],
624
+ ["subjectPublicKeyRef", "publicKey"],
625
+ ],
626
+ label,
627
+ stats,
628
+ );
629
+ const extension = certificateProperties.certificateExtension;
630
+ if (extension !== undefined) {
631
+ delete certificateProperties.certificateExtension;
632
+ if (certificateProperties.certificateFileExtension === undefined) {
633
+ certificateProperties.certificateFileExtension = extension;
634
+ countRewrite(
635
+ stats,
636
+ `${label}.certificateExtension (renamed certificateFileExtension)`,
637
+ );
638
+ } else if (certificateProperties.certificateFileExtension !== extension) {
639
+ countDrop(stats, `${label}.certificateExtension`);
640
+ }
641
+ }
642
+ dropUnmapped(certificateProperties, "certificateProperties", label, stats);
643
+ }
644
+
645
+ /**
646
+ * relatedCryptoMaterialProperties: the 1.7 securedBy.algorithmRef is one
647
+ * refType and a 2.0 list; the deprecated `algorithmRef` (the algorithm that
648
+ * generated the material) becomes a related asset, as 1.7 directs.
649
+ */
650
+ function convertRelatedMaterialProperties(related, stats) {
651
+ const label = "cryptoProperties.relatedCryptoMaterialProperties";
652
+ if (
653
+ isObjectRecord(related.securedBy) &&
654
+ typeof related.securedBy.algorithmRef === "string"
655
+ ) {
656
+ related.securedBy.algorithmRef = [related.securedBy.algorithmRef];
657
+ }
658
+ moveToRelatedAssets(related, [["algorithmRef", "algorithm"]], label, stats);
659
+ dropUnmapped(related, "relatedCryptoMaterialProperties", label, stats);
660
+ }
661
+
662
+ /**
663
+ * protocolProperties: protocol types outside the pinned 2.0 enum are
664
+ * dropped, and the deprecated `cryptoRefArray` becomes related assets.
665
+ */
666
+ function convertProtocolProperties(protocolProperties, stats) {
667
+ const label = "cryptoProperties.protocolProperties";
668
+ if (
669
+ protocolProperties.type !== undefined &&
670
+ !PROTOCOL_FAMILY_ENUM.has(protocolProperties.type)
671
+ ) {
672
+ delete protocolProperties.type;
673
+ countDrop(stats, `${label}.type`);
674
+ }
675
+ moveToRelatedAssets(
676
+ protocolProperties,
677
+ [["cryptoRefArray", "algorithm"]],
678
+ label,
679
+ stats,
680
+ );
681
+ // 1.7 still accepts the deprecated reference arrays as IKEv2 transform
682
+ // lists; a 2.0 transform holds the reference as its `algorithm`.
683
+ const transforms = protocolProperties.ikev2TransformTypes;
684
+ for (const transform of ["encr", "prf", "integ", "ke", "auth"]) {
685
+ if (Array.isArray(transforms?.[transform])) {
686
+ transforms[transform] = transforms[transform].map((entry) => {
687
+ if (typeof entry !== "string") {
688
+ return entry;
689
+ }
690
+ countRewrite(
691
+ stats,
692
+ `${label}.ikev2TransformTypes (reference → algorithm)`,
693
+ );
694
+ return { algorithm: entry };
695
+ });
696
+ }
697
+ }
698
+ dropUnmapped(protocolProperties, "protocolProperties", label, stats);
699
+ }
700
+
701
+ /**
702
+ * Convert cryptoProperties
703
+ * (#/$defs/cyclonedx-cryptography-2.0/$defs/cryptoProperties, required
704
+ * `[assetType]`): drop the deprecated free-text `curve` (2.0 keeps only
705
+ * `ellipticCurve`) and the algorithm families and protocol types the pinned
706
+ * 2.0 enums do not list, move the deprecated 1.x reference members into
707
+ * `relatedCryptographicAssets`, and count every member 2.0 has no field for.
708
+ */
709
+ export function convertCryptoProperties(cryptoProperties, stats) {
710
+ if (!isObjectRecord(cryptoProperties)) {
711
+ return undefined;
712
+ }
713
+ const converted = clone(cryptoProperties);
714
+ for (const [kind, convert] of [
715
+ ["algorithmProperties", convertAlgorithmProperties],
716
+ ["certificateProperties", convertCertificateProperties],
717
+ ["relatedCryptoMaterialProperties", convertRelatedMaterialProperties],
718
+ ["protocolProperties", convertProtocolProperties],
719
+ ]) {
720
+ if (isObjectRecord(converted[kind])) {
721
+ convert(converted[kind], stats);
722
+ }
723
+ }
724
+ dropUnmapped(converted, "cryptoProperties", "cryptoProperties", stats);
725
+ return converted;
726
+ }