@cdxgen/cdxgen 13.4.0 → 13.6.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 (305) hide show
  1. package/README.md +9 -9
  2. package/bin/cdxgen-secure.js +15 -0
  3. package/bin/cdxgen.js +29 -5
  4. package/bin/evinse.js +8 -0
  5. package/bin/hbom.js +15 -7
  6. package/bin/repl.js +29 -0
  7. package/bin/validate.js +6 -0
  8. package/data/cbomosdb-queries.json +13 -1
  9. package/data/component-tags.json +8 -0
  10. package/data/license-aliases.json +24 -2
  11. package/data/queries-darwin.json +25 -1
  12. package/data/queries-win.json +19 -1
  13. package/data/queries.json +41 -0
  14. package/data/remediations.json +407 -1
  15. package/data/rules/ai-bom.yaml +1 -1
  16. package/data/rules/brotli-decoder.yaml +107 -0
  17. package/data/rules/cbom-security.yaml +235 -4
  18. package/data/rules/go-binaries.yaml +46 -0
  19. package/data/rules/golem-go.yaml +80 -0
  20. package/data/rules/hbom-compliance.yaml +40 -22
  21. package/data/rules/hbom-performance.yaml +7 -1
  22. package/data/rules/host-topology.yaml +1 -1
  23. package/data/rules/obom-runtime.yaml +31 -2
  24. package/data/rules/php-runtime.yaml +143 -0
  25. package/data/rules/vscode-extensions.yaml +75 -0
  26. package/data/spdx-license-list.json +121 -7
  27. package/data/spdx-licenses.json +69 -0
  28. package/data/spdx.schema.json +845 -2
  29. package/lib/audit/index.js +14 -0
  30. package/lib/cli/bomAssembly.js +120 -6
  31. package/lib/cli/cliOptions.js +110 -3
  32. package/lib/cli/index.js +182 -6
  33. package/lib/cli/jsBom.js +153 -64
  34. package/lib/cli/jvmBom.js +363 -66
  35. package/lib/cli/managedBom.js +853 -87
  36. package/lib/cli/nativeBom.js +267 -33
  37. package/lib/core/boundedFile.js +344 -0
  38. package/lib/core/brotliProbe.js +182 -0
  39. package/lib/core/env.js +38 -8
  40. package/lib/core/fs.js +40 -19
  41. package/lib/core/httpClient.js +172 -46
  42. package/lib/core/lockPaths.js +38 -0
  43. package/lib/core/paths.js +24 -1
  44. package/lib/core/processTree.js +5 -0
  45. package/lib/core/projectConfig.js +1 -0
  46. package/lib/core/projectTooling.js +97 -0
  47. package/lib/core/propertySanitizer.js +72 -0
  48. package/lib/core/toolRegistry.js +170 -0
  49. package/lib/ecosystems/cppEvidence.js +263 -106
  50. package/lib/ecosystems/cppIncludeResolver.js +16 -5
  51. package/lib/ecosystems/ecosystems.js +25 -10
  52. package/lib/ecosystems/gemHostProbe.js +301 -0
  53. package/lib/ecosystems/golem.js +550 -6
  54. package/lib/ecosystems/gradleutils.js +858 -244
  55. package/lib/ecosystems/parsers-bazel.js +107 -6
  56. package/lib/ecosystems/parsers-dotnet.js +117 -18
  57. package/lib/ecosystems/parsers-go.js +1090 -367
  58. package/lib/ecosystems/parsers-js.js +505 -22
  59. package/lib/ecosystems/parsers-jvm.js +259 -17
  60. package/lib/ecosystems/parsers-misc.js +438 -64
  61. package/lib/ecosystems/parsers-python.js +100 -12
  62. package/lib/ecosystems/pythonutils.js +128 -2
  63. package/lib/ecosystems/rubyutils.js +544 -34
  64. package/lib/ecosystems/rusi.js +10 -0
  65. package/lib/ecosystems/scalacliutils.js +4 -1
  66. package/lib/ecosystems/scalasem.js +798 -151
  67. package/lib/ecosystems/vendoredCode.js +237 -3
  68. package/lib/ecosystems/venvProbe.js +360 -0
  69. package/lib/evinser/evinser.js +472 -61
  70. package/lib/evinser/swiftsem.js +68 -5
  71. package/lib/helpers/agenticToolutils.js +413 -93
  72. package/lib/helpers/vsixutils.js +1574 -315
  73. package/lib/inventory/agentSkillSpec.js +17 -0
  74. package/lib/inventory/apkInstalledDb.js +243 -0
  75. package/lib/inventory/atomUtils.js +110 -0
  76. package/lib/inventory/auditCategories.js +3 -3
  77. package/lib/inventory/brotliDecoder.js +142 -0
  78. package/lib/inventory/buildToolRateLimit.js +1 -1
  79. package/lib/inventory/cacheDir.js +52 -9
  80. package/lib/inventory/cbomutils.js +56 -7
  81. package/lib/inventory/certificates.js +2371 -0
  82. package/lib/inventory/communityAiConfigParser.js +4 -9
  83. package/lib/inventory/deps.js +41 -4
  84. package/lib/inventory/display.js +200 -3
  85. package/lib/inventory/dosai.js +639 -63
  86. package/lib/inventory/dotnetRuntime.js +217 -0
  87. package/lib/inventory/dynamic.js +45 -3
  88. package/lib/inventory/envcontext.js +475 -18
  89. package/lib/inventory/evidenceUtils.js +447 -23
  90. package/lib/inventory/fetchBatch.js +1 -1
  91. package/lib/inventory/formulationParsers.js +32 -3
  92. package/lib/inventory/goBuildInfo.js +140 -0
  93. package/lib/inventory/gtfobins.js +13 -0
  94. package/lib/inventory/hbom.js +67 -7
  95. package/lib/inventory/hbomAnalysis.js +16 -0
  96. package/lib/inventory/hostRuntimeProbe.js +686 -0
  97. package/lib/inventory/hostTopology.js +21 -0
  98. package/lib/inventory/jvmLocalRepos.js +9 -2
  99. package/lib/inventory/jvmToolEnv.js +29 -0
  100. package/lib/inventory/licenseEnhancer.js +12 -0
  101. package/lib/inventory/mavenCentralMirror.js +534 -0
  102. package/lib/inventory/nodeBuildInfo.js +218 -0
  103. package/lib/inventory/nodeHostProbe.js +202 -0
  104. package/lib/inventory/osPackagePurl.js +244 -0
  105. package/lib/inventory/osPackageResolver.js +271 -87
  106. package/lib/inventory/osinfo.js +79 -31
  107. package/lib/inventory/osqueryTransform.js +114 -5
  108. package/lib/inventory/phpBuildInfo.js +438 -0
  109. package/lib/inventory/phpHostProbe.js +185 -0
  110. package/lib/inventory/rootfsCerts.js +426 -0
  111. package/lib/inventory/rubyBuildInfo.js +972 -0
  112. package/lib/inventory/rubyHostProbe.js +218 -0
  113. package/lib/inventory/scalaCoords.js +4 -3
  114. package/lib/inventory/scalaDedupe.js +440 -0
  115. package/lib/inventory/source.js +256 -5
  116. package/lib/inventory/spdx.js +144 -0
  117. package/lib/inventory/traceRunner.js +5 -1
  118. package/lib/inventory/tracedCrypto.js +129 -0
  119. package/lib/managers/binary.js +866 -186
  120. package/lib/managers/docker.js +245 -12
  121. package/lib/parsers/email.js +277 -0
  122. package/lib/parsers/largeJson.js +62 -13
  123. package/lib/parsers/vscodeExtensionId.js +183 -0
  124. package/lib/server/server.js +198 -2
  125. package/lib/stages/postgen/annotator.js +17 -1
  126. package/lib/stages/postgen/introspection/reflect.js +4 -1
  127. package/lib/stages/postgen/postgen.js +5 -5
  128. package/lib/stages/postgen/ruleEngine.js +71 -6
  129. package/lib/stages/postgen/specVersionCompat.js +30 -0
  130. package/lib/stages/pregen/envAudit.js +1 -0
  131. package/lib/stages/pregen/pregen.js +231 -62
  132. package/lib/validator/bomValidator.js +32 -6
  133. package/lib/validator/generated/runtime.mjs +13 -0
  134. package/lib/validator/generated/validate-1.6.mjs +27 -8
  135. package/lib/validator/generated/validate-1.7.mjs +32 -13
  136. package/lib/validator/generated/validate-2.0.mjs +31 -12
  137. package/lib/validator/index.js +1 -1
  138. package/package.json +19 -18
  139. package/types/bin/cdxgen-secure.d.ts +3 -0
  140. package/types/bin/cdxgen-secure.d.ts.map +1 -0
  141. package/types/bin/repl.d.ts.map +1 -1
  142. package/types/lib/audit/index.d.ts.map +1 -1
  143. package/types/lib/cli/bomAssembly.d.ts +22 -3
  144. package/types/lib/cli/bomAssembly.d.ts.map +1 -1
  145. package/types/lib/cli/cliOptions.d.ts +43 -0
  146. package/types/lib/cli/cliOptions.d.ts.map +1 -1
  147. package/types/lib/cli/index.d.ts.map +1 -1
  148. package/types/lib/cli/jsBom.d.ts +1 -17
  149. package/types/lib/cli/jsBom.d.ts.map +1 -1
  150. package/types/lib/cli/jvmBom.d.ts +20 -0
  151. package/types/lib/cli/jvmBom.d.ts.map +1 -1
  152. package/types/lib/cli/managedBom.d.ts.map +1 -1
  153. package/types/lib/cli/nativeBom.d.ts.map +1 -1
  154. package/types/lib/core/boundedFile.d.ts +70 -0
  155. package/types/lib/core/boundedFile.d.ts.map +1 -0
  156. package/types/lib/core/brotliProbe.d.ts +37 -0
  157. package/types/lib/core/brotliProbe.d.ts.map +1 -0
  158. package/types/lib/core/env.d.ts +22 -2
  159. package/types/lib/core/env.d.ts.map +1 -1
  160. package/types/lib/core/fs.d.ts.map +1 -1
  161. package/types/lib/core/httpClient.d.ts +24 -0
  162. package/types/lib/core/httpClient.d.ts.map +1 -1
  163. package/types/lib/core/lockPaths.d.ts +19 -0
  164. package/types/lib/core/lockPaths.d.ts.map +1 -0
  165. package/types/lib/core/processTree.d.ts +2 -0
  166. package/types/lib/core/processTree.d.ts.map +1 -1
  167. package/types/lib/core/projectConfig.d.ts.map +1 -1
  168. package/types/lib/core/projectTooling.d.ts +41 -0
  169. package/types/lib/core/projectTooling.d.ts.map +1 -0
  170. package/types/lib/core/propertySanitizer.d.ts +26 -0
  171. package/types/lib/core/propertySanitizer.d.ts.map +1 -1
  172. package/types/lib/core/toolRegistry.d.ts +36 -0
  173. package/types/lib/core/toolRegistry.d.ts.map +1 -0
  174. package/types/lib/ecosystems/cppEvidence.d.ts +40 -13
  175. package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
  176. package/types/lib/ecosystems/cppIncludeResolver.d.ts +2 -1
  177. package/types/lib/ecosystems/cppIncludeResolver.d.ts.map +1 -1
  178. package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
  179. package/types/lib/ecosystems/gemHostProbe.d.ts +28 -0
  180. package/types/lib/ecosystems/gemHostProbe.d.ts.map +1 -0
  181. package/types/lib/ecosystems/golem.d.ts +81 -1
  182. package/types/lib/ecosystems/golem.d.ts.map +1 -1
  183. package/types/lib/ecosystems/gradleutils.d.ts +57 -21
  184. package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
  185. package/types/lib/ecosystems/parsers-bazel.d.ts.map +1 -1
  186. package/types/lib/ecosystems/parsers-dotnet.d.ts +40 -4
  187. package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
  188. package/types/lib/ecosystems/parsers-go.d.ts +85 -13
  189. package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
  190. package/types/lib/ecosystems/parsers-js.d.ts +17 -20
  191. package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
  192. package/types/lib/ecosystems/parsers-jvm.d.ts +28 -2
  193. package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
  194. package/types/lib/ecosystems/parsers-misc.d.ts +37 -58
  195. package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
  196. package/types/lib/ecosystems/parsers-python.d.ts +14 -3
  197. package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
  198. package/types/lib/ecosystems/pythonutils.d.ts +19 -1
  199. package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
  200. package/types/lib/ecosystems/rubyutils.d.ts +144 -12
  201. package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
  202. package/types/lib/ecosystems/rusi.d.ts.map +1 -1
  203. package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -1
  204. package/types/lib/ecosystems/scalasem.d.ts.map +1 -1
  205. package/types/lib/ecosystems/vendoredCode.d.ts +26 -0
  206. package/types/lib/ecosystems/vendoredCode.d.ts.map +1 -1
  207. package/types/lib/ecosystems/venvProbe.d.ts +40 -0
  208. package/types/lib/ecosystems/venvProbe.d.ts.map +1 -0
  209. package/types/lib/evinser/evinser.d.ts +88 -8
  210. package/types/lib/evinser/evinser.d.ts.map +1 -1
  211. package/types/lib/evinser/swiftsem.d.ts +10 -0
  212. package/types/lib/evinser/swiftsem.d.ts.map +1 -1
  213. package/types/lib/inventory/agentSkillSpec.d.ts +13 -0
  214. package/types/lib/inventory/agentSkillSpec.d.ts.map +1 -0
  215. package/types/lib/inventory/apkInstalledDb.d.ts +42 -0
  216. package/types/lib/inventory/apkInstalledDb.d.ts.map +1 -0
  217. package/types/lib/inventory/atomUtils.d.ts +33 -0
  218. package/types/lib/inventory/atomUtils.d.ts.map +1 -1
  219. package/types/lib/inventory/brotliDecoder.d.ts +58 -0
  220. package/types/lib/inventory/brotliDecoder.d.ts.map +1 -0
  221. package/types/lib/inventory/cacheDir.d.ts +12 -4
  222. package/types/lib/inventory/cacheDir.d.ts.map +1 -1
  223. package/types/lib/inventory/cbomutils.d.ts +17 -0
  224. package/types/lib/inventory/cbomutils.d.ts.map +1 -1
  225. package/types/lib/inventory/certificates.d.ts +205 -0
  226. package/types/lib/inventory/certificates.d.ts.map +1 -0
  227. package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
  228. package/types/lib/inventory/deps.d.ts +2 -1
  229. package/types/lib/inventory/deps.d.ts.map +1 -1
  230. package/types/lib/inventory/display.d.ts +18 -0
  231. package/types/lib/inventory/display.d.ts.map +1 -1
  232. package/types/lib/inventory/dosai.d.ts +162 -7
  233. package/types/lib/inventory/dosai.d.ts.map +1 -1
  234. package/types/lib/inventory/dotnetRuntime.d.ts +44 -0
  235. package/types/lib/inventory/dotnetRuntime.d.ts.map +1 -0
  236. package/types/lib/inventory/dynamic.d.ts +6 -1
  237. package/types/lib/inventory/dynamic.d.ts.map +1 -1
  238. package/types/lib/inventory/envcontext.d.ts +92 -8
  239. package/types/lib/inventory/envcontext.d.ts.map +1 -1
  240. package/types/lib/inventory/evidenceUtils.d.ts +29 -10
  241. package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
  242. package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
  243. package/types/lib/inventory/goBuildInfo.d.ts +10 -0
  244. package/types/lib/inventory/goBuildInfo.d.ts.map +1 -0
  245. package/types/lib/inventory/gtfobins.d.ts.map +1 -1
  246. package/types/lib/inventory/hbom.d.ts.map +1 -1
  247. package/types/lib/inventory/hbomAnalysis.d.ts +10 -0
  248. package/types/lib/inventory/hbomAnalysis.d.ts.map +1 -1
  249. package/types/lib/inventory/hostRuntimeProbe.d.ts +44 -0
  250. package/types/lib/inventory/hostRuntimeProbe.d.ts.map +1 -0
  251. package/types/lib/inventory/hostTopology.d.ts.map +1 -1
  252. package/types/lib/inventory/jvmToolEnv.d.ts +12 -0
  253. package/types/lib/inventory/jvmToolEnv.d.ts.map +1 -1
  254. package/types/lib/inventory/licenseEnhancer.d.ts.map +1 -1
  255. package/types/lib/inventory/mavenCentralMirror.d.ts +170 -0
  256. package/types/lib/inventory/mavenCentralMirror.d.ts.map +1 -0
  257. package/types/lib/inventory/nodeBuildInfo.d.ts +95 -0
  258. package/types/lib/inventory/nodeBuildInfo.d.ts.map +1 -0
  259. package/types/lib/inventory/nodeHostProbe.d.ts +15 -0
  260. package/types/lib/inventory/nodeHostProbe.d.ts.map +1 -0
  261. package/types/lib/inventory/osPackagePurl.d.ts +99 -0
  262. package/types/lib/inventory/osPackagePurl.d.ts.map +1 -0
  263. package/types/lib/inventory/osPackageResolver.d.ts +44 -2
  264. package/types/lib/inventory/osPackageResolver.d.ts.map +1 -1
  265. package/types/lib/inventory/osinfo.d.ts +31 -6
  266. package/types/lib/inventory/osinfo.d.ts.map +1 -1
  267. package/types/lib/inventory/osqueryTransform.d.ts +51 -0
  268. package/types/lib/inventory/osqueryTransform.d.ts.map +1 -1
  269. package/types/lib/inventory/phpBuildInfo.d.ts +142 -0
  270. package/types/lib/inventory/phpBuildInfo.d.ts.map +1 -0
  271. package/types/lib/inventory/phpHostProbe.d.ts +35 -0
  272. package/types/lib/inventory/phpHostProbe.d.ts.map +1 -0
  273. package/types/lib/inventory/rootfsCerts.d.ts +27 -0
  274. package/types/lib/inventory/rootfsCerts.d.ts.map +1 -0
  275. package/types/lib/inventory/rubyBuildInfo.d.ts +271 -0
  276. package/types/lib/inventory/rubyBuildInfo.d.ts.map +1 -0
  277. package/types/lib/inventory/rubyHostProbe.d.ts +47 -0
  278. package/types/lib/inventory/rubyHostProbe.d.ts.map +1 -0
  279. package/types/lib/inventory/source.d.ts +38 -0
  280. package/types/lib/inventory/source.d.ts.map +1 -1
  281. package/types/lib/inventory/spdx.d.ts +15 -0
  282. package/types/lib/inventory/spdx.d.ts.map +1 -1
  283. package/types/lib/inventory/traceRunner.d.ts +4 -1
  284. package/types/lib/inventory/traceRunner.d.ts.map +1 -1
  285. package/types/lib/inventory/tracedCrypto.d.ts +22 -0
  286. package/types/lib/inventory/tracedCrypto.d.ts.map +1 -1
  287. package/types/lib/managers/binary.d.ts +10 -0
  288. package/types/lib/managers/binary.d.ts.map +1 -1
  289. package/types/lib/managers/docker.d.ts +24 -0
  290. package/types/lib/managers/docker.d.ts.map +1 -1
  291. package/types/lib/parsers/email.d.ts +19 -0
  292. package/types/lib/parsers/email.d.ts.map +1 -0
  293. package/types/lib/parsers/largeJson.d.ts +17 -3
  294. package/types/lib/parsers/largeJson.d.ts.map +1 -1
  295. package/types/lib/server/server.d.ts +8 -0
  296. package/types/lib/server/server.d.ts.map +1 -1
  297. package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
  298. package/types/lib/stages/postgen/introspection/reflect.d.ts.map +1 -1
  299. package/types/lib/stages/postgen/ruleEngine.d.ts +7 -4
  300. package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
  301. package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
  302. package/types/lib/stages/pregen/envAudit.d.ts.map +1 -1
  303. package/types/lib/stages/pregen/pregen.d.ts +26 -9
  304. package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
  305. package/types/lib/validator/bomValidator.d.ts.map +1 -1
