@cdxgen/cdxgen 13.1.0 → 13.3.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 (283) hide show
  1. package/README.md +32 -15
  2. package/bin/cdxgen.js +243 -122
  3. package/bin/evinse.js +7 -0
  4. package/bin/sign.js +88 -14
  5. package/bin/tracebom.js +64 -4
  6. package/bin/validate.js +29 -7
  7. package/bin/verify.js +79 -39
  8. package/data/crypto-oid.json +88 -12
  9. package/data/remediations.json +47 -0
  10. package/data/rules/ai-bom.yaml +78 -0
  11. package/data/rules/cargo-rust.yaml +132 -0
  12. package/data/rules/mcp-servers.yaml +122 -0
  13. package/lib/audit/targets.js +6 -1
  14. package/lib/cli/bomAssembly.js +117 -15
  15. package/lib/cli/cliOptions.js +93 -1
  16. package/lib/cli/index.js +235 -5
  17. package/lib/cli/jsBom.js +108 -26
  18. package/lib/cli/jvmBom.js +68 -12
  19. package/lib/cli/managedBom.js +264 -41
  20. package/lib/cli/nativeBom.js +923 -15
  21. package/lib/core/activity.js +120 -2
  22. package/lib/core/env.js +44 -7
  23. package/lib/core/fs.js +174 -6
  24. package/lib/core/metadataProperties.js +97 -0
  25. package/lib/core/projectConfig.js +31 -4
  26. package/lib/core/userAgent.js +151 -0
  27. package/lib/ecosystems/bunutils.js +269 -101
  28. package/lib/ecosystems/cargoCache.js +364 -0
  29. package/lib/ecosystems/caxa.js +447 -7
  30. package/lib/ecosystems/cmakeResolver.js +66 -0
  31. package/lib/ecosystems/cppEvidence.js +104 -33
  32. package/lib/ecosystems/ecosystems.js +260 -99
  33. package/lib/ecosystems/golem.js +11 -1
  34. package/lib/ecosystems/gradleutils.js +185 -9
  35. package/lib/ecosystems/jsEvidence.js +19 -20
  36. package/lib/ecosystems/kosi.js +1263 -0
  37. package/lib/ecosystems/npmutils.js +110 -9
  38. package/lib/ecosystems/parsers-crystal.js +179 -0
  39. package/lib/ecosystems/parsers-dotnet.js +120 -49
  40. package/lib/ecosystems/parsers-elm.js +816 -0
  41. package/lib/ecosystems/parsers-gleam.js +1 -1
  42. package/lib/ecosystems/parsers-go.js +47 -9
  43. package/lib/ecosystems/parsers-js.js +171 -50
  44. package/lib/ecosystems/parsers-julia.js +268 -0
  45. package/lib/ecosystems/parsers-lua.js +218 -0
  46. package/lib/ecosystems/parsers-misc.js +919 -161
  47. package/lib/ecosystems/parsers-nim.js +221 -0
  48. package/lib/ecosystems/parsers-opam.js +180 -0
  49. package/lib/ecosystems/parsers-perl.js +277 -0
  50. package/lib/ecosystems/parsers-python.js +27 -15
  51. package/lib/ecosystems/parsers-r.js +148 -0
  52. package/lib/ecosystems/parsers-rebar.js +411 -0
  53. package/lib/ecosystems/parsers-rust.js +954 -33
  54. package/lib/ecosystems/parsers-spack.js +204 -0
  55. package/lib/ecosystems/parsers-stack.js +264 -0
  56. package/lib/ecosystems/parsers-terraform.js +194 -0
  57. package/lib/ecosystems/rubyutils.js +1426 -166
  58. package/lib/ecosystems/rusi.js +158 -7
  59. package/lib/evinser/evinser.js +547 -129
  60. package/lib/evinser/swiftsem.js +1914 -302
  61. package/lib/helpers/agenticToolutils.js +925 -0
  62. package/lib/helpers/bomSigner.js +652 -221
  63. package/lib/inventory/agentFormulationParser.js +57 -4
  64. package/lib/inventory/aiCollector.js +504 -10
  65. package/lib/inventory/aiInventory.js +12 -0
  66. package/lib/inventory/analyzer.js +488 -30
  67. package/lib/inventory/astWorker.js +6 -0
  68. package/lib/inventory/atomUtils.js +568 -31
  69. package/lib/inventory/auditCategories.js +8 -0
  70. package/lib/inventory/cbomutils.js +30 -0
  71. package/lib/inventory/cdxrs.js +110 -14
  72. package/lib/inventory/communityAiConfigParser.js +215 -2
  73. package/lib/inventory/depsUtils.js +183 -11
  74. package/lib/inventory/display.js +4 -5
  75. package/lib/inventory/dosai.js +627 -13
  76. package/lib/inventory/dynamic.js +39 -1
  77. package/lib/inventory/envcontext.js +9 -6
  78. package/lib/inventory/evidenceUtils.js +26 -5
  79. package/lib/inventory/fetchBatch.js +190 -19
  80. package/lib/inventory/fetchRate.js +74 -11
  81. package/lib/inventory/forgeEnricher.js +3 -2
  82. package/lib/inventory/jvmToolEnv.js +6 -5
  83. package/lib/inventory/mcpConfigParser.js +166 -2
  84. package/lib/inventory/mcpDiscovery.js +11 -0
  85. package/lib/inventory/mcpServerManifest.js +389 -0
  86. package/lib/inventory/mcpbBundle.js +419 -0
  87. package/lib/inventory/plugins.js +3 -0
  88. package/lib/inventory/protobom.js +62 -89
  89. package/lib/inventory/protobomLoader.js +4 -0
  90. package/lib/inventory/purl.js +152 -3
  91. package/lib/inventory/rustFormulationParser.js +1 -1
  92. package/lib/inventory/sbomDocument.js +2 -70
  93. package/lib/inventory/source.js +47 -23
  94. package/lib/inventory/stylePackageRefs.js +41 -0
  95. package/lib/inventory/svelteUtils.js +524 -0
  96. package/lib/inventory/traceRunner.js +210 -21
  97. package/lib/managers/binary.js +115 -24
  98. package/lib/managers/docker.js +440 -20
  99. package/lib/managers/oci.js +39 -1
  100. package/lib/parsers/cmakeLists.js +452 -0
  101. package/lib/parsers/huggingfaceUtils.js +15 -7
  102. package/lib/parsers/largeJson.js +454 -0
  103. package/lib/parsers/npmrc.js +19 -1
  104. package/lib/parsers/onnx.js +294 -0
  105. package/lib/parsers/safetensors.js +114 -0
  106. package/lib/stages/postgen/introspection/markers.js +29 -6
  107. package/lib/stages/postgen/postgen.js +237 -16
  108. package/lib/third-party/arborist/snapshots/calc-dep-flags.test.cjs +462 -0
  109. package/lib/validator/bomValidator.js +6 -16
  110. package/lib/validator/index.js +48 -10
  111. package/lib/validator/reporters/console.js +3 -0
  112. package/lib/validator/reporters/json.js +1 -0
  113. package/lib/validator/reporters/sarif.js +7 -0
  114. package/package.json +27 -27
  115. package/types/lib/audit/targets.d.ts.map +1 -1
  116. package/types/lib/cli/bomAssembly.d.ts +2 -1
  117. package/types/lib/cli/bomAssembly.d.ts.map +1 -1
  118. package/types/lib/cli/cliOptions.d.ts +33 -1
  119. package/types/lib/cli/cliOptions.d.ts.map +1 -1
  120. package/types/lib/cli/index.d.ts +2 -2
  121. package/types/lib/cli/index.d.ts.map +1 -1
  122. package/types/lib/cli/jsBom.d.ts +23 -0
  123. package/types/lib/cli/jsBom.d.ts.map +1 -1
  124. package/types/lib/cli/jvmBom.d.ts.map +1 -1
  125. package/types/lib/cli/managedBom.d.ts +33 -0
  126. package/types/lib/cli/managedBom.d.ts.map +1 -1
  127. package/types/lib/cli/nativeBom.d.ts +88 -8
  128. package/types/lib/cli/nativeBom.d.ts.map +1 -1
  129. package/types/lib/core/activity.d.ts.map +1 -1
  130. package/types/lib/core/env.d.ts +21 -0
  131. package/types/lib/core/env.d.ts.map +1 -1
  132. package/types/lib/core/fs.d.ts +55 -0
  133. package/types/lib/core/fs.d.ts.map +1 -1
  134. package/types/lib/core/metadataProperties.d.ts +39 -0
  135. package/types/lib/core/metadataProperties.d.ts.map +1 -0
  136. package/types/lib/core/projectConfig.d.ts +6 -2
  137. package/types/lib/core/projectConfig.d.ts.map +1 -1
  138. package/types/lib/core/userAgent.d.ts +56 -0
  139. package/types/lib/core/userAgent.d.ts.map +1 -0
  140. package/types/lib/ecosystems/bunutils.d.ts +12 -5
  141. package/types/lib/ecosystems/bunutils.d.ts.map +1 -1
  142. package/types/lib/ecosystems/cargoCache.d.ts +75 -0
  143. package/types/lib/ecosystems/cargoCache.d.ts.map +1 -0
  144. package/types/lib/ecosystems/caxa.d.ts +14 -0
  145. package/types/lib/ecosystems/caxa.d.ts.map +1 -1
  146. package/types/lib/ecosystems/cmakeResolver.d.ts +23 -0
  147. package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -1
  148. package/types/lib/ecosystems/cppEvidence.d.ts +2 -2
  149. package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
  150. package/types/lib/ecosystems/ecosystems.d.ts +15 -1
  151. package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
  152. package/types/lib/ecosystems/golem.d.ts.map +1 -1
  153. package/types/lib/ecosystems/gradleutils.d.ts +40 -4
  154. package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
  155. package/types/lib/ecosystems/jsEvidence.d.ts +5 -2
  156. package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
  157. package/types/lib/ecosystems/kosi.d.ts +86 -0
  158. package/types/lib/ecosystems/kosi.d.ts.map +1 -0
  159. package/types/lib/ecosystems/npmutils.d.ts +42 -0
  160. package/types/lib/ecosystems/npmutils.d.ts.map +1 -1
  161. package/types/lib/ecosystems/parsers-crystal.d.ts +27 -0
  162. package/types/lib/ecosystems/parsers-crystal.d.ts.map +1 -0
  163. package/types/lib/ecosystems/parsers-dotnet.d.ts +19 -0
  164. package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
  165. package/types/lib/ecosystems/parsers-elm.d.ts +79 -0
  166. package/types/lib/ecosystems/parsers-elm.d.ts.map +1 -0
  167. package/types/lib/ecosystems/parsers-go.d.ts +10 -0
  168. package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
  169. package/types/lib/ecosystems/parsers-js.d.ts +10 -4
  170. package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
  171. package/types/lib/ecosystems/parsers-julia.d.ts +57 -0
  172. package/types/lib/ecosystems/parsers-julia.d.ts.map +1 -0
  173. package/types/lib/ecosystems/parsers-lua.d.ts +50 -0
  174. package/types/lib/ecosystems/parsers-lua.d.ts.map +1 -0
  175. package/types/lib/ecosystems/parsers-misc.d.ts +90 -3
  176. package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
  177. package/types/lib/ecosystems/parsers-nim.d.ts +43 -0
  178. package/types/lib/ecosystems/parsers-nim.d.ts.map +1 -0
  179. package/types/lib/ecosystems/parsers-opam.d.ts +31 -0
  180. package/types/lib/ecosystems/parsers-opam.d.ts.map +1 -0
  181. package/types/lib/ecosystems/parsers-perl.d.ts +36 -0
  182. package/types/lib/ecosystems/parsers-perl.d.ts.map +1 -0
  183. package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
  184. package/types/lib/ecosystems/parsers-r.d.ts +35 -0
  185. package/types/lib/ecosystems/parsers-r.d.ts.map +1 -0
  186. package/types/lib/ecosystems/parsers-rebar.d.ts +42 -0
  187. package/types/lib/ecosystems/parsers-rebar.d.ts.map +1 -0
  188. package/types/lib/ecosystems/parsers-rust.d.ts +199 -0
  189. package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
  190. package/types/lib/ecosystems/parsers-spack.d.ts +33 -0
  191. package/types/lib/ecosystems/parsers-spack.d.ts.map +1 -0
  192. package/types/lib/ecosystems/parsers-stack.d.ts +35 -0
  193. package/types/lib/ecosystems/parsers-stack.d.ts.map +1 -0
  194. package/types/lib/ecosystems/parsers-terraform.d.ts +34 -0
  195. package/types/lib/ecosystems/parsers-terraform.d.ts.map +1 -0
  196. package/types/lib/ecosystems/pythonutils.d.ts +1 -1
  197. package/types/lib/ecosystems/rubyutils.d.ts +143 -2
  198. package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
  199. package/types/lib/ecosystems/rusi.d.ts +13 -0
  200. package/types/lib/ecosystems/rusi.d.ts.map +1 -1
  201. package/types/lib/evinser/evinser.d.ts +81 -2
  202. package/types/lib/evinser/evinser.d.ts.map +1 -1
  203. package/types/lib/evinser/swiftsem.d.ts +280 -15
  204. package/types/lib/evinser/swiftsem.d.ts.map +1 -1
  205. package/types/lib/helpers/agenticToolutils.d.ts +87 -0
  206. package/types/lib/helpers/agenticToolutils.d.ts.map +1 -0
  207. package/types/lib/helpers/bomSigner.d.ts +106 -13
  208. package/types/lib/helpers/bomSigner.d.ts.map +1 -1
  209. package/types/lib/inventory/agentFormulationParser.d.ts.map +1 -1
  210. package/types/lib/inventory/aiCollector.d.ts.map +1 -1
  211. package/types/lib/inventory/aiInventory.d.ts.map +1 -1
  212. package/types/lib/inventory/analyzer.d.ts.map +1 -1
  213. package/types/lib/inventory/atomUtils.d.ts +145 -3
  214. package/types/lib/inventory/atomUtils.d.ts.map +1 -1
  215. package/types/lib/inventory/auditCategories.d.ts +4 -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/cdxrs.d.ts +8 -3
  219. package/types/lib/inventory/cdxrs.d.ts.map +1 -1
  220. package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
  221. package/types/lib/inventory/depsUtils.d.ts +15 -0
  222. package/types/lib/inventory/depsUtils.d.ts.map +1 -1
  223. package/types/lib/inventory/display.d.ts.map +1 -1
  224. package/types/lib/inventory/dosai.d.ts +87 -1
  225. package/types/lib/inventory/dosai.d.ts.map +1 -1
  226. package/types/lib/inventory/dynamic.d.ts.map +1 -1
  227. package/types/lib/inventory/envcontext.d.ts.map +1 -1
  228. package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
  229. package/types/lib/inventory/fetchBatch.d.ts +34 -0
  230. package/types/lib/inventory/fetchBatch.d.ts.map +1 -1
  231. package/types/lib/inventory/fetchRate.d.ts +9 -6
  232. package/types/lib/inventory/fetchRate.d.ts.map +1 -1
  233. package/types/lib/inventory/forgeEnricher.d.ts.map +1 -1
  234. package/types/lib/inventory/jvmToolEnv.d.ts +5 -4
  235. package/types/lib/inventory/jvmToolEnv.d.ts.map +1 -1
  236. package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
  237. package/types/lib/inventory/mcpDiscovery.d.ts.map +1 -1
  238. package/types/lib/inventory/mcpServerManifest.d.ts +19 -0
  239. package/types/lib/inventory/mcpServerManifest.d.ts.map +1 -0
  240. package/types/lib/inventory/mcpbBundle.d.ts +19 -0
  241. package/types/lib/inventory/mcpbBundle.d.ts.map +1 -0
  242. package/types/lib/inventory/plugins.d.ts.map +1 -1
  243. package/types/lib/inventory/protobom.d.ts +18 -13
  244. package/types/lib/inventory/protobom.d.ts.map +1 -1
  245. package/types/lib/inventory/protobomLoader.d.ts.map +1 -1
  246. package/types/lib/inventory/purl.d.ts +71 -2
  247. package/types/lib/inventory/purl.d.ts.map +1 -1
  248. package/types/lib/inventory/sbomDocument.d.ts.map +1 -1
  249. package/types/lib/inventory/source.d.ts.map +1 -1
  250. package/types/lib/inventory/stylePackageRefs.d.ts +17 -0
  251. package/types/lib/inventory/stylePackageRefs.d.ts.map +1 -0
  252. package/types/lib/inventory/svelteUtils.d.ts +124 -0
  253. package/types/lib/inventory/svelteUtils.d.ts.map +1 -0
  254. package/types/lib/inventory/traceRunner.d.ts +47 -1
  255. package/types/lib/inventory/traceRunner.d.ts.map +1 -1
  256. package/types/lib/managers/binary.d.ts +30 -1
  257. package/types/lib/managers/binary.d.ts.map +1 -1
  258. package/types/lib/managers/docker.d.ts +29 -0
  259. package/types/lib/managers/docker.d.ts.map +1 -1
  260. package/types/lib/managers/oci.d.ts +14 -0
  261. package/types/lib/managers/oci.d.ts.map +1 -1
  262. package/types/lib/parsers/cmakeLists.d.ts +76 -0
  263. package/types/lib/parsers/cmakeLists.d.ts.map +1 -0
  264. package/types/lib/parsers/huggingfaceUtils.d.ts +8 -1
  265. package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -1
  266. package/types/lib/parsers/largeJson.d.ts +52 -0
  267. package/types/lib/parsers/largeJson.d.ts.map +1 -0
  268. package/types/lib/parsers/npmrc.d.ts +5 -0
  269. package/types/lib/parsers/npmrc.d.ts.map +1 -1
  270. package/types/lib/parsers/onnx.d.ts +28 -0
  271. package/types/lib/parsers/onnx.d.ts.map +1 -0
  272. package/types/lib/parsers/safetensors.d.ts +22 -0
  273. package/types/lib/parsers/safetensors.d.ts.map +1 -0
  274. package/types/lib/stages/postgen/introspection/markers.d.ts +3 -2
  275. package/types/lib/stages/postgen/introspection/markers.d.ts.map +1 -1
  276. package/types/lib/stages/postgen/postgen.d.ts +33 -0
  277. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  278. package/types/lib/validator/bomValidator.d.ts.map +1 -1
  279. package/types/lib/validator/index.d.ts +10 -1
  280. package/types/lib/validator/index.d.ts.map +1 -1
  281. package/types/lib/validator/reporters/console.d.ts.map +1 -1
  282. package/types/lib/validator/reporters/json.d.ts.map +1 -1
  283. package/types/lib/validator/reporters/sarif.d.ts.map +1 -1
