@cdxgen/cdxgen 13.0.1 → 13.2.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 (286) hide show
  1. package/README.md +30 -16
  2. package/bin/audit.js +6 -0
  3. package/bin/cdxgen.js +141 -7
  4. package/bin/evinse.js +3 -1
  5. package/data/component-tags.json +8 -1
  6. package/data/crypto-oid.json +88 -12
  7. package/data/frameworks-list.json +86 -1
  8. package/data/remediations.json +1167 -0
  9. package/data/rules/ai-bom.yaml +78 -0
  10. package/data/rules/asar-archives.yaml +1 -1
  11. package/data/rules/build-fidelity.yaml +782 -0
  12. package/data/rules/cargo-rust.yaml +132 -0
  13. package/data/rules/mcp-servers.yaml +122 -0
  14. package/data/rules/package-integrity.yaml +13 -13
  15. package/lib/audit/index.js +48 -4
  16. package/lib/audit/scoring.js +2 -8
  17. package/lib/audit/targets.js +6 -1
  18. package/lib/cli/bomAssembly.js +32 -1
  19. package/lib/cli/cliOptions.js +94 -7
  20. package/lib/cli/index.js +268 -49
  21. package/lib/cli/jsBom.js +91 -5
  22. package/lib/cli/jvmBom.js +1515 -1314
  23. package/lib/cli/managedBom.js +249 -28
  24. package/lib/cli/nativeBom.js +986 -10
  25. package/lib/core/activity.js +120 -2
  26. package/lib/core/buildLedger.js +799 -0
  27. package/lib/core/deferredExit.js +141 -0
  28. package/lib/core/env.js +108 -2
  29. package/lib/core/fs.js +60 -0
  30. package/lib/core/logger.js +12 -99
  31. package/lib/core/severity.js +16 -0
  32. package/lib/core/syncFileWriter.js +106 -0
  33. package/lib/core/userAgent.js +151 -0
  34. package/lib/ecosystems/cargoCache.js +364 -0
  35. package/lib/ecosystems/caxa.js +13 -5
  36. package/lib/ecosystems/cppEvidence.js +40 -2
  37. package/lib/ecosystems/ecosystems.js +250 -91
  38. package/lib/ecosystems/golem.js +11 -1
  39. package/lib/ecosystems/gradleutils.js +498 -17
  40. package/lib/ecosystems/kosi.js +1256 -0
  41. package/lib/ecosystems/parsers-crystal.js +179 -0
  42. package/lib/ecosystems/parsers-dotnet.js +69 -39
  43. package/lib/ecosystems/parsers-elm.js +816 -0
  44. package/lib/ecosystems/parsers-gleam.js +1 -1
  45. package/lib/ecosystems/parsers-js.js +26 -0
  46. package/lib/ecosystems/parsers-julia.js +268 -0
  47. package/lib/ecosystems/parsers-jvm.js +9 -0
  48. package/lib/ecosystems/parsers-lua.js +218 -0
  49. package/lib/ecosystems/parsers-misc.js +188 -2
  50. package/lib/ecosystems/parsers-nim.js +221 -0
  51. package/lib/ecosystems/parsers-opam.js +180 -0
  52. package/lib/ecosystems/parsers-perl.js +277 -0
  53. package/lib/ecosystems/parsers-python.js +172 -36
  54. package/lib/ecosystems/parsers-r.js +148 -0
  55. package/lib/ecosystems/parsers-rebar.js +411 -0
  56. package/lib/ecosystems/parsers-rust.js +944 -19
  57. package/lib/ecosystems/parsers-spack.js +204 -0
  58. package/lib/ecosystems/parsers-stack.js +264 -0
  59. package/lib/ecosystems/parsers-terraform.js +194 -0
  60. package/lib/ecosystems/pypiClassifiers.js +326 -0
  61. package/lib/ecosystems/pythonutils.js +49 -1
  62. package/lib/ecosystems/rubyutils.js +13 -0
  63. package/lib/ecosystems/rusi.js +126 -6
  64. package/lib/evinser/evinser.js +141 -13
  65. package/lib/helpers/agenticToolutils.js +925 -0
  66. package/lib/helpers/remote/dependency-track.js +81 -14
  67. package/lib/inventory/agentFormulationParser.js +57 -4
  68. package/lib/inventory/aiCollector.js +504 -10
  69. package/lib/inventory/aiInventory.js +12 -0
  70. package/lib/inventory/analyzer.js +488 -30
  71. package/lib/inventory/astWorker.js +6 -0
  72. package/lib/inventory/auditCategories.js +17 -0
  73. package/lib/inventory/cbomutils.js +30 -0
  74. package/lib/inventory/cdxrs.js +7 -2
  75. package/lib/inventory/communityAiConfigParser.js +215 -2
  76. package/lib/inventory/depsUtils.js +72 -0
  77. package/lib/inventory/dosai.js +508 -22
  78. package/lib/inventory/envcontext.js +215 -24
  79. package/lib/inventory/evidenceUtils.js +13 -0
  80. package/lib/inventory/fetchBatch.js +131 -2
  81. package/lib/inventory/fetchRate.js +74 -11
  82. package/lib/inventory/forgeEnricher.js +3 -2
  83. package/lib/inventory/jvmToolEnv.js +594 -0
  84. package/lib/inventory/mcpConfigParser.js +166 -2
  85. package/lib/inventory/mcpDiscovery.js +11 -0
  86. package/lib/inventory/mcpServerManifest.js +389 -0
  87. package/lib/inventory/mcpbBundle.js +419 -0
  88. package/lib/inventory/osinfo.js +1 -0
  89. package/lib/inventory/plugins.js +3 -0
  90. package/lib/inventory/protobom.js +54 -88
  91. package/lib/inventory/protobomLoader.js +4 -0
  92. package/lib/inventory/rustFormulationParser.js +1 -1
  93. package/lib/inventory/source.js +10 -4
  94. package/lib/inventory/stylePackageRefs.js +41 -0
  95. package/lib/inventory/svelteUtils.js +524 -0
  96. package/lib/inventory/toolRequirements.js +903 -0
  97. package/lib/managers/binary.js +24 -0
  98. package/lib/managers/docker.js +26 -5
  99. package/lib/parsers/huggingfaceUtils.js +15 -7
  100. package/lib/parsers/onnx.js +294 -0
  101. package/lib/parsers/safetensors.js +114 -0
  102. package/lib/server/server.js +1 -1
  103. package/lib/stages/postgen/annotationBuilder.js +97 -0
  104. package/lib/stages/postgen/auditBom.js +76 -79
  105. package/lib/stages/postgen/introspection/annotate.js +320 -0
  106. package/lib/stages/postgen/introspection/commandFacts.js +293 -0
  107. package/lib/stages/postgen/introspection/emit.js +192 -0
  108. package/lib/stages/postgen/introspection/formulationEvidence.js +427 -0
  109. package/lib/stages/postgen/introspection/markers.js +250 -0
  110. package/lib/stages/postgen/introspection/reflect.js +1214 -0
  111. package/lib/stages/postgen/introspection/report.js +1208 -0
  112. package/lib/stages/postgen/introspection/score.js +1067 -0
  113. package/lib/stages/postgen/introspection/shapeCommand.js +304 -0
  114. package/lib/stages/postgen/parentEdge.js +156 -0
  115. package/lib/stages/postgen/postgen.js +284 -3
  116. package/lib/stages/postgen/ruleEngine.js +17 -0
  117. package/lib/stages/pregen/envAudit.js +42 -2
  118. package/lib/stages/pregen/pregen.js +1171 -6
  119. package/lib/third-party/arborist/snapshots/calc-dep-flags.test.cjs +462 -0
  120. package/lib/validator/bomValidator.js +11 -2
  121. package/package.json +26 -26
  122. package/types/lib/audit/index.d.ts.map +1 -1
  123. package/types/lib/audit/scoring.d.ts +2 -8
  124. package/types/lib/audit/scoring.d.ts.map +1 -1
  125. package/types/lib/audit/targets.d.ts.map +1 -1
  126. package/types/lib/cli/bomAssembly.d.ts.map +1 -1
  127. package/types/lib/cli/cliOptions.d.ts +2 -1
  128. package/types/lib/cli/cliOptions.d.ts.map +1 -1
  129. package/types/lib/cli/index.d.ts +10 -2
  130. package/types/lib/cli/index.d.ts.map +1 -1
  131. package/types/lib/cli/jsBom.d.ts +23 -0
  132. package/types/lib/cli/jsBom.d.ts.map +1 -1
  133. package/types/lib/cli/jvmBom.d.ts.map +1 -1
  134. package/types/lib/cli/managedBom.d.ts +33 -0
  135. package/types/lib/cli/managedBom.d.ts.map +1 -1
  136. package/types/lib/cli/nativeBom.d.ts +88 -8
  137. package/types/lib/cli/nativeBom.d.ts.map +1 -1
  138. package/types/lib/core/activity.d.ts.map +1 -1
  139. package/types/lib/core/buildLedger.d.ts +272 -0
  140. package/types/lib/core/buildLedger.d.ts.map +1 -0
  141. package/types/lib/core/deferredExit.d.ts +84 -0
  142. package/types/lib/core/deferredExit.d.ts.map +1 -0
  143. package/types/lib/core/env.d.ts +43 -1
  144. package/types/lib/core/env.d.ts.map +1 -1
  145. package/types/lib/core/fs.d.ts +21 -0
  146. package/types/lib/core/fs.d.ts.map +1 -1
  147. package/types/lib/core/logger.d.ts +2 -11
  148. package/types/lib/core/logger.d.ts.map +1 -1
  149. package/types/lib/core/severity.d.ts +11 -0
  150. package/types/lib/core/severity.d.ts.map +1 -0
  151. package/types/lib/core/syncFileWriter.d.ts +33 -0
  152. package/types/lib/core/syncFileWriter.d.ts.map +1 -0
  153. package/types/lib/core/userAgent.d.ts +56 -0
  154. package/types/lib/core/userAgent.d.ts.map +1 -0
  155. package/types/lib/ecosystems/cargoCache.d.ts +75 -0
  156. package/types/lib/ecosystems/cargoCache.d.ts.map +1 -0
  157. package/types/lib/ecosystems/caxa.d.ts.map +1 -1
  158. package/types/lib/ecosystems/cppEvidence.d.ts +1 -1
  159. package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
  160. package/types/lib/ecosystems/ecosystems.d.ts +15 -1
  161. package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
  162. package/types/lib/ecosystems/gradleutils.d.ts +53 -0
  163. package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
  164. package/types/lib/ecosystems/kosi.d.ts +73 -0
  165. package/types/lib/ecosystems/kosi.d.ts.map +1 -0
  166. package/types/lib/ecosystems/parsers-crystal.d.ts +27 -0
  167. package/types/lib/ecosystems/parsers-crystal.d.ts.map +1 -0
  168. package/types/lib/ecosystems/parsers-dotnet.d.ts +19 -0
  169. package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
  170. package/types/lib/ecosystems/parsers-elm.d.ts +79 -0
  171. package/types/lib/ecosystems/parsers-elm.d.ts.map +1 -0
  172. package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
  173. package/types/lib/ecosystems/parsers-julia.d.ts +57 -0
  174. package/types/lib/ecosystems/parsers-julia.d.ts.map +1 -0
  175. package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
  176. package/types/lib/ecosystems/parsers-lua.d.ts +50 -0
  177. package/types/lib/ecosystems/parsers-lua.d.ts.map +1 -0
  178. package/types/lib/ecosystems/parsers-misc.d.ts +23 -0
  179. package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
  180. package/types/lib/ecosystems/parsers-nim.d.ts +43 -0
  181. package/types/lib/ecosystems/parsers-nim.d.ts.map +1 -0
  182. package/types/lib/ecosystems/parsers-opam.d.ts +31 -0
  183. package/types/lib/ecosystems/parsers-opam.d.ts.map +1 -0
  184. package/types/lib/ecosystems/parsers-perl.d.ts +36 -0
  185. package/types/lib/ecosystems/parsers-perl.d.ts.map +1 -0
  186. package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
  187. package/types/lib/ecosystems/parsers-r.d.ts +35 -0
  188. package/types/lib/ecosystems/parsers-r.d.ts.map +1 -0
  189. package/types/lib/ecosystems/parsers-rebar.d.ts +42 -0
  190. package/types/lib/ecosystems/parsers-rebar.d.ts.map +1 -0
  191. package/types/lib/ecosystems/parsers-rust.d.ts +199 -0
  192. package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
  193. package/types/lib/ecosystems/parsers-spack.d.ts +33 -0
  194. package/types/lib/ecosystems/parsers-spack.d.ts.map +1 -0
  195. package/types/lib/ecosystems/parsers-stack.d.ts +35 -0
  196. package/types/lib/ecosystems/parsers-stack.d.ts.map +1 -0
  197. package/types/lib/ecosystems/parsers-terraform.d.ts +34 -0
  198. package/types/lib/ecosystems/parsers-terraform.d.ts.map +1 -0
  199. package/types/lib/ecosystems/pypiClassifiers.d.ts +80 -0
  200. package/types/lib/ecosystems/pypiClassifiers.d.ts.map +1 -0
  201. package/types/lib/ecosystems/pythonutils.d.ts +21 -1
  202. package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
  203. package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
  204. package/types/lib/ecosystems/rusi.d.ts.map +1 -1
  205. package/types/lib/evinser/evinser.d.ts +34 -1
  206. package/types/lib/evinser/evinser.d.ts.map +1 -1
  207. package/types/lib/helpers/agenticToolutils.d.ts +87 -0
  208. package/types/lib/helpers/agenticToolutils.d.ts.map +1 -0
  209. package/types/lib/helpers/remote/dependency-track.d.ts +45 -4
  210. package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -1
  211. package/types/lib/inventory/agentFormulationParser.d.ts.map +1 -1
  212. package/types/lib/inventory/aiCollector.d.ts.map +1 -1
  213. package/types/lib/inventory/aiInventory.d.ts.map +1 -1
  214. package/types/lib/inventory/analyzer.d.ts.map +1 -1
  215. package/types/lib/inventory/auditCategories.d.ts +12 -0
  216. package/types/lib/inventory/auditCategories.d.ts.map +1 -1
  217. package/types/lib/inventory/cbomutils.d.ts.map +1 -1
  218. package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
  219. package/types/lib/inventory/depsUtils.d.ts.map +1 -1
  220. package/types/lib/inventory/dosai.d.ts +43 -0
  221. package/types/lib/inventory/dosai.d.ts.map +1 -1
  222. package/types/lib/inventory/envcontext.d.ts.map +1 -1
  223. package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
  224. package/types/lib/inventory/fetchBatch.d.ts +43 -0
  225. package/types/lib/inventory/fetchBatch.d.ts.map +1 -1
  226. package/types/lib/inventory/fetchRate.d.ts +9 -6
  227. package/types/lib/inventory/fetchRate.d.ts.map +1 -1
  228. package/types/lib/inventory/forgeEnricher.d.ts.map +1 -1
  229. package/types/lib/inventory/jvmToolEnv.d.ts +190 -0
  230. package/types/lib/inventory/jvmToolEnv.d.ts.map +1 -0
  231. package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
  232. package/types/lib/inventory/mcpDiscovery.d.ts.map +1 -1
  233. package/types/lib/inventory/mcpServerManifest.d.ts +19 -0
  234. package/types/lib/inventory/mcpServerManifest.d.ts.map +1 -0
  235. package/types/lib/inventory/mcpbBundle.d.ts +19 -0
  236. package/types/lib/inventory/mcpbBundle.d.ts.map +1 -0
  237. package/types/lib/inventory/osinfo.d.ts.map +1 -1
  238. package/types/lib/inventory/plugins.d.ts.map +1 -1
  239. package/types/lib/inventory/protobom.d.ts +18 -13
  240. package/types/lib/inventory/protobom.d.ts.map +1 -1
  241. package/types/lib/inventory/protobomLoader.d.ts.map +1 -1
  242. package/types/lib/inventory/source.d.ts.map +1 -1
  243. package/types/lib/inventory/stylePackageRefs.d.ts +17 -0
  244. package/types/lib/inventory/stylePackageRefs.d.ts.map +1 -0
  245. package/types/lib/inventory/svelteUtils.d.ts +124 -0
  246. package/types/lib/inventory/svelteUtils.d.ts.map +1 -0
  247. package/types/lib/inventory/toolRequirements.d.ts +216 -0
  248. package/types/lib/inventory/toolRequirements.d.ts.map +1 -0
  249. package/types/lib/managers/binary.d.ts.map +1 -1
  250. package/types/lib/managers/docker.d.ts.map +1 -1
  251. package/types/lib/parsers/huggingfaceUtils.d.ts +8 -1
  252. package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -1
  253. package/types/lib/parsers/onnx.d.ts +28 -0
  254. package/types/lib/parsers/onnx.d.ts.map +1 -0
  255. package/types/lib/parsers/safetensors.d.ts +22 -0
  256. package/types/lib/parsers/safetensors.d.ts.map +1 -0
  257. package/types/lib/stages/postgen/annotationBuilder.d.ts +53 -0
  258. package/types/lib/stages/postgen/annotationBuilder.d.ts.map +1 -0
  259. package/types/lib/stages/postgen/auditBom.d.ts.map +1 -1
  260. package/types/lib/stages/postgen/introspection/annotate.d.ts +81 -0
  261. package/types/lib/stages/postgen/introspection/annotate.d.ts.map +1 -0
  262. package/types/lib/stages/postgen/introspection/commandFacts.d.ts +32 -0
  263. package/types/lib/stages/postgen/introspection/commandFacts.d.ts.map +1 -0
  264. package/types/lib/stages/postgen/introspection/emit.d.ts +71 -0
  265. package/types/lib/stages/postgen/introspection/emit.d.ts.map +1 -0
  266. package/types/lib/stages/postgen/introspection/formulationEvidence.d.ts +154 -0
  267. package/types/lib/stages/postgen/introspection/formulationEvidence.d.ts.map +1 -0
  268. package/types/lib/stages/postgen/introspection/markers.d.ts +58 -0
  269. package/types/lib/stages/postgen/introspection/markers.d.ts.map +1 -0
  270. package/types/lib/stages/postgen/introspection/reflect.d.ts +77 -0
  271. package/types/lib/stages/postgen/introspection/reflect.d.ts.map +1 -0
  272. package/types/lib/stages/postgen/introspection/report.d.ts +85 -0
  273. package/types/lib/stages/postgen/introspection/report.d.ts.map +1 -0
  274. package/types/lib/stages/postgen/introspection/score.d.ts +149 -0
  275. package/types/lib/stages/postgen/introspection/score.d.ts.map +1 -0
  276. package/types/lib/stages/postgen/introspection/shapeCommand.d.ts +79 -0
  277. package/types/lib/stages/postgen/introspection/shapeCommand.d.ts.map +1 -0
  278. package/types/lib/stages/postgen/parentEdge.d.ts +35 -0
  279. package/types/lib/stages/postgen/parentEdge.d.ts.map +1 -0
  280. package/types/lib/stages/postgen/postgen.d.ts +35 -2
  281. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  282. package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
  283. package/types/lib/stages/pregen/envAudit.d.ts.map +1 -1
  284. package/types/lib/stages/pregen/pregen.d.ts +131 -0
  285. package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
  286. package/types/lib/validator/bomValidator.d.ts.map +1 -1
