@cdxgen/cdxgen 13.5.0 → 13.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. package/README.md +17 -10
  2. package/bin/audit.js +7 -4
  3. package/bin/cdxgen.js +260 -37
  4. package/bin/convert.js +146 -22
  5. package/bin/evinse.js +28 -3
  6. package/bin/repl.js +47 -3
  7. package/bin/sign.js +211 -34
  8. package/bin/tracebom.js +18 -6
  9. package/bin/validate.js +24 -3
  10. package/bin/verify.js +113 -5
  11. package/data/behavior-taxonomy.schema.json +1491 -0
  12. package/data/cyclonedx-2.0-bundled.schema.json +18606 -5528
  13. package/data/cyclonedx-2.0-cryptography-defs.schema.json +857 -0
  14. package/data/license-aliases.json +24 -2
  15. package/data/pqc-migration.json +239 -0
  16. package/data/remediations.json +176 -0
  17. package/data/rules/ai-bom.yaml +1 -1
  18. package/data/rules/brotli-decoder.yaml +107 -0
  19. package/data/rules/cbom-security.yaml +4 -3
  20. package/data/rules/package-integrity.yaml +28 -0
  21. package/data/rules/vscode-extensions.yaml +75 -0
  22. package/data/spdx-license-list.json +121 -7
  23. package/data/spdx-licenses.json +69 -0
  24. package/data/spdx.schema.json +845 -2
  25. package/lib/audit/index.js +25 -3
  26. package/lib/cli/bomAssembly.js +172 -4
  27. package/lib/cli/cliOptions.js +121 -17
  28. package/lib/cli/index.js +720 -902
  29. package/lib/cli/jsBom.js +156 -64
  30. package/lib/cli/jvmBom.js +602 -86
  31. package/lib/cli/managedBom.js +161 -19
  32. package/lib/cli/nativeBom.js +52 -5
  33. package/lib/core/boundedFile.js +344 -0
  34. package/lib/core/brotliProbe.js +182 -0
  35. package/lib/core/env.js +34 -0
  36. package/lib/core/fs.js +138 -3
  37. package/lib/core/globPatterns.js +218 -0
  38. package/lib/core/httpClient.js +98 -1
  39. package/lib/core/lockPaths.js +38 -0
  40. package/lib/core/paths.js +24 -1
  41. package/lib/core/processTree.js +100 -8
  42. package/lib/core/projectConfig.js +332 -25
  43. package/lib/core/toolRegistry.js +184 -0
  44. package/lib/ecosystems/cppEvidence.js +263 -106
  45. package/lib/ecosystems/cppIncludeResolver.js +16 -5
  46. package/lib/ecosystems/denoutils.js +2 -2
  47. package/lib/ecosystems/ecosystems.js +25 -10
  48. package/lib/ecosystems/gemHostProbe.js +301 -0
  49. package/lib/ecosystems/golem.js +3 -8
  50. package/lib/ecosystems/gradleutils.js +1909 -229
  51. package/lib/ecosystems/jsEvidence.js +90 -38
  52. package/lib/ecosystems/kosi.js +3 -5
  53. package/lib/ecosystems/npmVersionResolution.js +376 -0
  54. package/lib/ecosystems/parsers-bazel.js +107 -6
  55. package/lib/ecosystems/parsers-js.js +505 -22
  56. package/lib/ecosystems/parsers-misc.js +209 -20
  57. package/lib/ecosystems/parsers-python.js +178 -30
  58. package/lib/ecosystems/parsers-rust.js +117 -15
  59. package/lib/ecosystems/pythonutils.js +128 -2
  60. package/lib/ecosystems/remote/huggingface.js +22 -0
  61. package/lib/ecosystems/rubyutils.js +538 -31
  62. package/lib/ecosystems/rusi.js +2 -4
  63. package/lib/ecosystems/scalacliutils.js +2 -0
  64. package/lib/ecosystems/scalasem.js +798 -152
  65. package/lib/ecosystems/vendoredCode.js +237 -3
  66. package/lib/ecosystems/venvProbe.js +360 -0
  67. package/lib/evinser/evinser.js +536 -71
  68. package/lib/evinser/scalasem.js +5 -1
  69. package/lib/helpers/agenticToolutils.js +525 -94
  70. package/lib/helpers/bomSigner.js +43 -9
  71. package/lib/helpers/jssSigner.js +1276 -0
  72. package/lib/helpers/vsixutils.js +1574 -315
  73. package/lib/inventory/agentBlueprint.js +193 -0
  74. package/lib/inventory/agentToolNames.js +145 -0
  75. package/lib/inventory/aiCollector.js +153 -7
  76. package/lib/inventory/aiInventory.js +44 -8
  77. package/lib/inventory/aiProviders.js +324 -0
  78. package/lib/inventory/atomUtils.js +77 -0
  79. package/lib/inventory/bomUtils.js +8 -1
  80. package/lib/inventory/brotliDecoder.js +142 -0
  81. package/lib/inventory/buildToolRateLimit.js +1 -1
  82. package/lib/inventory/cbomutils.js +56 -7
  83. package/lib/inventory/ciParsers/githubActionsLock.js +821 -0
  84. package/lib/inventory/citations.js +31 -2
  85. package/lib/inventory/communityAiConfigParser.js +978 -80
  86. package/lib/inventory/cyclonedx20.js +152 -0
  87. package/lib/inventory/cyclonedx20Common.js +286 -0
  88. package/lib/inventory/cyclonedx20Derived.js +159 -0
  89. package/lib/inventory/cyclonedx20Parties.js +552 -0
  90. package/lib/inventory/cyclonedx20Read.js +768 -0
  91. package/lib/inventory/cyclonedx20ReadCommon.js +374 -0
  92. package/lib/inventory/cyclonedx20ReadComponents.js +692 -0
  93. package/lib/inventory/cyclonedx20ReadContext.js +380 -0
  94. package/lib/inventory/cyclonedx20ReadEvidence.js +466 -0
  95. package/lib/inventory/cyclonedx20ReadSections.js +599 -0
  96. package/lib/inventory/cyclonedx20Render.js +766 -0
  97. package/lib/inventory/cyclonedx20RenderComponents.js +716 -0
  98. package/lib/inventory/cyclonedx20RenderDefinitions.js +405 -0
  99. package/lib/inventory/cyclonedx20RenderEvidence.js +726 -0
  100. package/lib/inventory/cyclonedx20RenderHardware.js +203 -0
  101. package/lib/inventory/cyclonedx20RenderPatents.js +174 -0
  102. package/lib/inventory/cyclonedx20RenderRefIds.js +314 -0
  103. package/lib/inventory/cyclonedx20RenderSections.js +499 -0
  104. package/lib/inventory/cyclonedx20Tables.js +594 -0
  105. package/lib/inventory/deps.js +141 -13
  106. package/lib/inventory/dosai.js +375 -6
  107. package/lib/inventory/dosaiParsers.js +3 -6
  108. package/lib/inventory/dotnetRuntime.js +367 -0
  109. package/lib/inventory/ecosystemFormulationParsers.js +979 -0
  110. package/lib/inventory/envcontext.js +436 -48
  111. package/lib/inventory/evidenceUtils.js +13 -1
  112. package/lib/inventory/fetchBatch.js +1 -1
  113. package/lib/inventory/formulationParsers.js +124 -14
  114. package/lib/inventory/gtfobins.js +13 -0
  115. package/lib/inventory/hbom.js +45 -6
  116. package/lib/inventory/hbomLoader.js +166 -0
  117. package/lib/inventory/hostRuntimeProbe.js +686 -0
  118. package/lib/inventory/jvmLocalRepos.js +9 -2
  119. package/lib/inventory/jvmToolEnv.js +29 -0
  120. package/lib/inventory/licenseEnhancer.js +12 -0
  121. package/lib/inventory/mavenCentralMirror.js +534 -0
  122. package/lib/inventory/mcpConfigParser.js +5 -0
  123. package/lib/inventory/nodeBuildInfo.js +218 -0
  124. package/lib/inventory/nodeHostProbe.js +202 -0
  125. package/lib/inventory/occurrenceKey.js +90 -0
  126. package/lib/inventory/osPackageResolver.js +182 -0
  127. package/lib/inventory/phpBuildInfo.js +10 -59
  128. package/lib/inventory/phpHostProbe.js +32 -488
  129. package/lib/inventory/pqcMigration.js +426 -0
  130. package/lib/inventory/rubyBuildInfo.js +972 -0
  131. package/lib/inventory/rubyHostProbe.js +218 -0
  132. package/lib/inventory/rustFormulationParser.js +21 -10
  133. package/lib/inventory/scalaCoords.js +4 -3
  134. package/lib/inventory/scalaDedupe.js +440 -0
  135. package/lib/inventory/source.js +114 -8
  136. package/lib/managers/binary.js +337 -3
  137. package/lib/managers/docker.js +79 -0
  138. package/lib/parsers/huggingfaceManifest.js +9 -1
  139. package/lib/parsers/huggingfaceUtils.js +18 -0
  140. package/lib/parsers/kiroPermissions.js +166 -0
  141. package/lib/parsers/largeJson.js +28 -11
  142. package/lib/parsers/vscodeExtensionId.js +183 -0
  143. package/lib/server/server.js +48 -35
  144. package/lib/stages/postgen/postgen.js +41 -1
  145. package/lib/stages/postgen/ruleEngine.js +13 -5
  146. package/lib/stages/postgen/specVersionCompat.js +76 -0
  147. package/lib/stages/pregen/envAudit.js +1 -0
  148. package/lib/stages/pregen/pregen.js +114 -57
  149. package/lib/validator/bomValidator.js +14 -2
  150. package/lib/validator/complianceEngine.js +30 -3
  151. package/lib/validator/complianceRules.js +1416 -4
  152. package/lib/validator/generated/validate-1.6.mjs +1 -1
  153. package/lib/validator/generated/validate-1.7.mjs +1 -1
  154. package/lib/validator/generated/validate-2.0.mjs +57554 -13851
  155. package/lib/validator/index.js +49 -8
  156. package/lib/validator/reporters/json.js +6 -0
  157. package/package.json +11 -10
  158. package/types/bin/repl.d.ts.map +1 -1
  159. package/types/lib/audit/index.d.ts +6 -2
  160. package/types/lib/audit/index.d.ts.map +1 -1
  161. package/types/lib/cli/bomAssembly.d.ts +29 -1
  162. package/types/lib/cli/bomAssembly.d.ts.map +1 -1
  163. package/types/lib/cli/cliOptions.d.ts +6 -0
  164. package/types/lib/cli/cliOptions.d.ts.map +1 -1
  165. package/types/lib/cli/index.d.ts.map +1 -1
  166. package/types/lib/cli/jsBom.d.ts +3 -18
  167. package/types/lib/cli/jsBom.d.ts.map +1 -1
  168. package/types/lib/cli/jvmBom.d.ts +15 -0
  169. package/types/lib/cli/jvmBom.d.ts.map +1 -1
  170. package/types/lib/cli/managedBom.d.ts.map +1 -1
  171. package/types/lib/cli/nativeBom.d.ts.map +1 -1
  172. package/types/lib/core/boundedFile.d.ts +100 -0
  173. package/types/lib/core/boundedFile.d.ts.map +1 -0
  174. package/types/lib/core/brotliProbe.d.ts +37 -0
  175. package/types/lib/core/brotliProbe.d.ts.map +1 -0
  176. package/types/lib/core/env.d.ts +14 -0
  177. package/types/lib/core/env.d.ts.map +1 -1
  178. package/types/lib/core/fs.d.ts +4 -0
  179. package/types/lib/core/fs.d.ts.map +1 -1
  180. package/types/lib/core/globPatterns.d.ts +70 -0
  181. package/types/lib/core/globPatterns.d.ts.map +1 -0
  182. package/types/lib/core/httpClient.d.ts +24 -0
  183. package/types/lib/core/httpClient.d.ts.map +1 -1
  184. package/types/lib/core/lockPaths.d.ts +19 -0
  185. package/types/lib/core/lockPaths.d.ts.map +1 -0
  186. package/types/lib/core/paths.d.ts +9 -0
  187. package/types/lib/core/paths.d.ts.map +1 -1
  188. package/types/lib/core/processTree.d.ts +17 -4
  189. package/types/lib/core/processTree.d.ts.map +1 -1
  190. package/types/lib/core/projectConfig.d.ts +47 -8
  191. package/types/lib/core/projectConfig.d.ts.map +1 -1
  192. package/types/lib/core/toolRegistry.d.ts +36 -0
  193. package/types/lib/core/toolRegistry.d.ts.map +1 -0
  194. package/types/lib/ecosystems/cppEvidence.d.ts +40 -13
  195. package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
  196. package/types/lib/ecosystems/cppIncludeResolver.d.ts +2 -1
  197. package/types/lib/ecosystems/cppIncludeResolver.d.ts.map +1 -1
  198. package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
  199. package/types/lib/ecosystems/gemHostProbe.d.ts +28 -0
  200. package/types/lib/ecosystems/gemHostProbe.d.ts.map +1 -0
  201. package/types/lib/ecosystems/golem.d.ts.map +1 -1
  202. package/types/lib/ecosystems/gradleutils.d.ts +294 -20
  203. package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
  204. package/types/lib/ecosystems/jsEvidence.d.ts +14 -1
  205. package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
  206. package/types/lib/ecosystems/kosi.d.ts.map +1 -1
  207. package/types/lib/ecosystems/npmVersionResolution.d.ts +119 -0
  208. package/types/lib/ecosystems/npmVersionResolution.d.ts.map +1 -0
  209. package/types/lib/ecosystems/parsers-bazel.d.ts.map +1 -1
  210. package/types/lib/ecosystems/parsers-js.d.ts +17 -20
  211. package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
  212. package/types/lib/ecosystems/parsers-misc.d.ts +19 -0
  213. package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
  214. package/types/lib/ecosystems/parsers-python.d.ts +10 -0
  215. package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
  216. package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
  217. package/types/lib/ecosystems/pythonutils.d.ts +19 -1
  218. package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
  219. package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -1
  220. package/types/lib/ecosystems/rubyutils.d.ts +144 -12
  221. package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
  222. package/types/lib/ecosystems/rusi.d.ts.map +1 -1
  223. package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -1
  224. package/types/lib/ecosystems/scalasem.d.ts +58 -16
  225. package/types/lib/ecosystems/scalasem.d.ts.map +1 -1
  226. package/types/lib/ecosystems/vendoredCode.d.ts +26 -0
  227. package/types/lib/ecosystems/vendoredCode.d.ts.map +1 -1
  228. package/types/lib/ecosystems/venvProbe.d.ts +40 -0
  229. package/types/lib/ecosystems/venvProbe.d.ts.map +1 -0
  230. package/types/lib/evinser/evinser.d.ts +120 -13
  231. package/types/lib/evinser/evinser.d.ts.map +1 -1
  232. package/types/lib/evinser/scalasem.d.ts.map +1 -1
  233. package/types/lib/helpers/agenticToolutils.d.ts +53 -19
  234. package/types/lib/helpers/agenticToolutils.d.ts.map +1 -1
  235. package/types/lib/helpers/bomSigner.d.ts +20 -3
  236. package/types/lib/helpers/bomSigner.d.ts.map +1 -1
  237. package/types/lib/helpers/jssSigner.d.ts +288 -0
  238. package/types/lib/helpers/jssSigner.d.ts.map +1 -0
  239. package/types/lib/helpers/vsixutils.d.ts +303 -19
  240. package/types/lib/helpers/vsixutils.d.ts.map +1 -1
  241. package/types/lib/inventory/agentBlueprint.d.ts +70 -0
  242. package/types/lib/inventory/agentBlueprint.d.ts.map +1 -0
  243. package/types/lib/inventory/agentToolNames.d.ts +51 -0
  244. package/types/lib/inventory/agentToolNames.d.ts.map +1 -0
  245. package/types/lib/inventory/aiCollector.d.ts.map +1 -1
  246. package/types/lib/inventory/aiInventory.d.ts.map +1 -1
  247. package/types/lib/inventory/aiProviders.d.ts +85 -0
  248. package/types/lib/inventory/aiProviders.d.ts.map +1 -0
  249. package/types/lib/inventory/atomUtils.d.ts +19 -0
  250. package/types/lib/inventory/atomUtils.d.ts.map +1 -1
  251. package/types/lib/inventory/bomUtils.d.ts.map +1 -1
  252. package/types/lib/inventory/brotliDecoder.d.ts +58 -0
  253. package/types/lib/inventory/brotliDecoder.d.ts.map +1 -0
  254. package/types/lib/inventory/cbomutils.d.ts +17 -0
  255. package/types/lib/inventory/cbomutils.d.ts.map +1 -1
  256. package/types/lib/inventory/ciParsers/githubActionsLock.d.ts +101 -0
  257. package/types/lib/inventory/ciParsers/githubActionsLock.d.ts.map +1 -0
  258. package/types/lib/inventory/citations.d.ts +5 -0
  259. package/types/lib/inventory/citations.d.ts.map +1 -1
  260. package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
  261. package/types/lib/inventory/cyclonedx20.d.ts +99 -0
  262. package/types/lib/inventory/cyclonedx20.d.ts.map +1 -0
  263. package/types/lib/inventory/cyclonedx20Common.d.ts +102 -0
  264. package/types/lib/inventory/cyclonedx20Common.d.ts.map +1 -0
  265. package/types/lib/inventory/cyclonedx20Derived.d.ts +74 -0
  266. package/types/lib/inventory/cyclonedx20Derived.d.ts.map +1 -0
  267. package/types/lib/inventory/cyclonedx20Parties.d.ts +91 -0
  268. package/types/lib/inventory/cyclonedx20Parties.d.ts.map +1 -0
  269. package/types/lib/inventory/cyclonedx20Read.d.ts +51 -0
  270. package/types/lib/inventory/cyclonedx20Read.d.ts.map +1 -0
  271. package/types/lib/inventory/cyclonedx20ReadCommon.d.ts +69 -0
  272. package/types/lib/inventory/cyclonedx20ReadCommon.d.ts.map +1 -0
  273. package/types/lib/inventory/cyclonedx20ReadComponents.d.ts +77 -0
  274. package/types/lib/inventory/cyclonedx20ReadComponents.d.ts.map +1 -0
  275. package/types/lib/inventory/cyclonedx20ReadContext.d.ts +118 -0
  276. package/types/lib/inventory/cyclonedx20ReadContext.d.ts.map +1 -0
  277. package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts +40 -0
  278. package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts.map +1 -0
  279. package/types/lib/inventory/cyclonedx20ReadSections.d.ts +45 -0
  280. package/types/lib/inventory/cyclonedx20ReadSections.d.ts.map +1 -0
  281. package/types/lib/inventory/cyclonedx20Render.d.ts +53 -0
  282. package/types/lib/inventory/cyclonedx20Render.d.ts.map +1 -0
  283. package/types/lib/inventory/cyclonedx20RenderComponents.d.ts +73 -0
  284. package/types/lib/inventory/cyclonedx20RenderComponents.d.ts.map +1 -0
  285. package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts +29 -0
  286. package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts.map +1 -0
  287. package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts +110 -0
  288. package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts.map +1 -0
  289. package/types/lib/inventory/cyclonedx20RenderHardware.d.ts +42 -0
  290. package/types/lib/inventory/cyclonedx20RenderHardware.d.ts.map +1 -0
  291. package/types/lib/inventory/cyclonedx20RenderPatents.d.ts +26 -0
  292. package/types/lib/inventory/cyclonedx20RenderPatents.d.ts.map +1 -0
  293. package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts +55 -0
  294. package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts.map +1 -0
  295. package/types/lib/inventory/cyclonedx20RenderSections.d.ts +45 -0
  296. package/types/lib/inventory/cyclonedx20RenderSections.d.ts.map +1 -0
  297. package/types/lib/inventory/cyclonedx20Tables.d.ts +134 -0
  298. package/types/lib/inventory/cyclonedx20Tables.d.ts.map +1 -0
  299. package/types/lib/inventory/deps.d.ts +35 -2
  300. package/types/lib/inventory/deps.d.ts.map +1 -1
  301. package/types/lib/inventory/dosai.d.ts +36 -1
  302. package/types/lib/inventory/dosai.d.ts.map +1 -1
  303. package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
  304. package/types/lib/inventory/dotnetRuntime.d.ts +91 -0
  305. package/types/lib/inventory/dotnetRuntime.d.ts.map +1 -0
  306. package/types/lib/inventory/ecosystemFormulationParsers.d.ts +73 -0
  307. package/types/lib/inventory/ecosystemFormulationParsers.d.ts.map +1 -0
  308. package/types/lib/inventory/envcontext.d.ts +74 -12
  309. package/types/lib/inventory/envcontext.d.ts.map +1 -1
  310. package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
  311. package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
  312. package/types/lib/inventory/gtfobins.d.ts.map +1 -1
  313. package/types/lib/inventory/hbom.d.ts +11 -0
  314. package/types/lib/inventory/hbom.d.ts.map +1 -1
  315. package/types/lib/inventory/hbomLoader.d.ts +54 -0
  316. package/types/lib/inventory/hbomLoader.d.ts.map +1 -1
  317. package/types/lib/inventory/hostRuntimeProbe.d.ts +44 -0
  318. package/types/lib/inventory/hostRuntimeProbe.d.ts.map +1 -0
  319. package/types/lib/inventory/jvmLocalRepos.d.ts +5 -1
  320. package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -1
  321. package/types/lib/inventory/jvmToolEnv.d.ts +12 -0
  322. package/types/lib/inventory/jvmToolEnv.d.ts.map +1 -1
  323. package/types/lib/inventory/licenseEnhancer.d.ts.map +1 -1
  324. package/types/lib/inventory/mavenCentralMirror.d.ts +170 -0
  325. package/types/lib/inventory/mavenCentralMirror.d.ts.map +1 -0
  326. package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
  327. package/types/lib/inventory/nodeBuildInfo.d.ts +95 -0
  328. package/types/lib/inventory/nodeBuildInfo.d.ts.map +1 -0
  329. package/types/lib/inventory/nodeHostProbe.d.ts +15 -0
  330. package/types/lib/inventory/nodeHostProbe.d.ts.map +1 -0
  331. package/types/lib/inventory/occurrenceKey.d.ts +52 -0
  332. package/types/lib/inventory/occurrenceKey.d.ts.map +1 -0
  333. package/types/lib/inventory/osPackageResolver.d.ts +38 -0
  334. package/types/lib/inventory/osPackageResolver.d.ts.map +1 -1
  335. package/types/lib/inventory/phpBuildInfo.d.ts.map +1 -1
  336. package/types/lib/inventory/phpHostProbe.d.ts.map +1 -1
  337. package/types/lib/inventory/pqcMigration.d.ts +84 -0
  338. package/types/lib/inventory/pqcMigration.d.ts.map +1 -0
  339. package/types/lib/inventory/rubyBuildInfo.d.ts +271 -0
  340. package/types/lib/inventory/rubyBuildInfo.d.ts.map +1 -0
  341. package/types/lib/inventory/rubyHostProbe.d.ts +47 -0
  342. package/types/lib/inventory/rubyHostProbe.d.ts.map +1 -0
  343. package/types/lib/inventory/rustFormulationParser.d.ts +7 -2
  344. package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
  345. package/types/lib/inventory/scalaCoords.d.ts.map +1 -1
  346. package/types/lib/inventory/scalaDedupe.d.ts +43 -0
  347. package/types/lib/inventory/scalaDedupe.d.ts.map +1 -0
  348. package/types/lib/inventory/source.d.ts +25 -0
  349. package/types/lib/inventory/source.d.ts.map +1 -1
  350. package/types/lib/managers/binary.d.ts.map +1 -1
  351. package/types/lib/managers/docker.d.ts +12 -0
  352. package/types/lib/managers/docker.d.ts.map +1 -1
  353. package/types/lib/parsers/huggingfaceManifest.d.ts +10 -1
  354. package/types/lib/parsers/huggingfaceManifest.d.ts.map +1 -1
  355. package/types/lib/parsers/huggingfaceUtils.d.ts +12 -0
  356. package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -1
  357. package/types/lib/parsers/kiroPermissions.d.ts +62 -0
  358. package/types/lib/parsers/kiroPermissions.d.ts.map +1 -0
  359. package/types/lib/parsers/largeJson.d.ts +4 -3
  360. package/types/lib/parsers/largeJson.d.ts.map +1 -1
  361. package/types/lib/parsers/vscodeExtensionId.d.ts +48 -0
  362. package/types/lib/parsers/vscodeExtensionId.d.ts.map +1 -0
  363. package/types/lib/server/server.d.ts.map +1 -1
  364. package/types/lib/stages/postgen/postgen.d.ts +7 -0
  365. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  366. package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
  367. package/types/lib/stages/postgen/specVersionCompat.d.ts +25 -0
  368. package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
  369. package/types/lib/stages/pregen/envAudit.d.ts.map +1 -1
  370. package/types/lib/stages/pregen/pregen.d.ts +12 -8
  371. package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
  372. package/types/lib/validator/bomValidator.d.ts +5 -1
  373. package/types/lib/validator/bomValidator.d.ts.map +1 -1
  374. package/types/lib/validator/complianceEngine.d.ts +4 -4
  375. package/types/lib/validator/complianceEngine.d.ts.map +1 -1
  376. package/types/lib/validator/complianceRules.d.ts +14 -2
  377. package/types/lib/validator/complianceRules.d.ts.map +1 -1
  378. package/types/lib/validator/index.d.ts +10 -0
  379. package/types/lib/validator/index.d.ts.map +1 -1
  380. package/types/lib/validator/reporters/json.d.ts.map +1 -1
