@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
package/README.md CHANGED
@@ -121,7 +121,9 @@ Sections include:
121
121
  - [MCP Inventory](docs/MCP.md)
122
122
  - [REPL Guide](docs/REPL.md)
123
123
  - [Custom Properties](docs/CUSTOM_PROPERTIES.md)
124
- - [Claude Code Plugin](claude-plugin/README.md)
124
+ - [Coding Agent Plugin](agent-plugin/README.md)
125
+ - [Installing the plugin in coding agents](docs/AGENT_PLUGINS.md)
126
+ - [Agent CI recipes](docs/AGENT_CI.md)
125
127
  - [Deprecations](docs/DEPRECATIONS.md)
126
128
  - [Security Policy](SECURITY.md)
127
129
  - [Threat Model](docs/THREAT_MODEL.md)
@@ -216,7 +218,7 @@ Common asset names:
216
218
  #### Linux
217
219
 
218
220
  ```bash
219
- VERSION="v13.5.0"
221
+ VERSION="v13.7.0"
220
222
  ASSET="cdx-audit-linux-amd64"
221
223
  BASE_URL="https://github.com/cdxgen/cdxgen/releases/download/${VERSION}"
222
224
 
@@ -230,7 +232,7 @@ chmod +x "${ASSET}"
230
232
  #### macOS
231
233
 
232
234
  ```bash
233
- VERSION="v13.5.0"
235
+ VERSION="v13.7.0"
234
236
  ASSET="cdx-audit-darwin-arm64"
235
237
  BASE_URL="https://github.com/cdxgen/cdxgen/releases/download/${VERSION}"
236
238
 
@@ -244,7 +246,7 @@ chmod +x "${ASSET}"
244
246
  #### Windows (PowerShell)
245
247
 
246
248
  ```powershell
247
- $Version = "v13.5.0"
249
+ $Version = "v13.7.0"
248
250
  $Asset = "cdx-audit-windows-amd64.exe"
249
251
  $BaseUrl = "https://github.com/cdxgen/cdxgen/releases/download/$Version"
250
252
 
@@ -269,7 +271,7 @@ steps:
269
271
  env:
270
272
  GH_TOKEN: ${{ github.token }}
271
273
  run: |
272
- gh release download v13.5.0 \
274
+ gh release download v13.7.0 \
273
275
  --repo cdxgen/cdxgen \
274
276
  --pattern 'cdx-audit-linux-amd64' \
275
277
  --pattern 'cdx-audit-linux-amd64.sha256'
@@ -296,7 +298,7 @@ winget install cdxgen
296
298
 
297
299
  You can also use the cdxgen container image with node, deno, or bun runtime versions.
298
300
 
299
- The default version uses Node.js 24
301
+ The default version uses Node.js 26
300
302
 
301
303
  ```bash
302
304
  docker run --rm -e CDXGEN_DEBUG_MODE=debug -v /tmp:/tmp -v $(pwd):/app:rw -t ghcr.io/cdxgen/cdxgen:master -r /app -o /app/bom.json
@@ -337,7 +339,7 @@ npm install -g @cdxgen/cdxgen --ignore-scripts --min-release-age=2
337
339
  **pnpm**:
338
340
 
339
341
  ```shell
340
- pnpm add -g @cdxgen/cdxgen --omit=optional --ignore-scripts --minimum-release-age=2880
342
+ pnpm add -g @cdxgen/cdxgen --ignore-scripts --config.minimum-release-age=2880
341
343
  ```
342
344
 
343
345
  **bun**:
@@ -621,16 +623,21 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
621
623
  pnpm dlx @cdxgen/cdxgen-plugins-bin
622
624
  ```
623
625
 
624
- ## Claude Code plugin
626
+ ## Coding agent plugin
625
627
 
626
- The cdxgen toolkit is also packaged as a [Claude Code](https://claude.com/claude-code) plugin, so agents drive the correct command and flags — including the dry-run-first and no-auto-install safety constraints — instead of guessing.
628
+ The cdxgen toolkit is also packaged as a plugin for coding agents, so agents drive the correct command and flags, including the dry-run-first and no-auto-install safety constraints, instead of guessing. It is meant for Claude Code, OpenAI Codex, the GitHub Copilot CLI and app, Cursor, Gemini CLI, Kiro and opencode, and has been tried in Claude Code and Codex so far.
627
629
 
628
630
  ```shell