package/lib/cli/index.js CHANGED
@@ -18,6 +18,7 @@ import {
18
18
  recordActivity,
19
19
  setActivityContext,
20
20
  } from "../core/activity.js";
21
+ import { recordDegradation } from "../core/buildLedger.js";
21
22
  import { hasAnyProjectType, PROJECT_TYPE_ALIASES } from "../core/env.js";
22
23
  import {
23
24
  clearFileDiscoveryCache,
@@ -31,6 +32,11 @@ import { thoughtLog } from "../core/logger.js";
31
32
  import { mapWithConcurrency } from "../core/parallel.js";
32
33
  import { dirNameStr } from "../core/paths.js";
33
34
  import { ui } from "../core/ui.js";
35
+ import { isElmProjectFile } from "../ecosystems/parsers-elm.js";
36
+ import {
37
+ isJuliaManifestFile,
38
+ isJuliaProjectFile,
39
+ } from "../ecosystems/parsers-julia.js";
34
40
  import {
35
41
  parseBitbucketPipelinesFile,
36
42
  parseContainerFile,
@@ -40,7 +46,7 @@ import {
40
46
  } from "../ecosystems/parsers-misc.js";
41
47
  import { isPyLockFile } from "../ecosystems/pylockutils.js";
42
48
  import {
43
- buildDependencyTrackBomPayload,
49
+ buildDependencyTrackBomRequest,
44
50
  getDependencyTrackBomApiUrl,
45
51
  } from "../helpers/remote/dependency-track.js";
46
52
  import { optionIncludesAiInventoryProjectType } from "../inventory/aiInventory.js";
@@ -89,6 +95,7 @@ import {
89
95
  determineParentComponent,
90
96
  } from "./bomAssembly.js";
91
97
  import {
98
+ createAgenticBom,
92
99
  createAsarBom,
93
100
  createCaxaBom,
94
101
  createChromeExtensionBom,
@@ -125,24 +132,36 @@ import {
125
132
  createGitHubBom,
126
133
  createHelmBom,
127
134
  createJenkinsBom,
135
+ createPerlBom,
128
136
  createPHPBom,
129
137
  createPythonBom,
138
+ createRBom,
130
139
  createRubyBom,
140
+ createTerraformBom,
131
141
  } from "./managedBom.js";
132
142
  import {
133
143
  createCargoCacheBom,
134
144
  createClojureBom,
135
145
  createCocoaBom,
136
146
  createCppBom,
147
+ createCrystalBom,
137
148
  createDartBom,
138
149
  createElixirBom,
150
+ createElmBom,
151
+ createErlangBom,
139
152
  createGleamBom,
140
153
  createGoBom,
141
154
  createHaskellBom,
155
+ createJuliaBom,
156
+ createLuaBom,
157
+ createNimBom,
142
158
  createNixBom,
159
+ createOCamlBom,
143
160
  createRustBom,
161
+ createSpackBom,
144
162
  createSwiftBom,
145
163
  createZigBom,
164
+ findStackLockFiles,
146
165
  getCargoCacheDir,
147
166
  } from "./nativeBom.js";
148
167
 
@@ -153,26 +172,42 @@ export {
153
172
  createGitHubBom,
154
173
  createHelmBom,
155
174
  createJenkinsBom,
175
+ createPerlBom,
156
176
  createPHPBom,
157
177
  createPixiBom,
158
178
  createPythonBom,
179
+ createRBom,
159
180
  createRubyBom,
181
+ createTerraformBom,
160
182
  } from "./managedBom.js";
161
183
  export {
162
184
  createClojureBom,
163
185
  createCocoaBom,
164
186
  createCppBom,
187
+ createCrystalBom,
165
188
  createDartBom,
166
189
  createElixirBom,
190
+ createElmBom,
191
+ createErlangBom,
167
192
  createGleamBom,
168
193
  createGoBom,
169
194
  createHaskellBom,
195
+ createJuliaBom,
196
+ createLuaBom,
197
+ createNimBom,
170
198
  createNixBom,
199
+ createOCamlBom,
171
200
  createRustBom,
201
+ createSpackBom,
172
202
  createSwiftBom,
173
203
  createZigBom,
174
204
  } from "./nativeBom.js";
175
205
 
206
+ import {
207
+ deferFailOnError,
208
+ isDeferredFailOnError,
209
+ } from "../core/deferredExit.js";
210
+
176
211
  const dirName = dirNameStr;
177
212
 
178
213
  const isWin = _platform() === "win32";
@@ -816,6 +851,23 @@ export async function createMultiXBom(pathList, options) {
816
851
  // from here on, so repeated walks of them can share one view of the tree.
817
852
  setDirWalkCacheRoot(options.allLayersExplodedDir);
818
853
  const scanOnePath = async (path) => {
854
+ try {
855
+ return await scanOnePathInner(path);
856
+ } catch (err) {
857
+ if (!isDeferredFailOnError(err)) {
858
+ throw err;
859
+ }
860
+ // The failing path contributes nothing, and the remaining paths still
861
+ // do: fail-on-error scopes the loss to the leg that failed.
862
+ return {
863
+ components: [],
864
+ dependencies: [],
865
+ options: { ...sharedOptions },
866
+ parentSubComponents: [],
867
+ };
868
+ }
869
+ };
870
+ const scanOnePathInner = async (path) => {
819
871
  // Each path accumulates into its own lists and its own view of options, so
820
872
  // that legs which record a parent component or a tool cannot overwrite
821
873
  // another path's. The lists are merged below in pathList order.
@@ -1433,6 +1485,14 @@ export async function createMultiXBom(pathList, options) {
1433
1485
  );
1434
1486
  }
1435
1487
  setProjectTypeActivityContext("jar", path);
1488
+ recordDegradation("jvm.jar.heuristic", {
1489
+ ecosystem: "java",
1490
+ tool: "jar",
1491
+ impact: "versions",
1492
+ path,
1493
+ detail:
1494
+ "Components are being inferred by scanning jar/war/ear files from disk.",
1495
+ });
1436
1496
  bomData = await createJarBom(path, options);
1437
1497
  if (bomData?.bomJson?.components?.length) {
1438
1498
  thoughtLog(
@@ -2029,7 +2089,8 @@ export async function createXBom(path, options) {
2029
2089
  `${options.multiProject ? "**/" : ""}cabal.project.freeze`,
2030
2090
  options,
2031
2091
  );
2032
- if (hackageFiles.length) {
2092
+ const stackLockDetectFiles = findStackLockFiles(path, options);
2093
+ if (hackageFiles.length || stackLockDetectFiles.length) {
2033
2094
  return createHaskellBom(path, options);
2034
2095
  }
2035
2096
 
@@ -2254,6 +2315,131 @@ export async function createXBom(path, options) {
2254
2315
  if (gleamTomlFiles.length) {
2255
2316
  return await createGleamBom(path, options);
2256
2317
  }
2318
+
2319
+ // Julia
2320
+ const juliaProjectFiles = getAllFiles(
2321
+ path,
2322
+ `${options.multiProject ? "**/" : ""}Project.toml`,
2323
+ options,
2324
+ );
2325
+ const juliaManifestFiles = getAllFiles(
2326
+ path,
2327
+ `${options.multiProject ? "**/" : ""}Manifest.toml`,
2328
+ options,
2329
+ );
2330
+ // `Project.toml` is not a name Julia owns — Cloud Native Buildpacks use it
2331
+ // too — so dispatch only when a file actually declares a Julia environment.
2332
+ if (
2333
+ juliaManifestFiles.some(isJuliaManifestFile) ||
2334
+ juliaProjectFiles.some(isJuliaProjectFile)
2335
+ ) {
2336
+ return await createJuliaBom(path, options);
2337
+ }
2338
+
2339
+ // Erlang with rebar3
2340
+ const rebarLockFiles = getAllFiles(
2341
+ path,
2342
+ `${options.multiProject ? "**/" : ""}rebar.lock`,
2343
+ options,
2344
+ );
2345
+ if (rebarLockFiles.length) {
2346
+ return await createErlangBom(path, options);
2347
+ }
2348
+
2349
+ // OCaml with opam
2350
+ const opamLockedFiles = getAllFiles(
2351
+ path,
2352
+ `${options.multiProject ? "**/" : ""}*.opam.locked`,
2353
+ options,
2354
+ );
2355
+ if (opamLockedFiles.length) {
2356
+ return await createOCamlBom(path, options);
2357
+ }
2358
+
2359
+ // Elm with elm.json (0.19) or elm-package.json (0.18)
2360
+ const elmJsonFiles = getAllFiles(
2361
+ path,
2362
+ `${options.multiProject ? "**/" : ""}elm.json`,
2363
+ options,
2364
+ ).filter(isElmProjectFile);
2365
+ const legacyElmFiles = getAllFiles(
2366
+ path,
2367
+ `${options.multiProject ? "**/" : ""}elm-package.json`,
2368
+ options,
2369
+ );
2370
+ if (elmJsonFiles.length || legacyElmFiles.length) {
2371
+ return await createElmBom(path, options);
2372
+ }
2373
+
2374
+ // Crystal with shards
2375
+ const shardYmlFiles = getAllFiles(
2376
+ path,
2377
+ `${options.multiProject ? "**/" : ""}shard.yml`,
2378
+ options,
2379
+ );
2380
+ if (shardYmlFiles.length) {
2381
+ return await createCrystalBom(path, options);
2382
+ }
2383
+
2384
+ // Nim with nimble
2385
+ const nimbleFiles = getAllFiles(
2386
+ path,
2387
+ `${options.multiProject ? "**/" : ""}*.nimble`,
2388
+ options,
2389
+ );
2390
+ if (nimbleFiles.length) {
2391
+ return await createNimBom(path, options);
2392
+ }
2393
+
2394
+ // Lua with LuaRocks
2395
+ const rockspecFiles = getAllFiles(
2396
+ path,
2397
+ `${options.multiProject ? "**/" : ""}*.rockspec`,
2398
+ options,
2399
+ );
2400
+ if (rockspecFiles.length) {
2401
+ return await createLuaBom(path, options);
2402
+ }
2403
+
2404
+ // Spack environments
2405
+ const spackLockFiles = getAllFiles(
2406
+ path,
2407
+ `${options.multiProject ? "**/" : ""}spack.lock`,
2408
+ options,
2409
+ );
2410
+ if (spackLockFiles.length) {
2411
+ return await createSpackBom(path, options);
2412
+ }
2413
+
2414
+ // R with renv
2415
+ const renvLockFiles = getAllFiles(
2416
+ path,
2417
+ `${options.multiProject ? "**/" : ""}renv.lock`,
2418
+ options,
2419
+ );
2420
+ if (renvLockFiles.length) {
2421
+ return createRBom(path, options);
2422
+ }
2423
+
2424
+ // Perl with Carton
2425
+ const cpanSnapshotFiles = getAllFiles(
2426
+ path,
2427
+ `${options.multiProject ? "**/" : ""}cpanfile.snapshot`,
2428
+ options,
2429
+ );
2430
+ if (cpanSnapshotFiles.length) {
2431
+ return createPerlBom(path, options);
2432
+ }
2433
+
2434
+ // Terraform and OpenTofu providers
2435
+ const tfLockFiles = getAllFiles(
2436
+ path,
2437
+ `${options.multiProject ? "**/" : ""}.terraform.lock.hcl`,
2438
+ options,
2439
+ );
2440
+ if (tfLockFiles.length) {
2441
+ return createTerraformBom(path, options);
2442
+ }
2257
2443
  }
2258
2444
 
2259
2445
  /**
@@ -2292,7 +2478,28 @@ export async function createHBom(_path, options) {
2292
2478
  * @param {Object} options Parse options from the cli
2293
2479
  * @returns {Promise<Object>} Promise resolving to BOM object
2294
2480
  */
2481
+ /**
2482
+ * Generate a BOM for one path, letting a deferred fail-on-error abort return
2483
+ * the empty BOM the flag promises rather than unwinding past the reports.
2484
+ *
2485
+ * @param {string} path Source path.
2486
+ * @param {Object} options CLI options.
2487
+ * @returns {Promise<Object>} BOM NS data.
2488
+ */
2295
2489
  export async function createBom(path, options) {
2490
+ try {
2491
+ return await createBomForPath(path, options);
2492
+ } catch (err) {
2493
+ if (!isDeferredFailOnError(err)) {
2494
+ throw err;
2495
+ }
2496
+ // fail-on-error forbids an incomplete result, so the extractor kept
2497
+ // nothing; the CLI still writes the reports and exits non-zero.
2498
+ return buildBomNSData(options, [], "", { src: path, filename: "" });
2499
+ }
2500
+ }
2501
+
2502
+ async function createBomForPath(path, options) {
2296
2503
  clearFileDiscoveryCache();
2297
2504
  let { projectType } = options;
2298
2505
  if (!projectType) {
@@ -2327,7 +2534,11 @@ export async function createBom(path, options) {
2327
2534
  console.log(
2328
2535
  `OS BOM generation has failed due to problems with exporting the image ${path}`,
2329
2536
  );
2330
- options.failOnError && process.exit(1);
2537
+ deferFailOnError(options, {
2538
+ ecosystem: "container",
2539
+ tool: "docker",
2540
+ detail: "exporting the image for the OS BOM failed",
2541
+ });
2331
2542
  return {};
2332
2543
  }
2333
2544
  isContainerMode = true;
@@ -2367,7 +2578,11 @@ export async function createBom(path, options) {
2367
2578
  console.log(
2368
2579
  `OCI BOM generation has failed due to problems with exporting the image ${path}.`,
2369
2580
  );
2370
- options.failOnError && process.exit(1);
2581
+ deferFailOnError(options, {
2582
+ ecosystem: "container",
2583
+ tool: "docker",
2584
+ detail: "exporting the image for the OCI BOM failed",
2585
+ });
2371
2586
  return {};
2372
2587
  }
2373
2588
  if (DEBUG_MODE) {
@@ -2576,6 +2791,39 @@ export async function createBom(path, options) {
2576
2791
  if (PROJECT_TYPE_ALIASES["gleam"].includes(projectType[0])) {
2577
2792
  return await createGleamBom(path, options);
2578
2793
  }
2794
+ if (PROJECT_TYPE_ALIASES["julia"].includes(projectType[0])) {
2795
+ return await createJuliaBom(path, options);
2796
+ }
2797
+ if (PROJECT_TYPE_ALIASES["erlang"].includes(projectType[0])) {
2798
+ return await createErlangBom(path, options);
2799
+ }
2800
+ if (PROJECT_TYPE_ALIASES["ocaml"].includes(projectType[0])) {
2801
+ return await createOCamlBom(path, options);
2802
+ }
2803
+ if (PROJECT_TYPE_ALIASES["elm"].includes(projectType[0])) {
2804
+ return await createElmBom(path, options);
2805
+ }
2806
+ if (PROJECT_TYPE_ALIASES["crystal"].includes(projectType[0])) {
2807
+ return await createCrystalBom(path, options);
2808
+ }
2809
+ if (PROJECT_TYPE_ALIASES["nim"].includes(projectType[0])) {
2810
+ return await createNimBom(path, options);
2811
+ }
2812
+ if (PROJECT_TYPE_ALIASES["lua"].includes(projectType[0])) {
2813
+ return await createLuaBom(path, options);
2814
+ }
2815
+ if (PROJECT_TYPE_ALIASES["spack"].includes(projectType[0])) {
2816
+ return await createSpackBom(path, options);
2817
+ }
2818
+ if (PROJECT_TYPE_ALIASES["r"].includes(projectType[0])) {
2819
+ return createRBom(path, options);
2820
+ }
2821
+ if (PROJECT_TYPE_ALIASES["perl"].includes(projectType[0])) {
2822
+ return createPerlBom(path, options);
2823
+ }
2824
+ if (PROJECT_TYPE_ALIASES["terraform"].includes(projectType[0])) {
2825
+ return createTerraformBom(path, options);
2826
+ }
2579
2827
  if (PROJECT_TYPE_ALIASES["caxa"].includes(projectType[0])) {
2580
2828
  return await createCaxaBom(path, options);
2581
2829
  }
@@ -2585,6 +2833,9 @@ export async function createBom(path, options) {
2585
2833
  if (PROJECT_TYPE_ALIASES["vscode-extension"].includes(projectType[0])) {
2586
2834
  return await createVscodeExtensionBom(path, options);
2587
2835
  }
2836
+ if (PROJECT_TYPE_ALIASES["agentic"].includes(projectType[0])) {
2837
+ return await createAgenticBom(path, options);
2838
+ }
2588
2839
  if (PROJECT_TYPE_ALIASES["chrome-extension"].includes(projectType[0])) {
2589
2840
  return await createChromeExtensionBom(path, options);
2590
2841
  }
@@ -2660,8 +2911,8 @@ export async function submitBom(args, bomContents) {
2660
2911
  });
2661
2912
  return undefined;
2662
2913
  }
2663
- const bomPayload = buildDependencyTrackBomPayload(args, bomContents);
2664
- if (!bomPayload) {
2914
+ const bomRequest = buildDependencyTrackBomRequest(args, bomContents);
2915
+ if (!bomRequest) {
2665
2916
  console.log(
2666
2917
  "Invalid Dependency-Track submission arguments. Provide projectId or projectName (projectVersion defaults to main) and specify parent project either by UUID or by parent project name + version.",
2667
2918
  );
@@ -2674,21 +2925,21 @@ export async function submitBom(args, bomContents) {
2674
2925
  serverUrl,
2675
2926
  "params",
2676
2927
  args.projectName,
2677
- bomPayload.projectVersion,
2928
+ args.projectVersion || "main",
2678
2929
  );
2679
2930
  }
2680
2931
  try {
2681
2932
  const requestOptions = {
2682
- method: "PUT",
2933
+ method: "POST",
2683
2934
  followRedirect: false,
2684
2935
  https: {
2685
2936
  rejectUnauthorized: !args.skipDtTlsCheck,
2686
2937
  },
2687
2938
  headers: {
2688
2939
  "X-Api-Key": (args.apiKey || "").replace(/[\r\n]/g, ""),
2689
- "Content-Type": "application/json",
2940
+ "Content-Type": bomRequest.contentType,
2690
2941
  },
2691
- json: bomPayload,
2942
+ body: bomRequest.body,
2692
2943
  responseType: "json",
2693
2944
  context: {
2694
2945
  activityIntent: "bom-submit",
@@ -2711,47 +2962,15 @@ export async function submitBom(args, bomContents) {
2711
2962
  );
2712
2963
  } else if (error.response && error.response.statusCode === 405) {
2713
2964
  console.log(
2714
- "Method PUT not allowed on Dependency-Track server. Trying with POST ...",
2965
+ `The server at ${serverUrl} does not accept a multipart/form-data POST on /api/v1/bom. Check that the URL points to a Dependency-Track 4.x or later API server.`,
2966
+ );
2967
+ } else if (DEBUG_MODE) {
2968
+ console.log(
2969
+ "Unable to submit the SBOM to the Dependency-Track server",
2970
+ error,
2715
2971
  );
2716
- // Method not allowed errors
2717
- try {
2718
- return await cdxgenAgent(dependencyTrackApiUrl, {
2719
- method: "POST",
2720
- followRedirect: false,
2721
- https: {
2722
- rejectUnauthorized: !args.skipDtTlsCheck,
2723
- },
2724
- headers: {
2725
- "X-Api-Key": (args.apiKey || "").replace(/[\r\n]/g, ""),
2726
- "Content-Type": "application/json",
2727
- },
2728
- json: bomPayload,
2729
- responseType: "json",
2730
- context: {
2731
- activityIntent: "bom-submit",
2732
- },
2733
- }).json();
2734
- } catch (error) {
2735
- if (DEBUG_MODE) {
2736
- console.log(
2737
- "Unable to submit the SBOM to the Dependency-Track server using POST method",
2738
- error,
2739
- );
2740
- } else {
2741
- console.log(
2742
- "Unable to submit the SBOM to the Dependency-Track server using POST method",
2743
- );
2744
- }
2745
- }
2746
2972
  } else {
2747
- if (DEBUG_MODE) {
2748
- console.log(
2749
- "Unable to submit the SBOM to the Dependency-Track server using POST method",
2750
- error,
2751
- );
2752
- } else {
2753
- console.log("Unable to submit the SBOM to the Dependency-Track server");
2754
- }
2973
+ console.log("Unable to submit the SBOM to the Dependency-Track server");
2755
2974
  }
2756
2975
  // rethrow error as function is async and we should try to catch it in the caller
2757
2976
  throw error;
package/lib/cli/jsBom.js CHANGED
@@ -11,6 +11,8 @@ import {
11
11
  readEnvironmentVariable,
12
12
  recordSensitiveFileRead,
13
13
  } from "../core/activity.js";
14
+ import { recordDegradation } from "../core/buildLedger.js";
15
+ import { deferFailOnError } from "../core/deferredExit.js";
14
16
  import { hasAnyProjectType, isPackageManagerAllowed } from "../core/env.js";
15
17
  import { getAllFiles, safeExistsSync, safeSpawnSync } from "../core/fs.js";
16
18
  import { thoughtLog } from "../core/logger.js";
@@ -51,6 +53,10 @@ import {
51
53
  fetchHuggingFaceAssetInventory,
52
54
  normalizeHuggingFaceReference,
53
55
  } from "../ecosystems/remote/huggingface.js";
56
+ import {
57
+ AGENTIC_TOOL_PURL_TYPE,
58
+ collectAgenticTools,
59
+ } from "../helpers/agenticToolutils.js";
54
60
  import {
55
61
  cleanupTempDir,
56
62
  collectInstalledExtensions,
@@ -98,6 +104,13 @@ const isWin = _platform() === "win32";
98
104
  * local Modelfile/`.gguf` file input. Returns the explicit selection from
99
105
  * `getExactAiInventoryType` when one is present.
100
106
  *
107
+ * Direct HuggingFace interpretation of the source path is opt-in: only
108
+ * unambiguous references (`pkg:huggingface/...` purls and huggingface.co
109
+ * URLs) are recognized on their own. Bare `owner/repo`-shaped values are
110
+ * ordinary relative paths (eg: `repotests/sveltejs-realworld`) unless an AI
111
+ * inventory type such as `-t ai` is explicitly selected, in which case
112
+ * `getExactAiInventoryType` already returned it above.
113
+ *
101
114
  * @param {string} path Project or file path
102
115
  * @param {object} options CLI options
103
116
  * @returns {string|undefined} The detected AI inventory type (`"ai"`) or undefined
@@ -107,7 +120,7 @@ export function getDirectAiInventoryType(path, options) {
107
120
  if (exactAiInventoryType) {
108
121
  return exactAiInventoryType;
109
122
  }
110
- if (normalizeHuggingFaceReference(path)) {
123
+ if (normalizeHuggingFaceReference(path, { explicitOnly: true })) {
111
124
  return "ai";
112
125
  }
113
126
  try {
@@ -155,8 +168,10 @@ export async function createNodejsBom(path, options) {
155
168
  excludedAiInventoryTypes,
156
169
  );
157
170
  let aiInventory = { components: [], dependencies: [], services: [] };
171
+ // A value that exists on the local filesystem is always a project path -
172
+ // never a remote model id - so existing inputs skip remote resolution.
158
173
  const directHuggingFaceSource =
159
- exactAiInventoryType === "ai"
174
+ exactAiInventoryType === "ai" && !safeExistsSync(path)
160
175
  ? normalizeHuggingFaceReference(path)
161
176
  : undefined;
162
177
  if (directHuggingFaceSource?.repoId) {
@@ -529,6 +544,14 @@ export async function createNodejsBom(path, options) {
529
544
  isSecureMode &&
530
545
  !installArgs.join(" ").includes("--allow-git")
531
546
  ) {
547
+ recordDegradation("js.git-dependency", {
548
+ ecosystem: "npm",
549
+ tool: pkgMgr,
550
+ impact: "integrity",
551
+ command: `${pkgMgr} ${installArgs.join(" ")}`,
552
+ detail:
553
+ "Secure mode npm install may still fetch and install git dependencies.",
554
+ });
532
555
  console.log(
533
556
  "Consider passing '--allow-git=none' via the environment variable NPM_INSTALL_ARGS to prevent any git dependencies from being fetched and installed via npm.",
534
557
  );
@@ -580,6 +603,13 @@ export async function createNodejsBom(path, options) {
580
603
  `**PACKAGE MANAGER**: Let's run the '${pkgMgr}' command with the arguments '${installArgs.join(" ")}' to generate the needed lock files.`,
581
604
  );
582
605
  }
606
+ recordDegradation("js.no-lockfile", {
607
+ ecosystem: "npm",
608
+ tool: pkgMgr,
609
+ impact: "versions",
610
+ detail:
611
+ "No lockfile was found for this project, so the SBOM is generated without pinned dependency versions.",
612
+ });
583
613
  console.warn(
584
614
  "\x1b[1;35mNotice: Generating an SBOM without a lockfile is risky and non-deterministic. Consider generating and committing the lockfile to your repository to ensure reproducible builds and SBOMs.\x1b[0m",
585
615
  );
@@ -640,7 +670,11 @@ export async function createNodejsBom(path, options) {
640
670
  console.log("---------------");
641
671
  console.log(result.stderr);
642
672
  }
643
- options.failOnError && process.exit(1);
673
+ deferFailOnError(options, {
674
+ ecosystem: "npm",
675
+ tool: "npm",
676
+ detail: "the npm command failed",
677
+ });
644
678
  } else {
645
679
  anyInstallSuccess = true;
646
680
  }
@@ -936,7 +970,11 @@ export async function createNodejsBom(path, options) {
936
970
  );
937
971
  if (result.status === 1 || result.error) {
938
972
  console.error(result.stdout, result.stderr);
939
- options.failOnError && process.exit(1);
973
+ deferFailOnError(options, {
974
+ ecosystem: "npm",
975
+ tool: "npm",
976
+ detail: "the yarn or pnpm command failed",
977
+ });
940
978
  }
941
979
  }
942
980
  // Look for shrinkwrap file
@@ -1013,7 +1051,11 @@ export async function createNodejsBom(path, options) {
1013
1051
  pnpmLock,
1014
1052
  "was found!",
1015
1053
  );
1016
- options.failOnError && process.exit(1);
1054
+ deferFailOnError(options, {
1055
+ ecosystem: "npm",
1056
+ tool: "npm",
1057
+ detail: "no JavaScript dependency evidence could be collected",
1058
+ });
1017
1059
  }
1018
1060
  if (
1019
1061
  yarnLockFiles?.length &&
@@ -1719,6 +1761,50 @@ export async function createVscodeExtensionBom(path, options) {
1719
1761
  });
1720
1762
  }
1721
1763
 
1764
+ /**
1765
+ * Create a BOM that catalogs agentic CLI tools installed for the current user
1766
+ * (for example Kiro CLI, zcode, opencode, and Claude Code), along with the
1767
+ * agents, plugins, and providers they define.
1768
+ *
1769
+ * The scan is read-only and value-redacting: it records tool versions where a
1770
+ * declarative source exists, plus structural counts, but never reads
1771
+ * credentials, transcripts, session logs, or telemetry.
1772
+ *
1773
+ * @param {string} path Positional input. A host scan does not read a project
1774
+ * tree, so an explicit path other than the current directory is rejected
1775
+ * rather than silently ignored.
1776
+ * @param {Object} options Parse options from the CLI
1777
+ * @returns {Promise<Object>} Promise resolving to BOM data
1778
+ */
1779
+ export async function createAgenticBom(path, options) {
1780
+ // Guard against a surprising host-wide scan masquerading as a project scan.
1781
+ // cdxgen always supplies a positional path (defaulting to "."), so only an
1782
+ // explicit path that resolves somewhere other than the current directory is
1783
+ // treated as a mistake.
1784
+ const resolvedPath = path ? resolve(path) : process.cwd();
1785
+ if (resolvedPath !== process.cwd()) {
1786
+ throw new Error(
1787
+ "The 'agentic' project type performs a host-wide scan of installed " +
1788
+ "agentic CLI tool directories and does not accept a path argument. " +
1789
+ `Re-run without the path (received '${path}').`,
1790
+ );
1791
+ }
1792
+ // Must not go to stdout: every entry point keeps stdout reserved for the BOM
1793
+ // payload so `cdxgen -t agentic -o -` stays pipeable.
1794
+ thoughtLog(
1795
+ "Scanning the current user's home directory for installed agentic CLI tools.",
1796
+ );
1797
+ const inventory = collectAgenticTools(options);
1798
+ const pkgList = trimComponents(inventory.components || []);
1799
+ return buildBomNSData(options, pkgList, AGENTIC_TOOL_PURL_TYPE, {
1800
+ src: "~",
1801
+ filename: "agentic-cli-tools",
1802
+ nsMapping: {},
1803
+ dependencies: inventory.dependencies || [],
1804
+ services: inventory.services || [],
1805
+ });
1806
+ }
1807
+
1722
1808
  /**
1723
1809
  * Function to create BOM for Electron ASAR archives.
1724
1810
  *