@@ -0,0 +1,440 @@
1
+ import { basename } from "node:path";
2
+
3
+ import { Purl } from "@cdxgen/cdx-purl";
4
+
5
+ import { mergeDependencies, trimComponents } from "./depsUtils.js";
6
+ import { mavenPurl } from "./purl.js";
7
+ import { publishedArtifactId, scalaCoordinateOfPurl } from "./scalaCoords.js";
8
+
9
+ const COMPILER_VERSION_PROPERTY = "cdx:scala:compilerVersion";
10
+
11
+ // A jar scan that read the coordinates from the jar's own pom.properties
12
+ // records them with this confidence; a guess from the file name or the
13
+ // manifest records less.
14
+ const DESCRIPTOR_CONFIDENCE = 0.5;
15
+
16
+ function compilerVersionsOf(component) {
17
+ return (component.properties || [])
18
+ .filter((property) => property.name === COMPILER_VERSION_PROPERTY)
19
+ .map((property) => property.value)
20
+ .filter(Boolean);
21
+ }
22
+
23
+ function parsedPurl(component) {
24
+ try {
25
+ return Purl.parse(component?.purl || "");
26
+ } catch (_err) {
27
+ return undefined;
28
+ }
29
+ }
30
+
31
+ // The jar names a component was read from, without the extension.
32
+ function jarStems(component) {
33
+ return (component.properties || [])
34
+ .filter((property) => property.name === "internal:SrcFile")
35
+ .map((property) => basename(String(property.value || "")))
36
+ .filter((name) => name.toLowerCase().endsWith(".jar"))
37
+ .map((name) => name.slice(0, -".jar".length));
38
+ }
39
+
40
+ function isJarSourced(component) {
41
+ return jarStems(component).length > 0;
42
+ }
43
+
44
+ // Whether a jar scan guessed the coordinates rather than reading them from the
45
+ // jar's Maven descriptor. A jar with a descriptor names its own artifact, even
46
+ // when that artifact is spelled `<group>.<name>` like a staged copy.
47
+ function hasGuessedIdentity(component) {
48
+ const identities = [component.evidence?.identity || []].flat();
49
+ return !identities.some(
50
+ (identity) =>
51
+ (identity?.confidence ?? 0) >= DESCRIPTOR_CONFIDENCE ||
52
+ (identity?.methods || []).some(
53
+ (method) => (method?.confidence ?? 0) >= DESCRIPTOR_CONFIDENCE,
54
+ ),
55
+ );
56
+ }
57
+
58
+ // A classifier or a type other than jar names a different artifact of the same
59
+ // coordinates, which is not a duplicate.
60
+ function isPlainJar(component) {
61
+ const purl = parsedPurl(component);
62
+ if (!purl) {
63
+ return false;
64
+ }
65
+ const qualifiers = purl.qualifiers || {};
66
+ return (
67
+ !qualifiers.classifier && (!qualifiers.type || qualifiers.type === "jar")
68
+ );
69
+ }
70
+
71
+ // The Scala binary versions a component was built for: the suffix its name
72
+ // keeps, or the compiler versions a build tool recorded. Empty for a library
73
+ // that is not a Scala artifact.
74
+ function binaryVersionsOf(component) {
75
+ const suffixVersion = scalaCoordinateOfPurl(component.purl)?.binaryVersion;
76
+ return new Set(
77
+ suffixVersion ? [suffixVersion] : compilerVersionsOf(component),
78
+ );
79
+ }
80
+
81
+ // Two spellings name one artifact only when they were built for the same Scala
82
+ // binary version, or both for none. `kafka_2.12` and `kafka_2.13` share the
83
+ // normalized coordinates but are different artifacts.
84
+ function sameBinaryVersion(a, b) {
85
+ const left = binaryVersionsOf(a);
86
+ const right = binaryVersionsOf(b);
87
+ if (!left.size || !right.size) {
88
+ return !left.size && !right.size;
89
+ }
90
+ return [...left].some((version) => right.has(version));
91
+ }
92
+
93
+ // Lower is better. A component a build tool reported outranks one a jar scan
94
+ // named; then the name without a `<group>.` prefix, then the purl that names
95
+ // its repository, then the shorter purl, then the lexicographically first, so
96
+ // the choice never depends on the order of the BOM.
97
+ function rank(component) {
98
+ return [
99
+ isJarSourced(component) ? 1 : 0,
100
+ component.name?.startsWith(`${component.group}.`) ? 1 : 0,
101
+ component.purl.includes("repository_url=") ? 0 : 1,
102
+ component.purl.length,
103
+ component.purl,
104
+ ];
105
+ }
106
+
107
+ function isBetter(candidate, component) {
108
+ const a = rank(candidate);
109
+ const b = rank(component);
110
+ for (let i = 0; i < a.length; i++) {
111
+ if (a[i] !== b[i]) {
112
+ return a[i] < b[i];
113
+ }
114
+ }
115
+ return false;
116
+ }
117
+
118
+ function best(components) {
119
+ let chosen;
120
+ for (const component of components) {
121
+ if (!chosen || isBetter(component, chosen)) {
122
+ chosen = component;
123
+ }
124
+ }
125
+ return chosen;
126
+ }
127
+
128
+ function refOf(component) {
129
+ return component["bom-ref"] || component.purl;
130
+ }
131
+
132
+ // The file names sbt-native-packager gives a staged copy of a library,
133
+ // without the version: `<group>.<artifact>` with the artifact as published,
134
+ // once for each Scala binary version it was built for, and once as named,
135
+ // since a module of the build itself is staged without the suffix when it
136
+ // turns cross paths off.
137
+ function stagedStems(component) {
138
+ return [
139
+ ...new Set([
140
+ `${component.group}.${component.name}`,
141
+ ...compilerVersionsOf(component).map(
142
+ (version) =>
143
+ `${component.group}.${publishedArtifactId({
144
+ name: component.name,
145
+ properties: [{ name: COMPILER_VERSION_PROPERTY, value: version }],
146
+ })}`,
147
+ ),
148
+ ]),
149
+ ];
150
+ }
151
+
152
+ // The listed libraries a staged file name can be a copy of, with the version
153
+ // the name carries: every split of the name at a hyphen whose left side is the
154
+ // staged stem of a library.
155
+ function stagedOwners(stem, ownersByStem) {
156
+ const found = [];
157
+ for (
158
+ let index = stem.indexOf("-");
159
+ index > 0;
160
+ index = stem.indexOf("-", index + 1)
161
+ ) {
162
+ const owners = ownersByStem.get(stem.slice(0, index));
163
+ if (owners) {
164
+ found.push({ owners, version: stem.slice(index + 1) });
165
+ }
166
+ }
167
+ return found;
168
+ }
169
+
170
+ function rewriteReferences(dependencies, refMap) {
171
+ if (!refMap.size) {
172
+ return dependencies;
173
+ }
174
+ const rewritten = (dependencies || []).map((dependency) => {
175
+ const ref = refMap.get(dependency.ref) || dependency.ref;
176
+ return {
177
+ ...dependency,
178
+ ref,
179
+ ...(dependency.dependsOn
180
+ ? {
181
+ dependsOn: [
182
+ ...new Set(
183
+ dependency.dependsOn.map(
184
+ (dependsOn) => refMap.get(dependsOn) || dependsOn,
185
+ ),
186
+ ),
187
+ ].filter((dependsOn) => dependsOn !== ref),
188
+ }
189
+ : {}),
190
+ };
191
+ });
192
+ return mergeDependencies([], rewritten);
193
+ }
194
+
195
+ /**
196
+ * Collapse the components that stand for one Scala library.
197
+ *
198
+ * A build tool such as sbt reports a library as `group:name@version` with the
199
+ * Scala binary suffix moved into `cdx:scala:compilerVersion`. The jars a scan
200
+ * finds on disk name the same library again, and not in the same way: with the
201
+ * suffix (`cats-core_3`), without a repository, or, for a jar without a Maven
202
+ * descriptor, only as the staged file name `<group>.<artifact>-<version>.jar`,
203
+ * which a filename-based guess splits at the wrong dot
204
+ * (`pkg:maven/cpg2-protos/io.appthreat.cpg2-protos_3`). Each of those is merged
205
+ * into the component the build tool reported. A staged jar of another version
206
+ * of a reported library, such as a stale build, keeps its own component but is
207
+ * renamed to the coordinates the reported library has.
208
+ *
209
+ * Spellings of the same coordinates merge only when they were built for the
210
+ * same Scala binary version, so the `_2.12` and `_2.13` artifacts of one
211
+ * library stay two components. Components that no reported library accounts
212
+ * for are left as they are.
213
+ *
214
+ * @param {Object[]} components BOM components
215
+ * @param {Object[]} dependencies BOM dependencies
216
+ * @returns {{components: Object[], dependencies: Object[], purlMap: Map<string, string>}}
217
+ * The collapsed components, the dependencies with references to merged
218
+ * components pointed at the component that remains, and the purl each
219
+ * merged or renamed component now has, keyed by the purl it had
220
+ */
221
+ export function mergeScalaDuplicateComponents(components, dependencies) {
222
+ const purlMap = new Map();
223
+ const candidates = (components || []).filter(
224
+ (component) =>
225
+ component?.purl?.startsWith("pkg:maven/") &&
226
+ isPlainJar(component) &&
227
+ component.group &&
228
+ component.version,
229
+ );
230
+ if (candidates.length < 2) {
231
+ return { components, dependencies, purlMap };
232
+ }
233
+ const byKey = new Map();
234
+ const ownersByStem = new Map();
235
+ for (const component of candidates) {
236
+ const key = scalaCoordinateOfPurl(component.purl)?.key;
237
+ if (key) {
238
+ byKey.set(key, [...(byKey.get(key) || []), component]);
239
+ }
240
+ for (const stem of stagedStems(component)) {
241
+ ownersByStem.set(stem, [...(ownersByStem.get(stem) || []), component]);
242
+ }
243
+ }
244
+ // Which component each one is a duplicate of.
245
+ const duplicateOf = new Map();
246
+ const repoints = new Map();
247
+ for (const component of candidates) {
248
+ const matches = new Set();
249
+ // The same coordinates, spelled with or without the Scala suffix, with or
250
+ // without a repository.
251
+ for (const other of byKey.get(scalaCoordinateOfPurl(component.purl)?.key) ||
252
+ []) {
253
+ if (other !== component && sameBinaryVersion(component, other)) {
254
+ matches.add(other);
255
+ }
256
+ }
257
+ // The staged file name of another listed library, whatever group and name
258
+ // the guess made of it. A jar that names itself in its Maven descriptor is
259
+ // the artifact it says it is.
260
+ if (isJarSourced(component) && hasGuessedIdentity(component)) {
261
+ for (const stem of jarStems(component)) {
262
+ for (const { owners, version } of stagedOwners(stem, ownersByStem)) {
263
+ const sameVersion = owners.filter(
264
+ (owner) => owner !== component && owner.version === version,
265
+ );
266
+ if (sameVersion.length) {
267
+ for (const owner of sameVersion) {
268
+ matches.add(owner);
269
+ }
270
+ continue;
271
+ }
272
+ // Another version of a library a build tool reported, when the guess
273
+ // agrees on it. A version that extends a known one
274
+ // (`4.1.100.Final-linux-x86_64`) can as well be that version with a
275
+ // classifier, so it is left alone.
276
+ const reportedOwners = owners.filter(
277
+ (owner) => owner !== component && !isJarSourced(owner),
278
+ );
279
+ const extendsKnown = owners.some((owner) =>
280
+ version.startsWith(`${owner.version}-`),
281
+ );
282
+ if (
283
+ reportedOwners.length &&
284
+ version === component.version &&
285
+ /^\d/.test(version) &&
286
+ !extendsKnown
287
+ ) {
288
+ const owner = best(reportedOwners);
289
+ const known = repoints.get(component);
290
+ if (!known || isBetter(owner, known)) {
291
+ repoints.set(component, owner);
292
+ }
293
+ }
294
+ }
295
+ }
296
+ }
297
+ const target = best(
298
+ [...matches].filter((other) => isBetter(other, component)),
299
+ );
300
+ if (target) {
301
+ duplicateOf.set(component, target);
302
+ }
303
+ }
304
+ // A chain of merges never carries a component past one built for another
305
+ // Scala binary version.
306
+ const root = (component) => {
307
+ let current = component;
308
+ while (duplicateOf.has(current)) {
309
+ const next = duplicateOf.get(current);
310
+ if (current !== component && !sameBinaryVersion(component, next)) {
311
+ break;
312
+ }
313
+ current = next;
314
+ }
315
+ return current;
316
+ };
317
+ const refMap = new Map();
318
+ const survivors = new Set(components);
319
+ for (const [component] of duplicateOf) {
320
+ const target = root(component);
321
+ const duplicate = { ...component };
322
+ const targetRef = refOf(target);
323
+ if (refOf(component) && targetRef && refOf(component) !== targetRef) {
324
+ refMap.set(refOf(component), targetRef);
325
+ }
326
+ if (component.purl !== target.purl) {
327
+ purlMap.set(component.purl, target.purl);
328
+ }
329
+ duplicate.purl = target.purl;
330
+ duplicate["bom-ref"] = target["bom-ref"];
331
+ trimComponents([target, duplicate]);
332
+ survivors.delete(component);
333
+ }
334
+ for (const [component, owner] of repoints) {
335
+ if (survivors.has(component)) {
336
+ repointToAnchor(component, root(owner), refMap, purlMap);
337
+ }
338
+ }
339
+ // A component merged into one that was renamed afterwards follows it.
340
+ resolveChains(refMap);
341
+ resolveChains(purlMap);
342
+ // Repointed components can now spell the same coordinates twice.
343
+ return {
344
+ components: trimComponents([...survivors]),
345
+ dependencies: rewriteReferences(dependencies, refMap),
346
+ purlMap,
347
+ };
348
+ }
349
+
350
+ function resolveChains(map) {
351
+ for (const [key, value] of map) {
352
+ let current = value;
353
+ const seen = new Set([key]);
354
+ while (map.has(current) && !seen.has(current)) {
355
+ seen.add(current);
356
+ current = map.get(current);
357
+ }
358
+ map.set(key, current);
359
+ }
360
+ }
361
+
362
+ // Give a staged jar of another version the group, name and purl shape the
363
+ // reported library has, so it is the same library at an older or newer version
364
+ // and not a differently named one.
365
+ function repointToAnchor(component, anchor, refMap, purlMap) {
366
+ const anchorPurl = parsedPurl(anchor);
367
+ if (!anchorPurl) {
368
+ return;
369
+ }
370
+ // The repository the reported version came from says nothing about where
371
+ // this one came from.
372
+ const { repository_url: _repository, ...qualifiers } =
373
+ anchorPurl.qualifiers || {};
374
+ const purl = mavenPurl(
375
+ anchor.group,
376
+ anchorPurl.name,
377
+ component.version,
378
+ qualifiers,
379
+ );
380
+ if (!purl) {
381
+ return;
382
+ }
383
+ const previousRef = refOf(component);
384
+ purlMap.set(component.purl, purl);
385
+ component.group = anchor.group;
386
+ component.name = anchor.name;
387
+ component.purl = purl;
388
+ component["bom-ref"] = decodeURIComponent(purl);
389
+ const known = new Set(compilerVersionsOf(component));
390
+ component.properties = [
391
+ ...(component.properties || []),
392
+ ...(anchor.properties || []).filter(
393
+ (property) =>
394
+ property.name === COMPILER_VERSION_PROPERTY &&
395
+ !known.has(property.value),
396
+ ),
397
+ ];
398
+ if (previousRef && previousRef !== component["bom-ref"]) {
399
+ refMap.set(previousRef, component["bom-ref"]);
400
+ }
401
+ }
402
+
403
+ /**
404
+ * Key the jar namespace map by the purls the components have after
405
+ * {@link mergeScalaDuplicateComponents}, so a merged or renamed jar still
406
+ * finds its namespaces. A purl that already has an entry keeps it, with the
407
+ * namespaces of the merged entry added.
408
+ *
409
+ * @param {Object} mapping Jar namespace map keyed by purl
410
+ * @param {Map<string, string>} purlMap New purl keyed by old purl
411
+ * @returns {Object} The re-keyed map
412
+ */
413
+ export function rekeyNamespaceMapping(mapping, purlMap) {
414
+ if (!mapping || !purlMap?.size) {
415
+ return mapping;
416
+ }
417
+ const rekeyed = { ...mapping };
418
+ for (const [oldPurl, newPurl] of purlMap) {
419
+ const entry = rekeyed[oldPurl];
420
+ if (!entry || oldPurl === newPurl) {
421
+ continue;
422
+ }
423
+ delete rekeyed[oldPurl];
424
+ const existing = rekeyed[newPurl];
425
+ if (!existing) {
426
+ rekeyed[newPurl] = entry;
427
+ continue;
428
+ }
429
+ rekeyed[newPurl] = {
430
+ ...existing,
431
+ namespaces: [
432
+ ...new Set([
433
+ ...(existing.namespaces || []),
434
+ ...(entry.namespaces || []),
435
+ ]),
436
+ ],
437
+ };
438
+ }
439
+ return rekeyed;
440
+ }
@@ -30,6 +30,7 @@ import {
30
30
  prefetchedResponse,
31
31
  prefetchJson,
32
32
  } from "./fetchBatch.js";