package/lib/cli/jsBom.js CHANGED
@@ -24,7 +24,10 @@ import {
24
24
  rewriteExtractedArchivePaths,
25
25
  } from "../ecosystems/asarutils.js";
26
26
  import { parseBunLock } from "../ecosystems/bunutils.js";
27
- import { parseCaxaMetadata } from "../ecosystems/caxa.js";
27
+ import {
28
+ enrichCaxaMetadataFromApp,
29
+ parseCaxaMetadata,
30
+ } from "../ecosystems/caxa.js";
28
31
  import {
29
32
  CHROME_EXTENSION_PURL_TYPE,
30
33
  collectChromeExtensionsFromPath,
@@ -53,6 +56,10 @@ import {
53
56
  fetchHuggingFaceAssetInventory,
54
57
  normalizeHuggingFaceReference,
55
58
  } from "../ecosystems/remote/huggingface.js";
59
+ import {
60
+ AGENTIC_TOOL_PURL_TYPE,
61
+ collectAgenticTools,
62
+ } from "../helpers/agenticToolutils.js";
56
63
  import {
57
64
  cleanupTempDir,
58
65
  collectInstalledExtensions,
@@ -73,6 +80,7 @@ import {
73
80
  } from "../inventory/analyzer.js";
74
81
  import {
75
82
  markNpmTypesPackagesAsExcluded,
83
+ markTypeOnlyDependenciesOptional,
76
84
  mergeDependencies,
77
85
  mergeServices,
78
86
  propagateRequiredScopeFromDependencies,
@@ -100,6 +108,13 @@ const isWin = _platform() === "win32";
100
108
  * local Modelfile/`.gguf` file input. Returns the explicit selection from
101
109
  * `getExactAiInventoryType` when one is present.
102
110
  *
111
+ * Direct HuggingFace interpretation of the source path is opt-in: only
112
+ * unambiguous references (`pkg:huggingface/...` purls and huggingface.co
113
+ * URLs) are recognized on their own. Bare `owner/repo`-shaped values are
114
+ * ordinary relative paths (eg: `repotests/sveltejs-realworld`) unless an AI
115
+ * inventory type such as `-t ai` is explicitly selected, in which case
116
+ * `getExactAiInventoryType` already returned it above.
117
+ *
103
118
  * @param {string} path Project or file path
104
119
  * @param {object} options CLI options
105
120
  * @returns {string|undefined} The detected AI inventory type (`"ai"`) or undefined
@@ -109,7 +124,7 @@ export function getDirectAiInventoryType(path, options) {
109
124
  if (exactAiInventoryType) {
110
125
  return exactAiInventoryType;
111
126
  }
112
- if (normalizeHuggingFaceReference(path)) {
127
+ if (normalizeHuggingFaceReference(path, { explicitOnly: true })) {
113
128
  return "ai";
114
129
  }
115
130
  try {
@@ -157,8 +172,10 @@ export async function createNodejsBom(path, options) {
157
172
  excludedAiInventoryTypes,
158
173
  );
159
174
  let aiInventory = { components: [], dependencies: [], services: [] };
175
+ // A value that exists on the local filesystem is always a project path -
176
+ // never a remote model id - so existing inputs skip remote resolution.
160
177
  const directHuggingFaceSource =
161
- exactAiInventoryType === "ai"
178
+ exactAiInventoryType === "ai" && !safeExistsSync(path)
162
179
  ? normalizeHuggingFaceReference(path)
163
180
  : undefined;
164
181
  if (directHuggingFaceSource?.repoId) {
@@ -554,7 +571,16 @@ export async function createNodejsBom(path, options) {
554
571
  recordSensitiveFileRead(npmrcFile, {
555
572
  label: "npm registry configuration",
556
573
  });
557
- const npmrcObj = parseNpmrc(npmrcData);
574
+ let npmrcObj = {};
575
+ try {
576
+ npmrcObj = parseNpmrc(npmrcData);
577
+ } catch (e) {
578
+ // A malformed .npmrc must degrade to a warning, never abort the scan.
579
+ console.warn(
580
+ `Unable to parse ${npmrcFile}. Continuing without it. ${e?.message || ""}`,
581
+ );
582
+ npmrcObj = {};
583
+ }
558
584
  for (const [key, value] of Object.entries(npmrcObj)) {
559
585
  const baseKey = key.replace(/^(?:\/\/[^/]+\/|@[^:]+:)/, "");
560
586
  if (
@@ -944,8 +970,12 @@ export async function createNodejsBom(path, options) {
944
970
  ) {
945
971
  // Rush.js creates node_modules inside common/temp directory
946
972
  const nmDir = join(path, "common", "temp", "node_modules");
947
- // Do rush install if we don't have node_modules directory
948
- if (!safeExistsSync(nmDir)) {
973
+ // Do rush install if we don't have node_modules directory. `rush install`
974
+ // drives pnpm without cdxgen's --ignore-scripts hardening and
975
+ // --bypass-policy disables rush's own policy gate, so it must respect
976
+ // --no-install-deps and the pre-build lifecycle like every other
977
+ // installer.
978
+ if (!safeExistsSync(nmDir) && options.installDeps !== false) {
949
979
  console.log("Executing 'rush install --no-link'", path);
950
980
  const result = safeSpawnSync(
951
981
  "rush",
@@ -1023,6 +1053,7 @@ export async function createNodejsBom(path, options) {
1023
1053
  }
1024
1054
  pkgList = propagateRequiredScopeFromDependencies(pkgList, dependencies);
1025
1055
  pkgList = markNpmTypesPackagesAsExcluded(pkgList);
1056
+ pkgList = markTypeOnlyDependenciesOptional(pkgList, dependencies);
1026
1057
  return buildBomNSData(options, pkgList, "npm", {
1027
1058
  allImports,
1028
1059
  allExports,
@@ -1107,25 +1138,25 @@ export async function createNodejsBom(path, options) {
1107
1138
  );
1108
1139
  workspacePackages.push(workspaceRef);
1109
1140
  workspaceSrcFiles[workspaceRef] = relativePkgJsonFile;
1110
- if (pkgData?.dependencies || pkgData?.devDependencies) {
1111
- const dlist = new Set();
1112
- for (const [k, v] of Object.entries({
1113
- ...(pkgData.dependencies || {}),
1114
- ...(pkgData.devDependencies || {}),
1115
- })) {
1116
- if (v.match(/^\d/)) {
1117
- dlist.add(`pkg:npm/${k}@${v}`);
1118
- } else {
1119
- dlist.add(`pkg:npm/${k}`);
1120
- }
1121
- }
1122
- workspaceDirectDeps[workspaceRef] = Array.from(dlist);
1123
- for (const dep of workspaceDirectDeps[workspaceRef]) {
1124
- if (!depsWorkspaceRefs[dep]) {
1125
- depsWorkspaceRefs[dep] = [];
1126
- }
1127
- depsWorkspaceRefs[dep].push(workspaceRef);
1141
+ // The declared name and range of each direct dependency, which
1142
+ // parseYarnLock resolves against the lock file to link the
1143
+ // member into the dependency tree.
1144
+ const declaredDeps = {
1145
+ ...(pkgData.dependencies || {}),
1146
+ ...(pkgData.optionalDependencies || {}),
1147
+ ...(pkgData.devDependencies || {}),
1148
+ };
1149
+ if (Object.keys(declaredDeps).length) {
1150
+ workspaceDirectDeps[workspaceRef] = declaredDeps;
1151
+ }
1152
+ for (const [k, v] of Object.entries(declaredDeps)) {
1153
+ const dep = /^\d/.test(String(v))
1154
+ ? `pkg:npm/${k}@${v}`
1155
+ : `pkg:npm/${k}`;
1156
+ if (!depsWorkspaceRefs[dep]) {
1157
+ depsWorkspaceRefs[dep] = [];
1128
1158
  }
1159
+ depsWorkspaceRefs[dep].push(workspaceRef);
1129
1160
  }
1130
1161
  }
1131
1162
  }
@@ -1482,6 +1513,7 @@ export async function createNodejsBom(path, options) {
1482
1513
  );
1483
1514
  pkgList = propagateRequiredScopeFromDependencies(pkgList, dependencies);
1484
1515
  pkgList = markNpmTypesPackagesAsExcluded(pkgList);
1516
+ pkgList = markTypeOnlyDependenciesOptional(pkgList, dependencies);
1485
1517
  if (exactAiInventoryType === "mcp") {
1486
1518
  pkgList = trimComponents(filterInventorySubjectsByTypes(pkgList, ["mcp"]));
1487
1519
  dependencies = filterInventoryDependencies(
@@ -1611,8 +1643,14 @@ export async function createCaxaBom(path, options) {
1611
1643
  if (DEBUG_MODE) {
1612
1644
  console.log(`Parsing ${mfile}`);
1613
1645
  }
1614
- const { parentComponent, components, dependencies } =
1615
- await parseCaxaMetadata(mfile);
1646
+ let mdata = await parseCaxaMetadata(mfile);
1647
+ if (options.caxaAppDir) {
1648
+ mdata = await enrichCaxaMetadataFromApp(
1649
+ mdata,
1650
+ resolve(options.caxaAppDir),
1651
+ );
1652
+ }
1653
+ const { parentComponent, components, dependencies } = mdata;
1616
1654
  if (parentComponent) {
1617
1655
  if (!finalParentComponent) {
1618
1656
  finalParentComponent = parentComponent;
@@ -1748,6 +1786,50 @@ export async function createVscodeExtensionBom(path, options) {
1748
1786
  });
1749
1787
  }
1750
1788
 
1789
+ /**
1790
+ * Create a BOM that catalogs agentic CLI tools installed for the current user
1791
+ * (for example Kiro CLI, zcode, opencode, and Claude Code), along with the
1792
+ * agents, plugins, and providers they define.
1793
+ *
1794
+ * The scan is read-only and value-redacting: it records tool versions where a
1795
+ * declarative source exists, plus structural counts, but never reads
1796
+ * credentials, transcripts, session logs, or telemetry.
1797
+ *
1798
+ * @param {string} path Positional input. A host scan does not read a project
1799
+ * tree, so an explicit path other than the current directory is rejected
1800
+ * rather than silently ignored.
1801
+ * @param {Object} options Parse options from the CLI
1802
+ * @returns {Promise<Object>} Promise resolving to BOM data
1803
+ */
1804
+ export async function createAgenticBom(path, options) {
1805
+ // Guard against a surprising host-wide scan masquerading as a project scan.
1806
+ // cdxgen always supplies a positional path (defaulting to "."), so only an
1807
+ // explicit path that resolves somewhere other than the current directory is
1808
+ // treated as a mistake.
1809
+ const resolvedPath = path ? resolve(path) : process.cwd();
1810
+ if (resolvedPath !== process.cwd()) {
1811
+ throw new Error(
1812
+ "The 'agentic' project type performs a host-wide scan of installed " +
1813
+ "agentic CLI tool directories and does not accept a path argument. " +
1814
+ `Re-run without the path (received '${path}').`,
1815
+ );
1816
+ }
1817
+ // Must not go to stdout: every entry point keeps stdout reserved for the BOM
1818
+ // payload so `cdxgen -t agentic -o -` stays pipeable.
1819
+ thoughtLog(
1820
+ "Scanning the current user's home directory for installed agentic CLI tools.",
1821
+ );
1822
+ const inventory = collectAgenticTools(options);
1823
+ const pkgList = trimComponents(inventory.components || []);
1824
+ return buildBomNSData(options, pkgList, AGENTIC_TOOL_PURL_TYPE, {
1825
+ src: "~",
1826
+ filename: "agentic-cli-tools",
1827
+ nsMapping: {},
1828
+ dependencies: inventory.dependencies || [],
1829
+ services: inventory.services || [],
1830
+ });
1831
+ }
1832
+
1751
1833
  /**
1752
1834
  * Function to create BOM for Electron ASAR archives.
1753
1835
  *
package/lib/cli/jvmBom.js CHANGED
@@ -49,6 +49,7 @@ import {
49
49
  parseGradleInfoLogsForUrls,
50
50
  parseGradleProperties,
51
51
  parseGradleResolvedDistributions,
52
+ parseGradleVersionCatalog,
52
53
  recordGradleInvocationFailure,
53
54
  splitOutputByGradleProjects,
54
55
  } from "../ecosystems/gradleutils.js";
@@ -166,14 +167,14 @@ export async function createJarBom(path, options) {
166
167
  const parentComponent = createDefaultParentComponent(path, "maven", options);
167
168
  if (options.useGradleCache) {
168
169
  nsMapping = await collectGradleDependencies(
169
- getGradleCommand(path, null),
170
+ getGradleCommand(path, null, options),
170
171
  path,
171
172
  false,
172
173
  true,
173
174
  );
174
175
  } else if (options.useMavenCache) {
175
176
  nsMapping = await collectMvnDependencies(
176
- getMavenCommand(path, null),
177
+ getMavenCommand(path, null, options),
177
178
  null,
178
179
  false,
179
180
  true,
@@ -244,6 +245,8 @@ export function discoverSbtProjectsFromCmd(basePath, sbtCmd, env) {
244
245
  {
245
246
  cwd: basePath,
246
247
  shell: true,
248
+ // The quotes around the sbt command are for the shell to strip.
249
+ cdxgenRawShellArgs: true,
247
250
  env,
248
251
  encoding: "utf-8",
249
252
  },
@@ -452,7 +455,7 @@ export async function createJavaBom(path, options) {
452
455
  }
453
456
  }
454
457
  const firstPom = pomFiles.length ? pomFiles[0] : undefined;
455
- let mavenCmd = getMavenCommand(path, path);
458
+ let mavenCmd = getMavenCommand(path, path, options);
456
459
  for (const f of pomFiles) {
457
460
  const basePath = dirname(f);
458
461
  if (
@@ -472,7 +475,7 @@ export async function createJavaBom(path, options) {
472
475
  );
473
476
  }
474
477
  if (mavenCmd?.endsWith("mvn")) {
475
- mavenCmd = getMavenCommand(basePath, path);
478
+ mavenCmd = getMavenCommand(basePath, path, options);
476
479
  }
477
480
  // Should we attempt to resolve class names
478
481
  if (options.resolveClass || options.deep) {
@@ -1040,11 +1043,23 @@ export async function createJavaBom(path, options) {
1040
1043
  if (resolveGradleDistribution && gradleInitArgs.length) {
1041
1044
  gradleInitArgs.push("-PcdxgenResolveDistribution=true");
1042
1045
  }
1043
- parallelPropTaskOut = executeParallelGradleProperties(
1044
- gradleRootPath,
1045
- [null].concat(includedBuilds),
1046
- gradleInitArgs,
1047
- );
1046
+ // `gradle properties` evaluates the project's build scripts, so it is
1047
+ // part of the dependency-tooling surface gated by --no-install-deps
1048
+ // (and the pre-build lifecycle).
1049
+ const gradleToolingAllowed =
1050
+ options.installDeps !== false || options.introspect === true;
1051
+ if (gradleToolingAllowed) {
1052
+ parallelPropTaskOut = executeParallelGradleProperties(
1053
+ gradleRootPath,
1054
+ [null].concat(includedBuilds),
1055
+ gradleInitArgs,
1056
+ options,
1057
+ );
1058
+ } else {
1059
+ console.log(
1060
+ "Skipping 'gradle properties' since dependency installation is disabled. Only statically parsed Gradle metadata will be used.",
1061
+ );
1062
+ }
1048
1063
  if (readEnvironmentVariable("GRADLE_INCLUDED_BUILDS") === undefined) {
1049
1064
  const outputLines = parallelPropTaskOut.split("\n");
1050
1065
  for (const [_i, line] of outputLines.entries()) {
@@ -1072,7 +1087,14 @@ export async function createJavaBom(path, options) {
1072
1087
  }
1073
1088
  parallelPropTaskOut = parallelPropTaskOut.concat(
1074
1089
  "\n",
1075
- executeParallelGradleProperties(gradleRootPath, includedBuilds),
1090
+ gradleToolingAllowed
1091
+ ? executeParallelGradleProperties(
1092
+ gradleRootPath,
1093
+ includedBuilds,
1094
+ [],
1095
+ options,
1096
+ )
1097
+ : "",
1076
1098
  );
1077
1099
  }
1078
1100
  }
@@ -1113,6 +1135,8 @@ export async function createJavaBom(path, options) {
1113
1135
  parallelPropTaskOut = executeParallelGradleProperties(
1114
1136
  gradleRootPath,
1115
1137
  allProjectsStr.filter((module) => !modulesToSkip.includes(module)),
1138
+ [],
1139
+ options,
1116
1140
  );
1117
1141
  const splitPropTaskOut = splitOutputByGradleProjects(
1118
1142
  parallelPropTaskOut,
@@ -1160,7 +1184,7 @@ export async function createJavaBom(path, options) {
1160
1184
  )
1161
1185
  ) {
1162
1186
  allProjects.push(parentComponent);
1163
- const gradleCmd = getGradleCommand(gradleRootPath, null);
1187
+ const gradleCmd = getGradleCommand(gradleRootPath, null, options);
1164
1188
  const gradleDepTask = readEnvironmentVariable("GRADLE_DEPENDENCY_TASK")
1165
1189
  ? readEnvironmentVariable("GRADLE_DEPENDENCY_TASK")
1166
1190
  : "dependencies";
@@ -1372,6 +1396,27 @@ export async function createJavaBom(path, options) {
1372
1396
  jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping };
1373
1397
  }
1374
1398
  }
1399
+
1400
+ // A version catalog declares coordinates without resolving them, so it
1401
+ // is used only when Gradle produced no dependency information at all.
1402
+ // The emitted components carry cdx:gradle:catalog=true to mark them as
1403
+ // declared rather than resolved.
1404
+ if (!pkgList.length) {
1405
+ const catalogFiles = getAllFiles(
1406
+ path,
1407
+ `${options.multiProject ? "**/" : ""}gradle/libs.versions.toml`,
1408
+ options,
1409
+ );
1410
+ for (const catalogFile of catalogFiles) {
1411
+ if (DEBUG_MODE) {
1412
+ console.log(`Parsing ${catalogFile}`);
1413
+ }
1414
+ const dlist = parseGradleVersionCatalog(catalogFile);
1415
+ if (dlist?.length) {
1416
+ pkgList = pkgList.concat(dlist);
1417
+ }
1418
+ }
1419
+ }
1375
1420
  }
1376
1421
 
1377
1422
  // Bazel
@@ -1617,6 +1662,13 @@ export async function createJavaBom(path, options) {
1617
1662
  pkgList = pkgList.concat(dlist);
1618
1663
  }
1619
1664
  }
1665
+ } else if (options.installDeps === false && !options.introspect) {
1666
+ // Executing sbt evaluates the project's build definition (arbitrary
1667
+ // Scala), so it belongs to the dependency-tooling surface disabled
1668
+ // by --no-install-deps and the pre-build lifecycle.
1669
+ console.log(
1670
+ "Skipping sbt dependencyTree since dependency installation is disabled. Only statically parsed sbt metadata will be used.",
1671
+ );
1620
1672
  } else {
1621
1673
  const SBT_CMD = readEnvironmentVariable("SBT_CMD") || "sbt";
1622
1674
  let sbtVersion = determineSbtVersion(path);
@@ -1732,6 +1784,9 @@ export async function createJavaBom(path, options) {
1732
1784
  const result = safeSpawnSync(SBT_CMD, sbtArgs, {
1733
1785
  cwd: basePath,
1734
1786
  shell: true,
1787
+ // The sbt commands below embed their own shell quoting, which the
1788
+ // shell must strip for sbt to see separate commands.
1789
+ cdxgenRawShellArgs: true,
1735
1790
  env,
1736
1791
  });
1737
1792
  if (result.status !== 0 || result.error) {
@@ -1871,6 +1926,7 @@ export async function createJavaBom(path, options) {
1871
1926
 
1872
1927
  if (
1873
1928
  millFiles?.length &&
1929
+ (options.installDeps !== false || options.introspect === true) &&
1874
1930
  isPackageManagerAllowed(
1875
1931
  "mill",
1876
1932
  ["bazel", "sbt", "gradle", "maven"],
@@ -1883,7 +1939,7 @@ export async function createJavaBom(path, options) {
1883
1939
  "maven",
1884
1940
  options,
1885
1941
  );
1886
- const millCmd = getMillCommand(millRootPath);
1942
+ const millCmd = getMillCommand(millRootPath, options);
1887
1943
  const millCommonArgs = [
1888
1944
  "--color",
1889
1945
  "false",