629
631
  claude plugin marketplace add cdxgen/cdxgen
630
632
  claude plugin install cdxgen@cdxgen-plugins
631
633
  ```
632
634
 
633
- It ships skills covering SBOM generation, container and rootfs scans, OBOM/HBOM, CBOM, AI-BOM and MCP inventory, BOM auditing, signing, validation, conversion, evidence enrichment, runtime tracing, and Dependency-Track publishing. See [claude-plugin/README.md](claude-plugin/README.md).
635
+ ```shell
636
+ codex plugin marketplace add cdxgen/cdxgen
637
+ codex plugin add cdxgen@cdxgen-plugins
638
+ ```
639
+
640
+ It ships skills covering SBOM generation, container and rootfs scans, OBOM/HBOM, CBOM, AI-BOM and MCP inventory, BOM auditing, signing, validation, conversion, evidence enrichment, runtime tracing, and Dependency-Track publishing. See [agent-plugin/README.md](agent-plugin/README.md) and the [installation guide](docs/AGENT_PLUGINS.md) for each client. To run cdxgen through an agent in GitHub Actions, see the [agent CI recipes](docs/AGENT_CI.md).
634
641
 
635
642
  ## Rust accelerator (cdxrs)
636
643
 
package/bin/audit.js CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { writeFileSync } from "node:fs";
4
3
  import { dirname } from "node:path";
5
4
  import process from "node:process";
6
5
 
@@ -13,6 +12,7 @@ import {
13
12
  retrieveCdxgenVersion,
14
13
  safeExistsSync,
15
14
  safeMkdirSync,
15
+ safeWriteSync,
16
16
  } from "../lib/ecosystems/utils.js";
17
17
 
18
18
  const args = yargs(hideBin(process.argv))
@@ -193,7 +193,7 @@ function writeOrPrint(output, outputPath) {
193
193
  if (!safeExistsSync(parentDir)) {
194
194
  safeMkdirSync(parentDir, { recursive: true });
195
195
  }
196
- writeFileSync(outputPath, output);
196
+ safeWriteSync(outputPath, output);
197
197
  }
198
198
 
199
199
  (async () => {
@@ -235,10 +235,13 @@ function writeOrPrint(output, outputPath) {
235
235
  report: args.report,
236
236
  });
237
237
  writeOrPrint(finalized.output, reportFile);
238
- process.exit(finalized.exitCode);
238
+ // exitCode instead of process.exit lets a piped stdout write drain before
239
+ // the process ends, and the finally block below still runs.
240
+ process.exitCode = finalized.exitCode;
239
241
  } catch (error) {
240
242
  console.error(error.message);
241
- process.exit(1);
243
+ // exitCode instead of process.exit lets pending stderr output drain.
244
+ process.exitCode = 1;
242
245
  } finally {
243
246
  progressTracker.stop();
244
247
  }
package/bin/cdxgen.js CHANGED
@@ -83,13 +83,24 @@ import {
83
83
  createOutputPlan,
84
84
  getOutputDirectory,
85
85
  } from "../lib/helpers/exportUtils.js";
86
+ import {
87
+ generateJssKeyPair,
88
+ signJssBom,
89
+ verifyJssBom,
90
+ } from "../lib/helpers/jssSigner.js";
86
91
  import {
87
92
  DEFAULT_CDX_SPEC_VERSION,
88
93
  getSupportedCycloneDxComponentTypes,
94
+ isCycloneDx20SpecVersion,
89
95
  isCycloneDxBom,
90
96
  normalizeCycloneDxComponentTypeFilter,
91
97
  toCycloneDxSpecVersionString,
92
98
  } from "../lib/inventory/bomUtils.js";
99
+ import {
100
+ DEPENDENCY_TRACK_CDX20_ERROR,
101
+ getInternalBom,
102
+ refreshRenderedBom,
103
+ } from "../lib/inventory/cyclonedx20.js";
93
104
  import {
94
105
  displaySelfThreatModel,
95
106
  printActivitySummary,
@@ -155,16 +166,37 @@ for (const configPattern of PROJECT_CONFIG_FILENAMES) {
155
166
  continue;
156
167
  }
157
168
  try {
158
- if (configPath.endsWith(".yml") || configPath.endsWith(".yaml")) {
159
- config = _load(fs.readFileSync(configPath, "utf-8"));
160
- } else {
161
- config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
162
- }
169
+ const parsedConfig =
170
+ configPath.endsWith(".yml") || configPath.endsWith(".yaml")
171
+ ? _load(fs.readFileSync(configPath, "utf-8"))
172
+ : JSON.parse(fs.readFileSync(configPath, "utf-8"));
163
173
  if (isSecureMode || DEBUG_MODE) {
164
174
  console.log(`Config file '${configPath}' loaded successfully.`);
165
175
  }
166
- const sanitized = sanitizeProjectConfig(config, dirname(configPath));
176
+ const sanitized = sanitizeProjectConfig(parsedConfig, dirname(configPath));
167
177
  config = sanitized.config;
178
+ for (const key of sanitized.operatorOnly) {
179
+ console.warn(
180
+ `\x1b[1;35mConfig file '${configPath}' sets '${key}', which only the command line or a CDXGEN_ environment variable may set. Ignoring it.\x1b[0m`,
181
+ );
182
+ }
183
+ for (const projectType of sanitized.hostScopeTypes) {
184
+ console.warn(
185
+ `\x1b[1;35mConfig file '${configPath}' selects the project type '${projectType}', which inventories this host rather than the project. Ignoring it. Pass '-t ${projectType}' on the command line if this is intentional.\x1b[0m`,
186
+ );
187
+ }
188
+ for (const key of sanitized.ignored) {
189
+ console.warn(
190
+ `Config file '${configPath}' sets '${key}', which is not an option a config file can set. Ignoring it.`,
191
+ );
192
+ }
193
+ for (const { key, pattern, reason } of sanitized.refusedPatterns) {
194
+ const shownPattern =
195
+ pattern.length > 80 ? `${pattern.slice(0, 77)}...` : pattern;
196
+ console.warn(
197
+ `\x1b[1;35mConfig file '${configPath}' sets the ${key} pattern '${shownPattern}', which ${reason}. Ignoring it. Pass the pattern on the command line if this is intentional.\x1b[0m`,
198
+ );
199
+ }
168
200
  for (const entry of sanitized.rejected) {
169
201
  console.warn(
170
202
  `\x1b[1;35mConfig file '${configPath}' sets '${entry}', which points outside the project directory. Ignoring it. Pass the option on the command line if this is intentional.\x1b[0m`,
@@ -425,7 +457,7 @@ const args = _yargs
425
457
  .option("generate-key-and-sign", {
426
458
  type: "boolean",
427
459
  description:
428
- "Generate a public/private key pair for SBOM_SIGN_ALGORITHM (RS512 by default) and then sign the generated SBOM using the JSON Signature Format (JSF).",
460
+ "Generate a public/private key pair for SBOM_SIGN_ALGORITHM and then sign the generated SBOM: with the JSON Signature Format (JSF, RS512 by default) at 1.x, or the JSON Signature Scheme (JSS, ITU-T X.590; Ed25519 by default) at --spec-version 2.0.",
429
461
  })
430
462
  .option("server", {
431
463
  type: "boolean",
@@ -490,6 +522,10 @@ const args = _yargs
490
522
  description: "Path for the usages slices file created by atom.",
491
523
  hidden: true,
492
524
  })
525
+ .option("callsites-slices-file", {
526
+ description: "Path for the callsites slices file created by atom.",
527
+ hidden: true,
528
+ })
493
529
  .option("data-flow-slices-file", {
494
530
  description: "Path for the data-flow slices file created by atom.",
495
531
  hidden: true,
@@ -630,7 +666,7 @@ const args = _yargs
630
666
  type: "boolean",
631
667
  default: false,
632
668
  description:
633
- "Generate formulation section with git metadata and build tools. Defaults to false.",
669
+ "Generate formulation section with git metadata, build tools and build inputs. On by default when CI=true, for BOM audits, the research and introspect profiles, OS project types and the cbom command; --no-include-formulation turns it off.",
634
670
  })
635
671
  .option("include-crypto", {
636
672
  type: "boolean",
@@ -693,6 +729,8 @@ const args = _yargs
693
729
  "suggest-build-tools",
694
730
  "ruby-docker-install",
695
731
  "resolve-gradle-distribution",
732
+ "gradle-prefer-lockfile",
733
+ "gradle-verification-fallback",
696
734
  "jvm-tool-setup",
697
735
  ],
698
736
  })
@@ -1204,6 +1242,21 @@ try {
1204
1242
  console.error(error.message);
1205
1243
  process.exit(1);
1206
1244
  }
1245
+ // Dependency-Track ingests CycloneDX 1.x only. Refuse an upload (server URL
1246
+ // plus API key, the same condition the submission below uses) before
1247
+ // generating, so a long scan does not end in an upload that cannot succeed.
1248
+ // Server mode checks each request instead, since a request may choose its own
1249
+ // version.
1250
+ if (
1251
+ !options.server &&
1252
+ typeof options.serverUrl === "string" &&
1253
+ options.serverUrl.length > 0 &&
1254
+ options.apiKey &&
1255
+ isCycloneDx20SpecVersion(options.specVersion)
1256
+ ) {
1257
+ console.error(DEPENDENCY_TRACK_CDX20_ERROR);
1258
+ process.exit(1);
1259
+ }
1207
1260
  if (!options.projectType) {
1208
1261
  thoughtLog(
1209
1262
  "Ok, the user wants me to identify all the project types and generate a consolidated BOM document.",
@@ -1276,6 +1329,7 @@ if (options.lifecycle) {
1276
1329
  const isHbomOnlyInvocation = isHbomOnlyProjectTypes(options.projectType);
1277
1330
  const advancedWarnings = applyAdvancedOptionsImpl(options, {
1278
1331
  isSecureMode: isSecureModeActive(),
1332
+ invokedCommandName,
1279
1333
  });
1280
1334
  // The config file comes from the working directory, usually the scanned
1281
1335
  // project, so whether the project's own code may run stays the operator's
@@ -1640,6 +1694,99 @@ const signCycloneDxPayload = (jsonPayload, keyDir, target, options) => {
1640
1694
  return signedBom;
1641
1695
  };
1642
1696
 
1697
+ /**
1698
+ * Signs a CycloneDX 2.0 payload with JSS (ITU-T X.590) using the configured
1699
+ * or generated key: the root and the nested members the draft allows (see
1700
+ * lib/helpers/jssSigner.js). A generated key is checked against the fresh
1701
+ * signature, as the JSF path does.
1702
+ *
1703
+ * @param {string} jsonPayload Serialized CycloneDX 2.0 BOM
1704
+ * @param {string|undefined} keyDir Directory for --generate-key-and-sign keys
1705
+ * @param {string} target Output the signed BOM is written to (for the activity log)
1706
+ * @param {Object} options CLI options
1707
+ * @returns {Object} Signed BOM
1708
+ * @throws {Error} When signing was requested but cannot be completed
1709
+ */
1710
+ const signJssPayload = (jsonPayload, keyDir, target, options) => {
1711
+ // Signing a supplied key needs SBOM_SIGN_ALGORITHM (see needsBomSigning);
1712
+ // only --generate-key-and-sign reaches here without one.
1713
+ const algorithm = readEnvironmentVariable("SBOM_SIGN_ALGORITHM") || "Ed25519";
1714
+ const sbomSignPrivateKey = readEnvironmentVariable("SBOM_SIGN_PRIVATE_KEY", {
1715
+ sensitive: true,
1716
+ });
1717
+ const sbomSignPrivateKeyBase64 = readEnvironmentVariable(
1718
+ "SBOM_SIGN_PRIVATE_KEY_BASE64",
1719
+ { sensitive: true },
1720
+ );
1721
+ let privateKey;
1722
+ let publicKeyFile;
1723
+ if (options.generateKeyAndSign) {
1724
+ if (!keyDir) {
1725
+ throw new Error(
1726
+ "--generate-key-and-sign needs a file output (-o) to write the generated keys next to.",
1727
+ );
1728
+ }
1729
+ publicKeyFile = join(keyDir, "public.key");
1730
+ const privateKeyFile = join(keyDir, "private.key");
1731
+ const generated = generateJssKeyPair(algorithm);
1732
+ safeWriteSync(
1733
+ publicKeyFile,
1734
+ generated.publicKey.export({ type: "spki", format: "pem" }),
1735
+ );
1736
+ // The private key is readable by the owner only.
1737
+ safeWriteSync(
1738
+ privateKeyFile,
1739
+ generated.privateKey.export({ type: "pkcs8", format: "pem" }),
1740
+ { mode: 0o600 },
1741
+ );
1742
+ console.log(
1743
+ "Created public/private key pairs for testing purposes",
1744
+ publicKeyFile,
1745
+ privateKeyFile,
1746
+ );
1747
+ privateKey = generated.privateKey;
1748
+ } else if (sbomSignPrivateKey) {
1749
+ if (!safeExistsSync(sbomSignPrivateKey)) {
1750
+ throw new Error(
1751
+ `The SBOM_SIGN_PRIVATE_KEY file '${sbomSignPrivateKey}' was not found.`,
1752
+ );
1753
+ }
1754
+ recordSensitiveFileRead(sbomSignPrivateKey, {
1755
+ label: "SBOM signing private key",
1756
+ });
1757
+ privateKey = fs.readFileSync(sbomSignPrivateKey);
1758
+ } else if (sbomSignPrivateKeyBase64) {
1759
+ privateKey = Buffer.from(sbomSignPrivateKeyBase64, "base64");
1760
+ } else {
1761
+ throw new Error(
1762
+ `Signing a CycloneDX 2.0 document needs a private key: set SBOM_SIGN_PRIVATE_KEY (PEM), SBOM_SIGN_PRIVATE_KEY_BASE64, or pass --generate-key-and-sign. Algorithm in use: ${algorithm}.`,
1763
+ );
1764
+ }
1765
+ thoughtLog(`Signing the BOM for "${target}" with JSS (${algorithm}).`);
1766
+ const signedBom = signJssBom(JSON.parse(jsonPayload), {
1767
+ algorithm,
1768
+ privateKey,
1769
+ });
1770
+ if (publicKeyFile) {
1771
+ const verdict = verifyJssBom(signedBom, {
1772
+ publicKey: fs.readFileSync(publicKeyFile, "utf8"),
1773
+ requireAll: true,
1774
+ });
1775
+ if (!verdict.valid) {
1776
+ throw new Error(
1777
+ `The new JSS signature does not verify with ${publicKeyFile}.`,
1778
+ );
1779
+ }
1780
+ console.log(
1781
+ "SBOM signature is verifiable natively with the public key and the algorithm",
1782
+ publicKeyFile,
1783
+ algorithm,
1784
+ );
1785
+ }
1786
+ recordActivity({ kind: "sign", status: "completed", target });
1787
+ return signedBom;
1788
+ };
1789
+
1643
1790
  /**
1644
1791
  * Signs the BOM for an output when signing is configured. A failure is
1645
1792
  * recorded and returned so that the caller can stop with a non-zero exit
@@ -1660,6 +1807,24 @@ const signForOutput = (bomJson, jsonPayload, keyDir, target, options) => {
1660
1807
  });
1661
1808
  return { bomJson, jsonPayload };
1662
1809
  }
1810
+ if (isCycloneDx20SpecVersion(bomJson?.specVersion || options?.specVersion)) {
1811
+ // A CycloneDX 2.0 document signs with JSS (ITU-T X.590) instead of JSF.
1812
+ try {
1813
+ const signedBom = signJssPayload(jsonPayload, keyDir, target, options);
1814
+ return {
1815
+ bomJson: signedBom,
1816
+ jsonPayload: stringifyJson(signedBom, options.jsonPretty),
1817
+ };
1818
+ } catch (err) {
1819
+ recordActivity({
1820
+ kind: "sign",
1821
+ reason: err.message,
1822
+ status: "failed",
1823
+ target,
1824
+ });
1825
+ return { bomJson, jsonPayload, signingError: err };
1826
+ }
1827
+ }
1663
1828
  try {
1664
1829
  const signedBom = signCycloneDxPayload(
1665
1830
  jsonPayload,
@@ -1998,7 +2163,10 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
1998
2163
  hasCriticalFindings,
1999
2164
  } = await import("../lib/stages/postgen/auditBom.js");
2000
2165
  thoughtLog("Let's run security audit...");
2001
- const postAuditFindings = await auditBom(bomNSData.bomJson, {
2166
+ // The audit and its annotations read the 1.x-shaped model; at 2.0 the
2167
+ // rendered document is refreshed once after the last mutation.
2168
+ const auditInternalBom = getInternalBom(bomNSData);
2169
+ const postAuditFindings = await auditBom(auditInternalBom, {
2002
2170
  ...options,
2003
2171
  getBomWithOras,
2004
2172
  });
@@ -2017,9 +2185,9 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
2017
2185
  }
2018
2186
  }
2019
2187
  if (postAuditFindings.length && options.specVersion >= 1.4) {
2020
- bomNSData.bomJson.annotations = [
2021
- ...(bomNSData.bomJson.annotations || []),
2022
- ...formatAnnotations(postAuditFindings, bomNSData.bomJson),
2188
+ auditInternalBom.annotations = [
2189
+ ...(auditInternalBom.annotations || []),
2190
+ ...formatAnnotations(postAuditFindings, auditInternalBom),
2023
2191
  ];
2024
2192
  thoughtLog(
2025
2193
  `Embedded ${postAuditFindings.length} audit findings as CycloneDX annotations`,
@@ -2053,7 +2221,7 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
2053
2221
  const requiredAuditTargetCount = collectAuditTargets(
2054
2222
  [
2055
2223
  {
2056
- bomJson: bomNSData.bomJson,
2224
+ bomJson: auditInternalBom,
2057
2225
  source: filePath,
2058
2226
  },
2059
2227
  ],
@@ -2074,7 +2242,7 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
2074
2242
  predictiveReport = await runAuditFromBoms(
2075
2243
  [
2076
2244
  {
2077
- bomJson: bomNSData.bomJson,
2245
+ bomJson: auditInternalBom,
2078
2246
  source: filePath,
2079
2247
  },
2080
2248
  ],
@@ -2111,14 +2279,14 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
2111
2279
  }
2112
2280
  const predictiveAnnotations = formatPredictiveAnnotations(
2113
2281
  predictiveReport,
2114
- bomNSData.bomJson,
2282
+ auditInternalBom,
2115
2283
  {
2116
2284
  minSeverity: options.bomAuditMinSeverity,
2117
2285
  },
2118
2286
  );
2119
2287
  if (predictiveAnnotations.length && options.specVersion >= 1.4) {
2120
- bomNSData.bomJson.annotations = [
2121
- ...(bomNSData.bomJson.annotations || []),
2288
+ auditInternalBom.annotations = [
2289
+ ...(auditInternalBom.annotations || []),
2122
2290
  ...predictiveAnnotations,
2123
2291
  ];
2124
2292
  thoughtLog(
@@ -2161,9 +2329,11 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
2161
2329
  target: internalCycloneDxInputPath,
2162
2330
  });
2163
2331
  } else {
2332
+ // Evinse reads and writes the 1.x shape, so the temp input is the
2333
+ // internal model, not the rendered 2.0 document.
2164
2334
  safeWriteSync(
2165
2335
  internalCycloneDxInputPath,
2166
- stringifyJson(bomNSData.bomJson, options.jsonPretty),
2336
+ stringifyJson(getInternalBom(bomNSData), options.jsonPretty),
2167
2337
  );
2168
2338
  }
2169
2339
  }
@@ -2193,7 +2363,7 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
2193
2363
  if (!options.projectType) {
2194
2364
  const evidenceLanguage = evinserModule.defaultEvidenceLanguage(
2195
2365
  filePath,
2196
- bomNSData?.bomJson,
2366
+ getInternalBom(bomNSData),
2197
2367
  options,
2198
2368
  );
2199
2369
  if (evidenceLanguage) {
@@ -2205,10 +2375,17 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
2205
2375
  "Skipping the evidence analysis since the BOM lists no package in a language it supports. Pass -t to choose the language.",
2206
2376
  );
2207
2377
  if (bomNSData) {
2208
- bomNSData.bomJson = applyEvidenceBasedFilter(
2209
- bomNSData.bomJson,
2378
+ // The filter mutates the 1.x model; the rendered 2.0 document is
2379
+ // refreshed below, once, after this last mutation.
2380
+ const filteredBom = applyEvidenceBasedFilter(
2381
+ getInternalBom(bomNSData),
2210
2382
  options,
2211
2383
  );
2384
+ if (bomNSData.internalBomJson) {
2385
+ bomNSData.internalBomJson = filteredBom;
2386
+ } else {
2387
+ bomNSData.bomJson = filteredBom;
2388
+ }
2212
2389
  }
2213
2390
  } else {
2214
2391
  const evinseOptions = evinserModule.buildEvinseOptions(
@@ -2216,6 +2393,12 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
2216
2393
  args,
2217
2394
  internalCycloneDxInputPath || options.output,
2218
2395
  );
2396
+ // The analysis reads the in-memory 1.x model. At 2.0 that model is
2397
+ // labelled 2.0 but is not a 2.0 document, so it is handed over
2398
+ // directly instead of being read back from the temporary file.
2399
+ if (bomNSData?.internalBomJson) {
2400
+ evinseOptions.inputBomJson = bomNSData.internalBomJson;
2401
+ }
2219
2402
  try {
2220
2403
  const dbObjMap = await evinserModule.prepareDB(evinseOptions);
2221
2404
  if (dbObjMap) {
@@ -2225,16 +2408,31 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
2225
2408
  );
2226
2409
  const evinseJson = await evinserModule.createEvinseFile(
2227
2410
  sliceArtefacts,
2228
- evinseOptions,
2411
+ { ...evinseOptions, returnInternalModel: true },
2229
2412
  );
2230
2413
  // The scope filter is deferred until here so the analyzers get to
2231
- // prove that an optional dependency is actually used.
2232
- bomNSData.bomJson = applyEvidenceBasedFilter(evinseJson, options);
2233
- if (options.print && evinseJson) {
2234
- printOccurrences(evinseJson);
2235
- printCallStack(evinseJson);
2414
+ // prove that an optional dependency is actually used. At 2.0
2415
+ // createEvinseFile runs postProcess again and would return the
2416
+ // rendered 2.0 document; `returnInternalModel` asks for the 1.x
2417
+ // model instead, which becomes the internal model and is
2418
+ // re-rendered below.
2419
+ const evinseInternalBom = evinseJson;
2420
+ if (bomNSData.internalBomJson) {
2421
+ bomNSData.internalBomJson = applyEvidenceBasedFilter(
2422
+ evinseInternalBom,
2423
+ options,
2424
+ );
2425
+ } else {
2426
+ bomNSData.bomJson = applyEvidenceBasedFilter(
2427
+ evinseInternalBom,
2428
+ options,
2429
+ );
2430
+ }
2431
+ if (options.print && evinseInternalBom) {
2432
+ printOccurrences(evinseInternalBom);
2433
+ printCallStack(evinseInternalBom);
2236
2434
  printReachables(sliceArtefacts);
2237
- printServices(evinseJson);
2435
+ printServices(evinseInternalBom);
2238
2436
  }
2239
2437
  }
2240
2438
  } catch (err) {
@@ -2249,6 +2447,10 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
2249
2447
  }
2250
2448
  }
2251
2449
  }
2450
+ // The last post-postProcess mutation is done; at 2.0 the rendered document
2451
+ // is refreshed from the internal model once, before validation, signing
2452
+ // and writing. At 1.x this is a no-op.
2453
+ refreshRenderedBom(bomNSData, options);
2252
2454
  // Perform automatic validation
2253
2455
  if (options.validate && bomNSData?.bomJson) {
2254
2456
  thoughtLog("Wait, let's check the generated BOM file for any issues.");
@@ -2302,7 +2504,12 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
2302
2504
  target: "spdx",
2303
2505
  });
2304
2506
  } else {
2305
- bomNSData.spdxJson = convertCycloneDxToSpdx(bomNSData.bomJson, options);
2507
+ // The SPDX converter reads the 1.x shape; at 2.0 that is the internal
2508
+ // model.
2509
+ bomNSData.spdxJson = convertCycloneDxToSpdx(
2510
+ getInternalBom(bomNSData),
2511
+ options,
2512
+ );
2306
2513
  recordActivity({
2307
2514
  kind: "convert",
2308
2515
  status: "completed",
@@ -2505,6 +2712,20 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
2505
2712
  status: "blocked",
2506
2713
  target: options.serverUrl,
2507
2714
  });
2715
+ } else if (isCycloneDx20SpecVersion(bomNSData.bomJson?.specVersion)) {
2716
+ // Unreachable from the CLI, which refuses this before generating; kept
2717
+ // so a 2.0 document can never reach Dependency-Track.
2718
+ recordActivity({
2719
+ kind: "submit",
2720
+ reason: DEPENDENCY_TRACK_CDX20_ERROR,
2721
+ status: "blocked",
2722
+ target: options.serverUrl,
2723
+ });
2724
+ console.error(DEPENDENCY_TRACK_CDX20_ERROR);
2725
+ if (cleanup) {
2726
+ cleanupSourceDir(srcDir);
2727
+ }
2728
+ process.exit(1);
2508
2729
  } else {
2509
2730
  try {
2510
2731
  recordActivity({
@@ -2543,7 +2764,8 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
2543
2764
  try {
2544
2765
  const { buildPublishCollectionPayload, publishTeaCollection } =
2545
2766
  await import("../lib/ecosystems/tea.js");
2546
- const parentComponent = bomNSData.bomJson.metadata?.component || {};
2767
+ const parentComponent =
2768
+ getInternalBom(bomNSData).metadata?.component || {};
2547
2769
  const projectName =
2548
2770
  options.teaCollectionName ||
2549
2771
  parentComponent.name ||
@@ -2619,17 +2841,18 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
2619
2841
  thoughtLog("BOM file is also available in .proto format!");
2620
2842
  }
2621
2843
  }
2622
- if (options.print && bomNSData.bomJson?.components) {
2623
- printSummary(bomNSData.bomJson);
2844
+ if (options.print && getInternalBom(bomNSData)?.components) {
2845
+ const printBom = getInternalBom(bomNSData);
2846
+ printSummary(printBom);
2624
2847
  if (options.includeFormulation) {
2625
- printFormulation(bomNSData.bomJson);
2848
+ printFormulation(printBom);
2626
2849
  }
2627
- printDependencyTree(bomNSData.bomJson);
2628
- printTable(bomNSData.bomJson);
2850
+ printDependencyTree(printBom);
2851
+ printTable(printBom);
2629
2852
  // CBOM related print
2630
2853
  if (options.includeCrypto) {
2631
- printTable(bomNSData.bomJson, ["cryptographic-asset"]);
2632
- printDependencyTree(bomNSData.bomJson, "provides");
2854
+ printTable(printBom, ["cryptographic-asset"]);
2855
+ printDependencyTree(printBom, "provides");
2633
2856
  }
2634
2857
  }
2635
2858
  if (isDryRun || DEBUG_MODE) {