33
+ import { mavenCentralFetchUrl } from "./mavenCentralMirror.js";
33
34
  import { canonicalPurlFromLooseString } from "./purl.js";
34
35
 
35
36
  /** Raised when a caller omits a registry helper that the purl type requires. */
@@ -105,9 +106,48 @@ function inferGitOperation(args = []) {
105
106
  return "command";
106
107
  }
107
108
 
109
+ let gitRedirectRefusalReported = false;
110
+
111
+ registerRunReset("source:git-redirect-refusal", () => {
112
+ gitRedirectRefusalReported = false;
113
+ });
114
+
115
+ /**
116
+ * Determine whether git must refuse HTTP redirects. A git host allowlist is
117
+ * checked against the URL cdxgen is given, and git would otherwise follow
118
+ * the server's redirect on its first request to a host the allowlist never
119
+ * saw. Secure mode refuses redirects in the HTTP client too.
120
+ *
121
+ * @returns {boolean} true when a git host allowlist or secure mode applies
122
+ */
123
+ export function gitRedirectsRefused() {
124
+ return isSecureMode || getAllowedHosts().length > 0;
125
+ }
126
+
127
+ /**
128
+ * Determine whether a failed git command stopped at an HTTP redirect.
129
+ *
130
+ * @param {string|undefined} stderr git error output
131
+ * @returns {boolean} true when git reports a 3xx response
132
+ */
133
+ function isGitRedirectRefusal(stderr) {
134
+ if (typeof stderr !== "string") {
135
+ return false;
136
+ }
137
+ const marker = "The requested URL returned error: 30";
138
+ const index = stderr.indexOf(marker);
139
+ return index !== -1 && "12378".includes(stderr[index + marker.length]);
140
+ }
141
+
108
142
  /**
109
143
  * Execute git with hardened defaults.
110
144
  *
145
+ * Every call runs with command-scope settings that keep the repository from
146
+ * running fsmonitor hooks or being opened as a bare repository. While a git
147
+ * host allowlist or secure mode applies, git also refuses HTTP redirects, so
148
+ * an allowed host cannot send a clone or ls-remote to a host the allowlist
149
+ * does not name.
150
+ *
111
151
  * @param {string[]} args git arguments
112
152
  * @param {Object} options command options
113
153
  * @param {string|undefined} options.cwd working directory
@@ -119,15 +159,23 @@ function inferGitOperation(args = []) {
119
159
  export function hardenedGitCommand(args, options = {}) {
120
160
  const gitOperation = inferGitOperation(args);
121
161
  const gitAllowProtocol = getGitAllowProtocol();
162
+ const refuseRedirects = gitRedirectsRefused();
163
+ const commandConfig = [
164
+ ["core.fsmonitor", "false"],
165
+ ["safe.bareRepository", "explicit"],
166
+ ];
167
+ if (refuseRedirects) {
168
+ commandConfig.push(["http.followRedirects", "false"]);
169
+ }
122
170
  const envConfigs = {
123
- GIT_CONFIG_COUNT: "2",
124
- GIT_CONFIG_KEY_0: "core.fsmonitor",
125
- GIT_CONFIG_VALUE_0: "false",
126
- GIT_CONFIG_KEY_1: "safe.bareRepository",
127
- GIT_CONFIG_VALUE_1: "explicit",
171
+ GIT_CONFIG_COUNT: String(commandConfig.length),
128
172
  GIT_NO_LAZY_FETCH: "1",
129
173
  GIT_TERMINAL_PROMPT: "0",
130
174
  };
175
+ commandConfig.forEach(([key, value], index) => {
176
+ envConfigs[`GIT_CONFIG_KEY_${index}`] = key;
177
+ envConfigs[`GIT_CONFIG_VALUE_${index}`] = value;
178
+ });
131
179
  if (options.noRepository) {
132
180
  // ls-remote works without a repository. Pointing GIT_DIR at a path that
133
181
  // does not exist stops git from discovering one in the working directory.
@@ -146,7 +194,7 @@ export function hardenedGitCommand(args, options = {}) {
146
194
  ...envConfigs,
147
195
  GIT_ALLOW_PROTOCOL: gitAllowProtocol,
148
196
  };
149
- return safeSpawnSync("git", args, {
197
+ const result = safeSpawnSync("git", args, {
150
198
  cdxgenActivity: {
151
199
  blockedReason: `Dry run mode blocks git ${gitOperation} operations.`,
152
200
  gitOperation,
@@ -159,6 +207,18 @@ export function hardenedGitCommand(args, options = {}) {
159
207
  cwd: options.cwd,
160
208
  env,
161
209
  });
210
+ if (
211
+ refuseRedirects &&
212
+ !gitRedirectRefusalReported &&
213
+ result?.status !== 0 &&
214
+ isGitRedirectRefusal(result?.stderr)
215
+ ) {
216
+ gitRedirectRefusalReported = true;
217
+ console.warn(
218
+ "A Git server answered with a redirect, which cdxgen does not follow while CDXGEN_GIT_ALLOWED_HOSTS, CDXGEN_SERVER_ALLOWED_HOSTS or secure mode is in effect. Use the repository's current URL instead.",
219
+ );
220
+ }
221
+ return result;
162
222
  }
163
223
 
164
224
  function normalizeTagName(tagName) {
@@ -795,6 +855,48 @@ export function getGitRemoteHost(remote) {
795
855
  return host.toLowerCase();
796
856
  }
797
857
 
858
+ /**
859
+ * Remove credentials from git output before it is logged. Every URL in the
860
+ * text loses its user name and password, which git copies into its error
861
+ * messages from the remote it was given.
862
+ *
863
+ * @param {string|undefined} text Output of a git command
864
+ * @param {string|undefined} repoUrl Remote the command was given
865
+ * @returns {string|undefined} Output with credentials replaced by ***
866
+ */
867
+ export function redactGitOutput(text, repoUrl) {
868
+ if (!text || typeof text !== "string") {
869
+ return text;
870
+ }
871
+ let redacted = text;
872
+ if (repoUrl && typeof repoUrl === "string") {
873
+ redacted = redacted.split(repoUrl).join(sanitizeRemoteUrlForLogs(repoUrl));
874
+ }
875
+ let from = 0;
876
+ while (from < redacted.length) {
877
+ const schemeEnd = redacted.indexOf("://", from);
878
+ if (schemeEnd === -1) {
879
+ break;
880
+ }
881
+ const authorityStart = schemeEnd + 3;
882
+ let authorityEnd = authorityStart;
883
+ while (
884
+ authorityEnd < redacted.length &&
885
+ !"/?#'\"<> \t\r\n".includes(redacted[authorityEnd])
886
+ ) {
887
+ authorityEnd++;
888
+ }
889
+ const at = redacted.lastIndexOf("@", authorityEnd - 1);
890
+ if (at >= authorityStart) {
891
+ redacted = `${redacted.slice(0, authorityStart)}***:***${redacted.slice(at)}`;
892
+ from = authorityStart + "***:***".length;
893
+ } else {
894
+ from = authorityEnd;
895
+ }
896
+ }
897
+ return redacted;
898
+ }
899
+
798
900
  /**
799
901
  * Clone a git repository into a temporary directory.
800
902
  *
@@ -859,8 +961,11 @@ export function gitClone(repoUrl, branch = null) {
859
961
  `Cloning Repo${branch ? ` with branch ${branch}` : ""} to ${tempDir}`,
860
962
  );
861
963
  const result = hardenedGitCommand(gitArgs);
862
- if (result.status !== 0) {
863
- console.error(result.stderr);
964
+ if (result.status !== 0 || result.error) {
965
+ console.error(redactGitOutput(result.stderr, repoUrl));
966
+ // The directory was created by this call, so it is always safe to remove.
967
+ safeRmSync(tempDir, { recursive: true, force: true });
968
+ throw new Error("Git clone failed.");
864
969
  }
865
970
 
866
971
  return tempDir;
@@ -1588,6 +1693,7 @@ export async function resolveGitUrlFromPurl(purlString, helpers = {}) {
1588
1693
  break;
1589
1694
  }
1590
1695
  const mavenCentralUrl =
1696
+ mavenCentralFetchUrl() ||
1591
1697
  readEnvironmentVariable("MAVEN_CENTRAL_URL") ||
1592
1698
  "https://repo1.maven.org/maven2/";
1593
1699
  registry = mavenCentralUrl.endsWith("/")