@@ -23,11 +23,16 @@ import {
23
23
  import {
24
24
  checksumFile,
25
25
  getAllFiles,
26
+ getTmpDir,
26
27
  safeExistsSync,
27
28
  safeSpawnSync,
28
29
  } from "../core/fs.js";
29
30
  import { thoughtLog } from "../core/logger.js";
30
31
  import { dirNameStr, isMac } from "../core/paths.js";
32
+ import {
33
+ isProjectToolingAllowed,
34
+ reportProjectToolingSkipped,
35
+ } from "../core/projectTooling.js";
31
36
  import { readCrateArchiveValues } from "../ecosystems/cargoCache.js";
32
37
  import {
33
38
  buildDependentPurl,
@@ -40,7 +45,12 @@ import {
40
45
  emptyCppBuildContext,
41
46
  resolveCppBuildContext,
42
47
  } from "../ecosystems/cppBuildContext.js";
43
- import { getCppModules, hasCppSources } from "../ecosystems/cppEvidence.js";
48
+ import {
49
+ getCppModules,
50
+ hasCppSources,
51
+ installedVcpkgPorts,
52
+ parseVcpkgManifest,
53
+ } from "../ecosystems/cppEvidence.js";
44
54
  import {
45
55
  getCratesMetadata,
46
56
  getSwiftPackageMetadata,
@@ -55,6 +65,7 @@ import {
55
65
  } from "../ecosystems/parsers-elm.js";
56
66
  import { parseGleamProject } from "../ecosystems/parsers-gleam.js";
57
67
  import {
68
+ compareGoVersions,
58
69
  isGoModWhyNotNeeded,
59
70
  parseGoListDep,
60
71
  parseGoModData,
@@ -126,6 +137,10 @@ import { resolveZigGraph } from "../ecosystems/zigResolver.js";
126
137
  import { cmakeBuildDirCandidates } from "../inventory/cmakeBuildDirs.js";
127
138
  import { mergeDependencies, trimComponents } from "../inventory/depsUtils.js";
128
139
  import { convertOSQueryResults } from "../inventory/evidenceUtils.js";
140
+ import {
141
+ clojureMirrorArgs,
142
+ leiningenMirrorArgs,
143
+ } from "../inventory/mavenCentralMirror.js";
129
144
  import { applyPurl, nixBomRef, tryBuildPurl } from "../inventory/purl.js";
130
145
  import {
131
146
  classifyProbeResult,
@@ -198,6 +213,30 @@ export function getCargoCacheDir() {
198
213
  );
199
214
  }
200
215
 
216
+ /**
217
+ * Add a Go module of the project, a nested go.mod or a go.work member, under
218
+ * the parent component. A module that is already the parent, one of its
219
+ * subcomponents, or a component (a directory replacement inside the project)
220
+ * is not added again, so no bom-ref appears twice.
221
+ *
222
+ * @param {Object} parentComponent The project's parent component
223
+ * @param {Object} moduleComponent The module to add
224
+ * @param {Object[]} pkgList Components found so far
225
+ */
226
+ function addGoSubComponent(parentComponent, moduleComponent, pkgList) {
227
+ const ref = moduleComponent?.["bom-ref"];
228
+ if (
229
+ !ref ||
230
+ ref === parentComponent["bom-ref"] ||
231
+ parentComponent.components?.some((c) => c["bom-ref"] === ref) ||
232
+ pkgList.some((c) => c["bom-ref"] === ref)
233
+ ) {
234
+ return;
235
+ }
236
+ parentComponent.components = parentComponent.components || [];
237
+ parentComponent.components.push(moduleComponent);
238
+ }
239
+
201
240
  /**
202
241
  * Function to create bom string for Go projects
203
242
  *
@@ -313,6 +352,20 @@ export async function createGoBom(path, options) {
313
352
  }
314
353
  }
315
354
  }
355
+ // go mod why answers for a module path, but go.sum also names versions
356
+ // that only took part in version selection. Only a version whose content
357
+ // go.sum holds a checksum for was ever downloaded, and of those, MVS
358
+ // builds the highest.
359
+ const builtVersions = {};
360
+ for (const apkg of pkgList) {
361
+ const built = builtVersions[apkg.name];
362
+ if (
363
+ apkg._integrity &&
364
+ (!built || compareGoVersions(apkg.version, built) > 0)
365
+ ) {
366
+ builtVersions[apkg.name] = apkg.version;
367
+ }
368
+ }
316
369
  // A module go reports as unneeded is optional, but only when every module
317
370
  // was checked: once go mod why fails, the answers are incomplete, and a
318
371
  // tool failure is not evidence that a module is unused.
@@ -321,7 +374,9 @@ export async function createGoBom(path, options) {
321
374
  continue;
322
375
  }
323
376
  if (requiredModules.has(apkg.name)) {
324
- apkg.scope = "required";
377
+ if (builtVersions[apkg.name] === apkg.version) {
378
+ apkg.scope = "required";
379
+ }
325
380
  } else if (!circuitBreak && unneededModules.has(apkg.name)) {
326
381
  apkg.scope = "optional";
327
382
  }
@@ -384,6 +439,9 @@ export async function createGoBom(path, options) {
384
439
  });
385
440
 
386
441
  let rootParentComponent = null;
442
+ // Whether the go toolchain resolved a module graph. A module without
443
+ // dependencies resolves to no components, and that is a complete answer.
444
+ let resolvedByToolchain = false;
387
445
  // Use the go list -deps and go mod why commands to generate a good quality BOM for non-docker invocations
388
446
  if (
389
447
  !hasAnyProjectType(["docker", "oci", "container", "os"], options, false)
@@ -403,13 +461,15 @@ export async function createGoBom(path, options) {
403
461
  console.log("Executing go list -deps in", basePath);
404
462
  }
405
463
  // TODO: Replacing this with -json gives us more interesting data points such as GoFiles, Imports, and Deps
464
+ // The fields after Dir name the module content checksum and, for a
465
+ // module a replace directive swapped out, the replacement Go builds.
406
466
  let result = safeSpawnSync(
407
467
  "go",
408
468
  [
409
469
  "list",
410
470
  "-deps",
411
471
  "-f",
412
- "'{{with .Module}}{{.Path}}|{{.Version}}|{{.Indirect}}|{{.GoMod}}|{{.GoVersion}}|{{.Main}}|{{.Time}}|{{.Deprecated}}|{{.GoModSum}}|{{.Dir}}{{end}}'",
472
+ "'{{with .Module}}{{.Path}}|{{.Version}}|{{.Indirect}}|{{.GoMod}}|{{.GoVersion}}|{{.Main}}|{{.Time}}|{{.Deprecated}}|{{.GoModSum}}|{{.Dir}}|{{.Sum}}|{{with .Replace}}{{.Path}}{{end}}|{{with .Replace}}{{.Version}}{{end}}|{{with .Replace}}{{.Sum}}{{end}}{{end}}'",
413
473
  "./...",
414
474
  ],
415
475
  {
@@ -453,7 +513,9 @@ export async function createGoBom(path, options) {
453
513
  const stdout = result.stdout;
454
514
  if (stdout) {
455
515
  let cmdOutput = Buffer.from(stdout).toString();
456
- const retMap = await parseGoListDep(cmdOutput, gosumMap);
516
+ const retMap = await parseGoListDep(cmdOutput, gosumMap, {
517
+ mainModuleDir: basePath,
518
+ });
457
519
  if (retMap.pkgList?.length) {
458
520
  pkgList = pkgList.concat(retMap.pkgList);
459
521
  }
@@ -462,6 +524,7 @@ export async function createGoBom(path, options) {
462
524
  retMap.parentComponent &&
463
525
  Object.keys(retMap.parentComponent).length
464
526
  ) {
527
+ resolvedByToolchain = true;
465
528
  if (!rootParentComponent) {
466
529
  // First (shallowest) module becomes the root
467
530
  rootParentComponent = retMap.parentComponent;
@@ -469,12 +532,18 @@ export async function createGoBom(path, options) {
469
532
  parentComponent = rootParentComponent;
470
533
  } else {
471
534
  // Subsequent modules become subcomponents
472
- if (!parentComponent.components) {
473
- parentComponent.components = [];
474
- }
475
- parentComponent.components.push(retMap.parentComponent);
535
+ addGoSubComponent(
536
+ parentComponent,
537
+ retMap.parentComponent,
538
+ pkgList,
539
+ );
476
540
  }
477
541
  }
542
+ // The other members of a go.work workspace are modules of the same
543
+ // project, which no registry holds.
544
+ for (const workspaceModule of retMap.workspaceModules || []) {
545
+ addGoSubComponent(parentComponent, workspaceModule, pkgList);
546
+ }
478
547
  if (DEBUG_MODE) {
479
548
  console.log("Executing go mod graph in", basePath);
480
549
  }
@@ -524,8 +593,11 @@ export async function createGoBom(path, options) {
524
593
  }
525
594
  // Retain the parent component hierarchy
526
595
  if (Object.keys(retMap.parentComponent).length) {
527
- parentComponent.components = parentComponent.components || [];
528
- parentComponent.components.push(retMap.parentComponent);
596
+ addGoSubComponent(
597
+ parentComponent,
598
+ retMap.parentComponent,
599
+ pkgList,
600
+ );
529
601
  }
530
602
  }
531
603
  } else {
@@ -538,6 +610,7 @@ export async function createGoBom(path, options) {
538
610
  shell: isWin,
539
611
  });
540
612
  if (result.stdout) {
613
+ resolvedByToolchain = true;
541
614
  const cmdOutput = Buffer.from(result.stdout).toString();
542
615
  // The arguments to parseGoModGraph are slightly different to force inclusion of all packages
543
616
  const retMap = await parseGoModGraph(
@@ -566,8 +639,11 @@ export async function createGoBom(path, options) {
566
639
  parentComponent = rootParentComponent;
567
640
  } else {
568
641
  // Subsequent modules become subcomponents
569
- parentComponent.components = parentComponent.components || [];
570
- parentComponent.components.push(retMap.parentComponent);
642
+ addGoSubComponent(
643
+ parentComponent,
644
+ retMap.parentComponent,
645
+ pkgList,
646
+ );
571
647
  }
572
648
  }
573
649
  } else {
@@ -589,7 +665,7 @@ export async function createGoBom(path, options) {
589
665
  }
590
666
  }
591
667
  }
592
- if (pkgList.length && !shouldManuallyParse) {
668
+ if ((pkgList.length || resolvedByToolchain) && !shouldManuallyParse) {
593
669
  return buildBomNSData(options, pkgList, "golang", {
594
670
  dependencies,
595
671
  parentComponent,
@@ -732,11 +808,19 @@ function cargoAnswersVersion(cwd) {
732
808
  * @param {string} [filterPlatform] Target triple to resolve the graph for
733
809
  * @returns {object|undefined} Parsed `cargo metadata` output
734
810
  */
735
- function runCargoMetadata(cargoTomlFile, filterPlatform) {
736
- const basePath = dirname(cargoTomlFile);
811
+ function runCargoMetadata(cargoTomlFile, filterPlatform, options = {}) {
812
+ // cargo reads `.cargo/config.toml` (rustc, rustc-wrapper, [env]) and rustup
813
+ // reads `rust-toolchain.toml` from the working directory, and `cargo
814
+ // metadata` runs rustc to learn the target. Without permission to run the
815
+ // project's tooling, cargo starts outside the project and stays offline.
816
+ const toolingAllowed = isProjectToolingAllowed(options);
817
+ const basePath = toolingAllowed ? dirname(cargoTomlFile) : getTmpDir();
737
818
  const platformArgs = filterPlatform
738
819
  ? ["--filter-platform", filterPlatform]
739
820
  : [];
821
+ if (!toolingAllowed) {
822
+ platformArgs.push("--offline");
823
+ }
740
824
  // `--locked` keeps the user's lock file untouched; a workspace that is out of
741
825
  // date with its lock file needs the retry without it.
742
826
  for (const lockArgs of [["--locked"], []]) {
@@ -810,7 +894,7 @@ function annotateCargoDependencyKinds(
810
894
  let anyMetadata = false;
811
895
  let everyMetadata = true;
812
896
  for (const cargoTomlFile of cargoFiles) {
813
- const metadata = runCargoMetadata(cargoTomlFile);
897
+ const metadata = runCargoMetadata(cargoTomlFile, undefined, options);
814
898
  if (!metadata) {
815
899
  everyMetadata = false;
816
900
  continue;
@@ -824,7 +908,11 @@ function annotateCargoDependencyKinds(
824
908
  visitedWorkspaceRoots.add(workspaceRoot);
825
909
  anyMetadata = true;
826
910
  if (CARGO_TARGET) {
827
- const targetMetadata = runCargoMetadata(cargoTomlFile, CARGO_TARGET);
911
+ const targetMetadata = runCargoMetadata(
912
+ cargoTomlFile,
913
+ CARGO_TARGET,
914
+ options,
915
+ );
828
916
  if (targetMetadata) {
829
917
  for (const key of parseCargoMetadataResolve(targetMetadata)
830
918
  .resolvedKeys) {
@@ -962,13 +1050,31 @@ export async function createRustBom(path, options) {
962
1050
  `${options.multiProject ? "**/" : ""}Cargo.toml`,
963
1051
  options,
964
1052
  );
1053
+ // `cargo check` compiles the project, running its build scripts and
1054
+ // procedural macros, so --deep runs it only when the project's own tooling
1055
+ // may run.
1056
+ const cargoToolingAllowed = isProjectToolingAllowed(options);
1057
+ if (
1058
+ options.deep &&
1059
+ cargoFiles.length &&
1060
+ !cargoToolingAllowed &&
1061
+ !hasAnyProjectType(["oci"], options, false)
1062
+ ) {
1063
+ reportProjectToolingSkipped(
1064
+ options,
1065
+ null,
1066
+ "Skipping 'cargo check' since dependency installation is disabled. Build scripts and procedural macros are not run, so the files each crate uses are not recorded.",
1067
+ );
1068
+ }
965
1069
  // Attempt to build or generate lock files automatically
966
1070
  for (const f of cargoFiles) {
967
1071
  // If there are no cargo.lock files, we can attempt a cargo install when
968
1072
  // options.deep is true or options.lifecycle == build or post-build with installDeps
969
1073
  // Why the need for installDeps? It currently defaults to true, so let's obey if someone wants no installs
970
1074
  if (
971
- (options.deep && !hasAnyProjectType(["oci"], options, false)) ||
1075
+ (options.deep &&
1076
+ cargoToolingAllowed &&
1077
+ !hasAnyProjectType(["oci"], options, false)) ||
972
1078
  (options.installDeps &&
973
1079
  !safeExistsSync(f.replace(".toml", ".lock")) &&
974
1080
  ["build", "post-build"].includes(options.lifecycle))
@@ -1709,10 +1815,33 @@ export function createCppBom(path, options) {
1709
1815
  // The need for java >= 21 with atom is causing confusions since there could be C projects
1710
1816
  // inside of other project types. So we currently limit this analyis only when -t argument
1711
1817
  // is used.
1712
- if (
1713
- !hasAnyProjectType(["docker", "oci", "container", "os"], options, false) &&
1714
- (!options.createMultiXBom || options.deep)
1715
- ) {
1818
+ if (!isImageScan && options.createMultiXBom && !options.deep) {
1819
+ // The atom analysis below is skipped in this mode, but a vcpkg manifest is
1820
+ // read without running anything, and its declared ports are as much a
1821
+ // part of the project as CMake's find_package names.
1822
+ const manifest = parseVcpkgManifest(path, {
1823
+ installedPorts: installedVcpkgPorts(path, options),
1824
+ isListed: (name) =>
1825
+ pkgList.some(
1826
+ (p) => !p.group && p.name?.toLowerCase() === `${name}`.toLowerCase(),
1827
+ ),
1828
+ });
1829
+ if (manifest.pkgList.length) {
1830
+ pkgList = pkgList.concat(manifest.pkgList);
1831
+ if (!parentComponent && manifest.parentComponent) {
1832
+ parentComponent = manifest.parentComponent;
1833
+ }
1834
+ if (parentComponent?.["bom-ref"]) {
1835
+ dependencies = mergeDependencies(dependencies, [
1836
+ {
1837
+ ref: parentComponent["bom-ref"],
1838
+ dependsOn: manifest.pkgList.map((p) => p["bom-ref"]),
1839
+ },
1840
+ ]);
1841
+ }
1842
+ }
1843
+ }
1844
+ if (!isImageScan && (!options.createMultiXBom || options.deep)) {
1716
1845
  let osPkgsList = [];
1717
1846
  // Case 1: Development libraries installed in this OS environment might be used for build
1718
1847
  // We collect OS packages with the word dev in the name using osquery here
@@ -1870,11 +1999,39 @@ export function createClojureBom(path, options) {
1870
1999
  if (readEnvironmentVariable("LEIN_ARGS")) {
1871
2000
  LEIN_ARGS = readEnvironmentVariable("LEIN_ARGS").split(" ");
1872
2001
  }
2002
+ const leinProjectContent = safeExistsSync(leinFiles[0])
2003
+ ? readFileSync(leinFiles[0], { encoding: "utf-8" })
2004
+ : undefined;
2005
+ LEIN_ARGS = leiningenMirrorArgs(LEIN_ARGS, leinProjectContent);
2006
+ // `lein deps :tree-data` evaluates project.clj, which is a Clojure
2007
+ // program, so it belongs to the dependency-tooling surface disabled by
2008
+ // --no-install-deps and the pre-build lifecycle.
2009
+ const leinToolingAllowed = isProjectToolingAllowed(options);
1873
2010
  for (const f of leinFiles) {
1874
2011
  if (DEBUG_MODE) {
1875
2012
  console.log(`Parsing ${f}`);
1876
2013
  }
1877
2014
  const basePath = dirname(f);
2015
+ if (!leinToolingAllowed) {
2016
+ reportProjectToolingSkipped(
2017
+ options,
2018
+ "clojure.lein.tooling-disabled",
2019
+ "Skipping 'lein deps :tree-data' since dependency installation is disabled. Only the dependencies declared in project.clj will be used.",
2020
+ {
2021
+ ecosystem: "clojure",
2022
+ tool: "lein",
2023
+ impact: "transitive-deps",
2024
+ detail:
2025
+ "Dependency installation is disabled, so project.clj was not evaluated and only its directly declared dependencies are available.",
2026
+ },
2027
+ );
2028
+ const leinData = readFileSync(f, { encoding: "utf-8" });
2029
+ const dlist = parseLeiningenData(leinData);
2030
+ if (dlist?.length) {
2031
+ pkgList = pkgList.concat(dlist);
2032
+ }
2033
+ continue;
2034
+ }
1878
2035
  console.log("Executing", LEIN_CMD, "in", basePath);
1879
2036
  const result = safeSpawnSync(LEIN_CMD, LEIN_ARGS, {
1880
2037
  cwd: basePath,
@@ -1937,6 +2094,7 @@ export function createClojureBom(path, options) {
1937
2094
  if (readEnvironmentVariable("CLJ_ARGS")) {
1938
2095
  CLJ_ARGS = readEnvironmentVariable("CLJ_ARGS").split(" ");
1939
2096
  }
2097
+ CLJ_ARGS = clojureMirrorArgs(CLJ_ARGS);
1940
2098
  for (const f of ednFiles) {
1941
2099
  const basePath = dirname(f);
1942
2100
  console.log("Executing", CLJ_CMD, "in", basePath);
@@ -2235,7 +2393,39 @@ export async function createSwiftBom(path, options) {
2235
2393
  );
2236
2394
  }
2237
2395
  if (swiftFiles.length) {
2396
+ // A SwiftPM manifest is a Swift program, so `swift package dump-package`
2397
+ // and `show-dependencies` execute the scanned project's code (and fetch
2398
+ // missing dependencies). They belong to the dependency-tooling surface
2399
+ // disabled by --no-install-deps and the pre-build lifecycle; the BOM then
2400
+ // comes from Package.resolved alone.
2401
+ const swiftToolingAllowed = isProjectToolingAllowed(options);
2402
+ if (!swiftToolingAllowed) {
2403
+ reportProjectToolingSkipped(
2404
+ options,
2405
+ "swift.tooling-disabled",
2406
+ "Skipping 'swift package show-dependencies' since dependency installation is disabled. Only the packages in Package.resolved will be used.",
2407
+ {
2408
+ ecosystem: "swift",
2409
+ tool: "swift",
2410
+ impact: "transitive-deps",
2411
+ detail:
2412
+ "Dependency installation is disabled, so the Package.swift manifest was not evaluated and only the packages from Package.resolved are available.",
2413
+ },
2414
+ );
2415
+ // The manifest is not run, so a project without Package.resolved still
2416
+ // gets a parent component named after its directory.
2417
+ if (!Object.keys(parentComponent).length) {
2418
+ parentComponent = createDefaultParentComponent(
2419
+ swiftFiles[0],
2420
+ "swift",
2421
+ options,
2422
+ );
2423
+ }
2424
+ }
2238
2425
  for (const f of swiftFiles) {
2426
+ if (!swiftToolingAllowed) {
2427
+ break;
2428
+ }
2239
2429
  const basePath = dirname(f);
2240
2430
  if (completedPath.includes(basePath)) {
2241
2431
  continue;
@@ -2461,10 +2651,33 @@ export async function createCocoaBom(path, options) {
2461
2651
  allDependencies.set(name, podDependencies);
2462
2652
  }
2463
2653
  const targetDependencies = new Map();
2464
- if (
2465
- !readEnvironmentVariable("COCOA_INCLUDED_TARGETS") &&
2466
- !readEnvironmentVariable("COCOA_EXCLUDED_TARGETS")
2467
- ) {
2654
+ // `pod ipc podfile-json` evaluates the Podfile, which is a Ruby program,
2655
+ // so per-target filtering through it belongs to the dependency-tooling
2656
+ // surface disabled by --no-install-deps and the pre-build lifecycle. A
2657
+ // gated scan then keeps every pod the lockfile resolved (the union across
2658
+ // targets) instead of the configured target subset.
2659
+ const cocoaTargetsConfigured =
2660
+ readEnvironmentVariable("COCOA_INCLUDED_TARGETS") ||
2661
+ readEnvironmentVariable("COCOA_EXCLUDED_TARGETS");
2662
+ const cocoaToolingAllowed = isProjectToolingAllowed(options);
2663
+ // True only when target names the Podfile actually resolved are known, so
2664
+ // the include/exclude filters below can be applied to real targets.
2665
+ let targetFilteringActive = false;
2666
+ if (!cocoaTargetsConfigured || !cocoaToolingAllowed) {
2667
+ if (cocoaTargetsConfigured) {
2668
+ reportProjectToolingSkipped(
2669
+ options,
2670
+ "cocoa.podfile-json.tooling-disabled",
2671
+ "Skipping 'pod ipc podfile-json' since dependency installation is disabled. Every pod from Podfile.lock is included without per-target filtering.",
2672
+ {
2673
+ ecosystem: "cocoa",
2674
+ tool: "pod",
2675
+ impact: "components",
2676
+ detail:
2677
+ "Dependency installation is disabled, so the Podfile was not evaluated and target filtering fell back to all pods resolved in Podfile.lock.",
2678
+ },
2679
+ );
2680
+ }
2468
2681
  targetDependencies.set("Pods", podfileLock["DEPENDENCIES"]);
2469
2682
  } else {
2470
2683
  const result = executePodCommand(
@@ -2472,18 +2685,39 @@ export async function createCocoaBom(path, options) {
2472
2685
  projectPath,
2473
2686
  options,
2474
2687
  );
2475
- const resolvedPodFile = JSON.parse(result.stdout);
2476
- parsePodfileTargets(
2477
- resolvedPodFile["target_definitions"][0],
2478
- targetDependencies,
2479
- );
2688
+ let resolvedPodFile;
2689
+ try {
2690
+ resolvedPodFile = JSON.parse(result.stdout);
2691
+ } catch (_e) {
2692
+ resolvedPodFile = undefined;
2693
+ }
2694
+ if (resolvedPodFile?.target_definitions?.length) {
2695
+ parsePodfileTargets(
2696
+ resolvedPodFile["target_definitions"][0],
2697
+ targetDependencies,
2698
+ );
2699
+ targetFilteringActive = true;
2700
+ } else {
2701
+ // pod failed or printed nothing usable (it refuses to run as root,
2702
+ // for one), and an unparseable Podfile used to abort the whole scan.
2703
+ // Keep every locked pod rather than none.
2704
+ console.log(
2705
+ "The Podfile could not be resolved with CocoaPods, so all pods from Podfile.lock are included without per-target filtering.",
2706
+ );
2707
+ targetDependencies.set("Pods", podfileLock["DEPENDENCIES"]);
2708
+ }
2480
2709
  }
2481
2710
  const usedTargets = new Set(
2482
- readEnvironmentVariable("COCOA_INCLUDED_TARGETS")
2711
+ targetFilteringActive && readEnvironmentVariable("COCOA_INCLUDED_TARGETS")
2483
2712
  ? readEnvironmentVariable("COCOA_INCLUDED_TARGETS").split(",")
2484
2713
  : targetDependencies.keys(),
2485
2714
  );
2486
- if (readEnvironmentVariable("COCOA_EXCLUDED_TARGETS")) {
2715
+ // Without the resolved Podfile there are no target names to exclude, and
2716
+ // excluding the lockfile's stand-in "Pods" target would drop every pod.
2717
+ if (
2718
+ targetFilteringActive &&
2719
+ readEnvironmentVariable("COCOA_EXCLUDED_TARGETS")
2720
+ ) {
2487
2721
  readEnvironmentVariable("COCOA_EXCLUDED_TARGETS")
2488
2722
  .split(",")
2489
2723
  .forEach((excludedTarget) => {