@cdxgen/cdxgen 0.0.1 → 13.0.1

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 (722) hide show
  1. package/README.md +921 -87
  2. package/bin/audit.js +239 -0
  3. package/bin/cdxgen.js +2335 -0
  4. package/bin/convert.js +220 -0
  5. package/bin/evinse.js +353 -0
  6. package/bin/hbom.js +504 -0
  7. package/bin/repl.js +2224 -0
  8. package/bin/sign.js +195 -0
  9. package/bin/tracebom.js +303 -0
  10. package/bin/validate.js +268 -0
  11. package/bin/verify.js +189 -0
  12. package/data/README.md +307 -0
  13. package/data/bom-1.4.schema.json +1605 -0
  14. package/data/bom-1.5.schema.json +3660 -0
  15. package/data/bom-1.6.schema.json +5511 -0
  16. package/data/bom-1.7.schema.json +6700 -0
  17. package/data/cbomosdb-queries.json +68 -0
  18. package/data/component-tags.json +339 -0
  19. package/data/container-knowledge-index.json +125 -0
  20. package/data/cosdb-queries.json +17 -0
  21. package/data/crypto-oid.json +1998 -0
  22. package/data/cryptography-defs.json +3793 -0
  23. package/data/cryptography-defs.schema.json +576 -0
  24. package/data/cyclonedx-2.0-bundled.schema.json +7182 -0
  25. package/data/frameworks-list.json +219 -0
  26. package/data/glibc-stdlib.json +117 -0
  27. package/data/gtfobins-index.json +6296 -0
  28. package/data/helpers/init.gradle +71 -0
  29. package/data/jsf-0.82.schema.json +211 -0
  30. package/data/known-licenses.json +82 -0
  31. package/data/lic-mapping.json +338 -0
  32. package/data/license-aliases.json +6624 -0
  33. package/data/license-db.json +39059 -0
  34. package/data/license-deprecations.json +302 -0
  35. package/data/lolbas-index.json +150 -0
  36. package/data/predictive-audit-allowlist.json +11 -0
  37. package/data/pypi-pkg-aliases.json +1199 -0
  38. package/data/python-stdlib.json +308 -0
  39. package/data/queries-darwin.json +193 -0
  40. package/data/queries-win.json +257 -0
  41. package/data/queries.json +268 -0
  42. package/data/ruby-known-modules.json +281 -0
  43. package/data/rules/ai-agent-governance.yaml +323 -0
  44. package/data/rules/ai-bom.yaml +268 -0
  45. package/data/rules/ai-oversight.yaml +186 -0
  46. package/data/rules/ai-provenance.yaml +92 -0
  47. package/data/rules/asar-archives.yaml +150 -0
  48. package/data/rules/cbom-security.yaml +165 -0
  49. package/data/rules/chrome-extensions.yaml +248 -0
  50. package/data/rules/ci-permissions.yaml +802 -0
  51. package/data/rules/container-risk.yaml +353 -0
  52. package/data/rules/dependency-sources.yaml +236 -0
  53. package/data/rules/golem-go.yaml +229 -0
  54. package/data/rules/hbom-compliance.yaml +325 -0
  55. package/data/rules/hbom-performance.yaml +307 -0
  56. package/data/rules/hbom-security.yaml +248 -0
  57. package/data/rules/host-topology.yaml +165 -0
  58. package/data/rules/mcp-servers.yaml +388 -0
  59. package/data/rules/obom-runtime.yaml +1776 -0
  60. package/data/rules/package-integrity.yaml +364 -0
  61. package/data/rules/rootfs-hardening.yaml +179 -0
  62. package/data/rules/vscode-extensions.yaml +237 -0
  63. package/data/spdx-export.schema.json +6794 -0
  64. package/data/spdx-license-list.json +7449 -0
  65. package/data/spdx-licenses.json +759 -0
  66. package/data/spdx.schema.json +819 -0
  67. package/data/templates/README.md +3 -0
  68. package/data/templates/asvs-4.0.3.cdx.json +2943 -0
  69. package/data/templates/asvs-5.0.cdx.json +3046 -0
  70. package/data/templates/bsimm-v13.cdx.json +1008 -0
  71. package/data/templates/masvs-2.0.0.cdx.json +225 -0
  72. package/data/templates/nist-ssdf-1.1.cdx.json +828 -0
  73. package/data/templates/pcissc-secure-slc-1.1.cdx.json +1027 -0
  74. package/data/templates/scvs-1.0.0.cdx.json +813 -0
  75. package/data/templates/ssaf-DRAFT-2023-11.cdx.json +127 -0
  76. package/data/vendor-alias.json +41967 -0
  77. package/data/wrapdb-releases.json +4227 -0
  78. package/index.cjs +15 -0
  79. package/lib/audit/index.js +2800 -0
  80. package/lib/audit/progress.js +114 -0
  81. package/lib/audit/reporters.js +937 -0
  82. package/lib/audit/scoring.js +560 -0
  83. package/lib/audit/targets.js +798 -0
  84. package/lib/cli/bomAssembly.js +1882 -0
  85. package/lib/cli/cliOptions.js +543 -0
  86. package/lib/cli/index.js +2759 -0
  87. package/lib/cli/jsBom.js +2087 -0
  88. package/lib/cli/jvmBom.js +1858 -0
  89. package/lib/cli/managedBom.js +2083 -0
  90. package/lib/cli/nativeBom.js +2125 -0
  91. package/lib/core/activity.js +1087 -0
  92. package/lib/core/env.js +719 -0
  93. package/lib/core/fs.js +1058 -0
  94. package/lib/core/httpClient.js +730 -0
  95. package/lib/core/logger.js +280 -0
  96. package/lib/core/parallel.js +323 -0
  97. package/lib/core/paths.js +70 -0
  98. package/lib/core/projectConfig.js +122 -0
  99. package/lib/core/propertySanitizer.js +174 -0
  100. package/lib/core/spdx.js +5 -0
  101. package/lib/core/state.js +59 -0
  102. package/lib/core/text.js +207 -0
  103. package/lib/core/ui.js +920 -0
  104. package/lib/core/urls.js +84 -0
  105. package/lib/ecosystems/asarutils.js +1636 -0
  106. package/lib/ecosystems/bunutils.js +402 -0
  107. package/lib/ecosystems/caxa.js +77 -0
  108. package/lib/ecosystems/chromextutils.js +1174 -0
  109. package/lib/ecosystems/cmakeResolver.js +587 -0
  110. package/lib/ecosystems/cppEvidence.js +305 -0
  111. package/lib/ecosystems/denoutils.js +1094 -0
  112. package/lib/ecosystems/dotnetutils.js +132 -0
  113. package/lib/ecosystems/ecosystems.js +2772 -0
  114. package/lib/ecosystems/golem.js +1807 -0
  115. package/lib/ecosystems/gradleutils.js +1048 -0
  116. package/lib/ecosystems/jsEvidence.js +317 -0
  117. package/lib/ecosystems/npmutils.js +586 -0
  118. package/lib/ecosystems/parsers-bazel.js +875 -0
  119. package/lib/ecosystems/parsers-dotnet.js +1430 -0
  120. package/lib/ecosystems/parsers-gleam.js +302 -0
  121. package/lib/ecosystems/parsers-go.js +818 -0
  122. package/lib/ecosystems/parsers-js.js +4222 -0
  123. package/lib/ecosystems/parsers-jvm.js +948 -0
  124. package/lib/ecosystems/parsers-misc.js +3191 -0
  125. package/lib/ecosystems/parsers-python.js +2070 -0
  126. package/lib/ecosystems/parsers-rust.js +1294 -0
  127. package/lib/ecosystems/parsers-zig.js +861 -0
  128. package/lib/ecosystems/pep770.js +341 -0
  129. package/lib/ecosystems/pylockutils.js +427 -0
  130. package/lib/ecosystems/pythonutils.js +1281 -0
  131. package/lib/ecosystems/registryProvenance.js +1003 -0
  132. package/lib/ecosystems/remote/huggingface.js +1343 -0
  133. package/lib/ecosystems/rubyutils.js +1629 -0
  134. package/lib/ecosystems/rusi.js +820 -0
  135. package/lib/ecosystems/sbtutils.js +972 -0
  136. package/lib/ecosystems/tea.js +607 -0
  137. package/lib/ecosystems/utils.js +583 -0
  138. package/lib/ecosystems/zigResolver.js +410 -0
  139. package/lib/evinser/db.js +145 -0
  140. package/lib/evinser/evinser.js +2362 -0
  141. package/lib/evinser/scalasem.js +65 -0
  142. package/lib/evinser/swiftsem.js +767 -0
  143. package/lib/helpers/annotationFormatter.js +84 -0
  144. package/lib/helpers/bomSigner.js +312 -0
  145. package/lib/helpers/exportUtils.js +160 -0
  146. package/lib/helpers/remote/dependency-track.js +117 -0
  147. package/lib/helpers/versutils.js +202 -0
  148. package/lib/helpers/vsixutils.js +1069 -0
  149. package/lib/inventory/agentFormulationParser.js +322 -0
  150. package/lib/inventory/aiCollector.js +2140 -0
  151. package/lib/inventory/aiInventory.js +414 -0
  152. package/lib/inventory/aiModelVariants.js +121 -0
  153. package/lib/inventory/aiOversightCollector.js +661 -0
  154. package/lib/inventory/aiProvenanceCollector.js +822 -0
  155. package/lib/inventory/analyzer.js +6089 -0
  156. package/lib/inventory/analyzerScope.js +807 -0
  157. package/lib/inventory/astWorker.js +20 -0
  158. package/lib/inventory/atomUtils.js +1092 -0
  159. package/lib/inventory/auditCategories.js +192 -0
  160. package/lib/inventory/bomUtils.js +369 -0
  161. package/lib/inventory/cacheCommands.js +182 -0
  162. package/lib/inventory/cacheDir.js +104 -0
  163. package/lib/inventory/cbomutils.js +590 -0
  164. package/lib/inventory/cdxrs.js +434 -0
  165. package/lib/inventory/ciParsers/azurePipelines.js +295 -0
  166. package/lib/inventory/ciParsers/circleCi.js +286 -0
  167. package/lib/inventory/ciParsers/common.js +24 -0
  168. package/lib/inventory/ciParsers/githubActions.js +2434 -0
  169. package/lib/inventory/ciParsers/gitlabCi.js +213 -0
  170. package/lib/inventory/ciParsers/jenkins.js +180 -0
  171. package/lib/inventory/citations.js +234 -0
  172. package/lib/inventory/communityAiConfigParser.js +756 -0
  173. package/lib/inventory/containerRisk.js +204 -0
  174. package/lib/inventory/cryptoAlgorithmFamily.js +258 -0
  175. package/lib/inventory/deps.js +807 -0
  176. package/lib/inventory/depsUtils.js +588 -0
  177. package/lib/inventory/display.js +2128 -0
  178. package/lib/inventory/dosai.js +601 -0
  179. package/lib/inventory/dosaiParsers.js +154 -0
  180. package/lib/inventory/dynamic.js +145 -0
  181. package/lib/inventory/envcontext.js +1793 -0
  182. package/lib/inventory/evidenceUtils.js +774 -0
  183. package/lib/inventory/fetchBatch.js +779 -0
  184. package/lib/inventory/fetchRate.js +255 -0
  185. package/lib/inventory/forgeEnricher.js +300 -0
  186. package/lib/inventory/formulationParsers.js +422 -0
  187. package/lib/inventory/gtfobins.js +339 -0
  188. package/lib/inventory/hbom.js +719 -0
  189. package/lib/inventory/hbomAnalysis.js +310 -0
  190. package/lib/inventory/hbomLoader.js +35 -0
  191. package/lib/inventory/hostTopology.js +835 -0
  192. package/lib/inventory/inventoryStats.js +100 -0
  193. package/lib/inventory/jsonLike.js +121 -0
  194. package/lib/inventory/licenseEnhancer.js +918 -0
  195. package/lib/inventory/lolbas.js +285 -0
  196. package/lib/inventory/mcp.js +253 -0
  197. package/lib/inventory/mcpConfigParser.js +683 -0
  198. package/lib/inventory/mcpDiscovery.js +112 -0
  199. package/lib/inventory/mcpPinning.js +209 -0
  200. package/lib/inventory/osPackageResolver.js +493 -0
  201. package/lib/inventory/osinfo.js +383 -0
  202. package/lib/inventory/osqueryTransform.js +274 -0
  203. package/lib/inventory/plugins.js +466 -0
  204. package/lib/inventory/protobom.js +231 -0
  205. package/lib/inventory/protobomLoader.js +43 -0
  206. package/lib/inventory/provenanceUtils.js +224 -0
  207. package/lib/inventory/purl.js +749 -0
  208. package/lib/inventory/rustFormulationParser.js +339 -0
  209. package/lib/inventory/sbomDocument.js +340 -0
  210. package/lib/inventory/source.js +1488 -0
  211. package/lib/inventory/spdx.js +361 -0
  212. package/lib/inventory/spdxExpression.js +512 -0
  213. package/lib/inventory/spdxUtils.js +107 -0
  214. package/lib/inventory/table.js +267 -0
  215. package/lib/inventory/traceRunner.js +439 -0
  216. package/lib/inventory/unicodeScan.js +147 -0
  217. package/lib/managers/binary.js +3459 -0
  218. package/lib/managers/containerutils.js +125 -0
  219. package/lib/managers/docker.js +2145 -0
  220. package/lib/managers/dockerConnection.js +162 -0
  221. package/lib/managers/oci.js +704 -0
  222. package/lib/managers/piptree.js +267 -0
  223. package/lib/parsers/cmakeCache.js +199 -0
  224. package/lib/parsers/gguf.js +492 -0
  225. package/lib/parsers/gitAiNotes.js +233 -0
  226. package/lib/parsers/gitmodules.js +239 -0
  227. package/lib/parsers/htmlExtract.js +610 -0
  228. package/lib/parsers/huggingfaceManifest.js +551 -0
  229. package/lib/parsers/huggingfaceUtils.js +506 -0
  230. package/lib/parsers/iri.js +618 -0
  231. package/lib/parsers/npmrc.js +99 -0
  232. package/lib/parsers/ollama.js +101 -0
  233. package/lib/parsers/xml.js +841 -0
  234. package/lib/server/openapi.yaml +433 -0
  235. package/lib/server/server.js +616 -0
  236. package/lib/stages/postgen/annotator.js +977 -0
  237. package/lib/stages/postgen/auditBom.js +468 -0
  238. package/lib/stages/postgen/postgen.js +1239 -0
  239. package/lib/stages/postgen/ruleEngine.js +731 -0
  240. package/lib/stages/postgen/sortBom.js +195 -0
  241. package/lib/stages/postgen/spdxConverter.js +796 -0
  242. package/lib/stages/postgen/specVersionCompat.js +703 -0
  243. package/lib/stages/pregen/envAudit.js +388 -0
  244. package/lib/stages/pregen/pregen.js +637 -0
  245. package/lib/third-party/README.md +9 -0
  246. package/lib/third-party/arborist/CHANGELOG.md +1109 -0
  247. package/lib/third-party/arborist/LICENSE.md +20 -0
  248. package/lib/third-party/arborist/README.md +315 -0
  249. package/lib/third-party/arborist/lib/arborist/index.js +258 -0
  250. package/lib/third-party/arborist/lib/arborist/load-actual.js +605 -0
  251. package/lib/third-party/arborist/lib/arborist/load-virtual.js +300 -0
  252. package/lib/third-party/arborist/lib/bin-links.js +120 -0
  253. package/lib/third-party/arborist/lib/calc-dep-flags.js +130 -0
  254. package/lib/third-party/arborist/lib/case-insensitive-map.js +51 -0
  255. package/lib/third-party/arborist/lib/consistent-resolve.js +42 -0
  256. package/lib/third-party/arborist/lib/debug.js +50 -0
  257. package/lib/third-party/arborist/lib/dep-valid.js +190 -0
  258. package/lib/third-party/arborist/lib/edge.js +417 -0
  259. package/lib/third-party/arborist/lib/from-path.js +36 -0
  260. package/lib/third-party/arborist/lib/gather-dep-set.js +43 -0
  261. package/lib/third-party/arborist/lib/index.js +22 -0
  262. package/lib/third-party/arborist/lib/inventory.js +138 -0
  263. package/lib/third-party/arborist/lib/link.js +169 -0
  264. package/lib/third-party/arborist/lib/node.js +1673 -0
  265. package/lib/third-party/arborist/lib/npm-extension.js +45 -0
  266. package/lib/third-party/arborist/lib/override-resolves.js +11 -0
  267. package/lib/third-party/arborist/lib/override-set.js +319 -0
  268. package/lib/third-party/arborist/lib/package-extensions.js +289 -0
  269. package/lib/third-party/arborist/lib/printable.js +210 -0
  270. package/lib/third-party/arborist/lib/proc-log.js +30 -0
  271. package/lib/third-party/arborist/lib/realpath.js +100 -0
  272. package/lib/third-party/arborist/lib/relpath.js +4 -0
  273. package/lib/third-party/arborist/lib/shrinkwrap.js +1291 -0
  274. package/lib/third-party/arborist/lib/spec-from-lock.js +34 -0
  275. package/lib/third-party/arborist/lib/tree-check.js +165 -0
  276. package/lib/third-party/arborist/lib/validate-npm-package-name.js +107 -0
  277. package/lib/third-party/arborist/lib/version-from-tgz.js +51 -0
  278. package/lib/third-party/arborist/lib/yarn-lock.js +397 -0
  279. package/lib/validator/bomValidator.js +985 -0
  280. package/lib/validator/complianceEngine.js +241 -0
  281. package/lib/validator/complianceRules.js +1680 -0
  282. package/lib/validator/generated/runtime.mjs +17 -0
  283. package/lib/validator/generated/validate-1.6.mjs +21258 -0
  284. package/lib/validator/generated/validate-1.7.mjs +24803 -0
  285. package/lib/validator/generated/validate-2.0.mjs +22931 -0
  286. package/lib/validator/index.js +246 -0
  287. package/lib/validator/reporters/annotations.js +142 -0
  288. package/lib/validator/reporters/console.js +160 -0
  289. package/lib/validator/reporters/index.js +41 -0
  290. package/lib/validator/reporters/json.js +37 -0
  291. package/lib/validator/reporters/sarif.js +184 -0
  292. package/package.json +209 -26
  293. package/types/bin/audit.d.ts +3 -0
  294. package/types/bin/audit.d.ts.map +1 -0
  295. package/types/bin/cdxgen.d.ts +3 -0
  296. package/types/bin/cdxgen.d.ts.map +1 -0
  297. package/types/bin/convert.d.ts +3 -0
  298. package/types/bin/convert.d.ts.map +1 -0
  299. package/types/bin/evinse.d.ts +3 -0
  300. package/types/bin/evinse.d.ts.map +1 -0
  301. package/types/bin/hbom.d.ts +3 -0
  302. package/types/bin/hbom.d.ts.map +1 -0
  303. package/types/bin/repl.d.ts +3 -0
  304. package/types/bin/repl.d.ts.map +1 -0
  305. package/types/bin/sign.d.ts +3 -0
  306. package/types/bin/sign.d.ts.map +1 -0
  307. package/types/bin/tracebom.d.ts +3 -0
  308. package/types/bin/tracebom.d.ts.map +1 -0
  309. package/types/bin/validate.d.ts +14 -0
  310. package/types/bin/validate.d.ts.map +1 -0
  311. package/types/bin/verify.d.ts +3 -0
  312. package/types/bin/verify.d.ts.map +1 -0
  313. package/types/lib/audit/index.d.ts +153 -0
  314. package/types/lib/audit/index.d.ts.map +1 -0
  315. package/types/lib/audit/progress.d.ts +31 -0
  316. package/types/lib/audit/progress.d.ts.map +1 -0
  317. package/types/lib/audit/reporters.d.ts +62 -0
  318. package/types/lib/audit/reporters.d.ts.map +1 -0
  319. package/types/lib/audit/scoring.d.ts +36 -0
  320. package/types/lib/audit/scoring.d.ts.map +1 -0
  321. package/types/lib/audit/targets.d.ts +77 -0
  322. package/types/lib/audit/targets.d.ts.map +1 -0
  323. package/types/lib/cli/bomAssembly.d.ts +329 -0
  324. package/types/lib/cli/bomAssembly.d.ts.map +1 -0
  325. package/types/lib/cli/cliOptions.d.ts +156 -0
  326. package/types/lib/cli/cliOptions.d.ts.map +1 -0
  327. package/types/lib/cli/index.d.ts +107 -0
  328. package/types/lib/cli/index.d.ts.map +1 -0
  329. package/types/lib/cli/jsBom.d.ts +94 -0
  330. package/types/lib/cli/jsBom.d.ts.map +1 -0
  331. package/types/lib/cli/jvmBom.d.ts +54 -0
  332. package/types/lib/cli/jvmBom.d.ts.map +1 -0
  333. package/types/lib/cli/managedBom.d.ts +105 -0
  334. package/types/lib/cli/managedBom.d.ts.map +1 -0
  335. package/types/lib/cli/nativeBom.d.ts +143 -0
  336. package/types/lib/cli/nativeBom.d.ts.map +1 -0
  337. package/types/lib/core/activity.d.ts +178 -0
  338. package/types/lib/core/activity.d.ts.map +1 -0
  339. package/types/lib/core/env.d.ts +192 -0
  340. package/types/lib/core/env.d.ts.map +1 -0
  341. package/types/lib/core/fs.d.ts +158 -0
  342. package/types/lib/core/fs.d.ts.map +1 -0
  343. package/types/lib/core/httpClient.d.ts +149 -0
  344. package/types/lib/core/httpClient.d.ts.map +1 -0
  345. package/types/lib/core/logger.d.ts +50 -0
  346. package/types/lib/core/logger.d.ts.map +1 -0
  347. package/types/lib/core/parallel.d.ts +95 -0
  348. package/types/lib/core/parallel.d.ts.map +1 -0
  349. package/types/lib/core/paths.d.ts +36 -0
  350. package/types/lib/core/paths.d.ts.map +1 -0
  351. package/types/lib/core/projectConfig.d.ts +23 -0
  352. package/types/lib/core/projectConfig.d.ts.map +1 -0
  353. package/types/lib/core/propertySanitizer.d.ts +23 -0
  354. package/types/lib/core/propertySanitizer.d.ts.map +1 -0
  355. package/types/lib/core/spdx.d.ts +5 -0
  356. package/types/lib/core/spdx.d.ts.map +1 -0
  357. package/types/lib/core/state.d.ts +20 -0
  358. package/types/lib/core/state.d.ts.map +1 -0
  359. package/types/lib/core/text.d.ts +78 -0
  360. package/types/lib/core/text.d.ts.map +1 -0
  361. package/types/lib/core/ui.d.ts +87 -0
  362. package/types/lib/core/ui.d.ts.map +1 -0
  363. package/types/lib/core/urls.d.ts +43 -0
  364. package/types/lib/core/urls.d.ts.map +1 -0
  365. package/types/lib/ecosystems/asarutils.d.ts +71 -0
  366. package/types/lib/ecosystems/asarutils.d.ts.map +1 -0
  367. package/types/lib/ecosystems/bunutils.d.ts +38 -0
  368. package/types/lib/ecosystems/bunutils.d.ts.map +1 -0
  369. package/types/lib/ecosystems/caxa.d.ts +8 -0
  370. package/types/lib/ecosystems/caxa.d.ts.map +1 -0
  371. package/types/lib/ecosystems/chromextutils.d.ts +97 -0
  372. package/types/lib/ecosystems/chromextutils.d.ts.map +1 -0
  373. package/types/lib/ecosystems/cmakeResolver.d.ts +176 -0
  374. package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -0
  375. package/types/lib/ecosystems/cppEvidence.d.ts +35 -0
  376. package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -0
  377. package/types/lib/ecosystems/denoutils.d.ts +76 -0
  378. package/types/lib/ecosystems/denoutils.d.ts.map +1 -0
  379. package/types/lib/ecosystems/dotnetutils.d.ts +45 -0
  380. package/types/lib/ecosystems/dotnetutils.d.ts.map +1 -0
  381. package/types/lib/ecosystems/ecosystems.d.ts +279 -0
  382. package/types/lib/ecosystems/ecosystems.d.ts.map +1 -0
  383. package/types/lib/ecosystems/golem.d.ts +60 -0
  384. package/types/lib/ecosystems/golem.d.ts.map +1 -0
  385. package/types/lib/ecosystems/gradleutils.d.ts +139 -0
  386. package/types/lib/ecosystems/gradleutils.d.ts.map +1 -0
  387. package/types/lib/ecosystems/jsEvidence.d.ts +17 -0
  388. package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -0
  389. package/types/lib/ecosystems/npmutils.d.ts +183 -0
  390. package/types/lib/ecosystems/npmutils.d.ts.map +1 -0
  391. package/types/lib/ecosystems/parsers-bazel.d.ts +36 -0
  392. package/types/lib/ecosystems/parsers-bazel.d.ts.map +1 -0
  393. package/types/lib/ecosystems/parsers-dotnet.d.ts +116 -0
  394. package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -0
  395. package/types/lib/ecosystems/parsers-gleam.d.ts +33 -0
  396. package/types/lib/ecosystems/parsers-gleam.d.ts.map +1 -0
  397. package/types/lib/ecosystems/parsers-go.d.ts +92 -0
  398. package/types/lib/ecosystems/parsers-go.d.ts.map +1 -0
  399. package/types/lib/ecosystems/parsers-js.d.ts +242 -0
  400. package/types/lib/ecosystems/parsers-js.d.ts.map +1 -0
  401. package/types/lib/ecosystems/parsers-jvm.d.ts +100 -0
  402. package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -0
  403. package/types/lib/ecosystems/parsers-misc.d.ts +450 -0
  404. package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -0
  405. package/types/lib/ecosystems/parsers-python.d.ts +145 -0
  406. package/types/lib/ecosystems/parsers-python.d.ts.map +1 -0
  407. package/types/lib/ecosystems/parsers-rust.d.ts +56 -0
  408. package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -0
  409. package/types/lib/ecosystems/parsers-zig.d.ts +83 -0
  410. package/types/lib/ecosystems/parsers-zig.d.ts.map +1 -0
  411. package/types/lib/ecosystems/pep770.d.ts +38 -0
  412. package/types/lib/ecosystems/pep770.d.ts.map +1 -0
  413. package/types/lib/ecosystems/pylockutils.d.ts +68 -0
  414. package/types/lib/ecosystems/pylockutils.d.ts.map +1 -0
  415. package/types/lib/ecosystems/pythonutils.d.ts +70 -0
  416. package/types/lib/ecosystems/pythonutils.d.ts.map +1 -0
  417. package/types/lib/ecosystems/registryProvenance.d.ts +26 -0
  418. package/types/lib/ecosystems/registryProvenance.d.ts.map +1 -0
  419. package/types/lib/ecosystems/remote/huggingface.d.ts +31 -0
  420. package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -0
  421. package/types/lib/ecosystems/rubyutils.d.ts +182 -0
  422. package/types/lib/ecosystems/rubyutils.d.ts.map +1 -0
  423. package/types/lib/ecosystems/rusi.d.ts +40 -0
  424. package/types/lib/ecosystems/rusi.d.ts.map +1 -0
  425. package/types/lib/ecosystems/sbtutils.d.ts +179 -0
  426. package/types/lib/ecosystems/sbtutils.d.ts.map +1 -0
  427. package/types/lib/ecosystems/tea.d.ts +180 -0
  428. package/types/lib/ecosystems/tea.d.ts.map +1 -0
  429. package/types/lib/ecosystems/utils.d.ts +41 -0
  430. package/types/lib/ecosystems/utils.d.ts.map +1 -0
  431. package/types/lib/ecosystems/zigResolver.d.ts +70 -0
  432. package/types/lib/ecosystems/zigResolver.d.ts.map +1 -0
  433. package/types/lib/evinser/db.d.ts +17 -0
  434. package/types/lib/evinser/db.d.ts.map +1 -0
  435. package/types/lib/evinser/evinser.d.ts +354 -0
  436. package/types/lib/evinser/evinser.d.ts.map +1 -0
  437. package/types/lib/evinser/scalasem.d.ts +15 -0
  438. package/types/lib/evinser/scalasem.d.ts.map +1 -0
  439. package/types/lib/evinser/swiftsem.d.ts +103 -0
  440. package/types/lib/evinser/swiftsem.d.ts.map +1 -0
  441. package/types/lib/helpers/annotationFormatter.d.ts +23 -0
  442. package/types/lib/helpers/annotationFormatter.d.ts.map +1 -0
  443. package/types/lib/helpers/bomSigner.d.ts +28 -0
  444. package/types/lib/helpers/bomSigner.d.ts.map +1 -0
  445. package/types/lib/helpers/exportUtils.d.ts +52 -0
  446. package/types/lib/helpers/exportUtils.d.ts.map +1 -0
  447. package/types/lib/helpers/remote/dependency-track.d.ts +23 -0
  448. package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -0
  449. package/types/lib/helpers/versutils.d.ts +8 -0
  450. package/types/lib/helpers/versutils.d.ts.map +1 -0
  451. package/types/lib/helpers/vsixutils.d.ts +130 -0
  452. package/types/lib/helpers/vsixutils.d.ts.map +1 -0
  453. package/types/lib/inventory/agentFormulationParser.d.ts +21 -0
  454. package/types/lib/inventory/agentFormulationParser.d.ts.map +1 -0
  455. package/types/lib/inventory/aiCollector.d.ts +61 -0
  456. package/types/lib/inventory/aiCollector.d.ts.map +1 -0
  457. package/types/lib/inventory/aiInventory.d.ts +103 -0
  458. package/types/lib/inventory/aiInventory.d.ts.map +1 -0
  459. package/types/lib/inventory/aiModelVariants.d.ts +31 -0
  460. package/types/lib/inventory/aiModelVariants.d.ts.map +1 -0
  461. package/types/lib/inventory/aiOversightCollector.d.ts +28 -0
  462. package/types/lib/inventory/aiOversightCollector.d.ts.map +1 -0
  463. package/types/lib/inventory/aiProvenanceCollector.d.ts +13 -0
  464. package/types/lib/inventory/aiProvenanceCollector.d.ts.map +1 -0
  465. package/types/lib/inventory/analyzer.d.ts +157 -0
  466. package/types/lib/inventory/analyzer.d.ts.map +1 -0
  467. package/types/lib/inventory/analyzerScope.d.ts +106 -0
  468. package/types/lib/inventory/analyzerScope.d.ts.map +1 -0
  469. package/types/lib/inventory/astWorker.d.ts +9 -0
  470. package/types/lib/inventory/astWorker.d.ts.map +1 -0
  471. package/types/lib/inventory/atomUtils.d.ts +159 -0
  472. package/types/lib/inventory/atomUtils.d.ts.map +1 -0
  473. package/types/lib/inventory/auditCategories.d.ts +80 -0
  474. package/types/lib/inventory/auditCategories.d.ts.map +1 -0
  475. package/types/lib/inventory/bomUtils.d.ts +145 -0
  476. package/types/lib/inventory/bomUtils.d.ts.map +1 -0
  477. package/types/lib/inventory/cacheCommands.d.ts +28 -0
  478. package/types/lib/inventory/cacheCommands.d.ts.map +1 -0
  479. package/types/lib/inventory/cacheDir.d.ts +55 -0
  480. package/types/lib/inventory/cacheDir.d.ts.map +1 -0
  481. package/types/lib/inventory/cbomutils.d.ts +37 -0
  482. package/types/lib/inventory/cbomutils.d.ts.map +1 -0
  483. package/types/lib/inventory/cdxrs.d.ts +90 -0
  484. package/types/lib/inventory/cdxrs.d.ts.map +1 -0
  485. package/types/lib/inventory/ciParsers/azurePipelines.d.ts +27 -0
  486. package/types/lib/inventory/ciParsers/azurePipelines.d.ts.map +1 -0
  487. package/types/lib/inventory/ciParsers/circleCi.d.ts +27 -0
  488. package/types/lib/inventory/ciParsers/circleCi.d.ts.map +1 -0
  489. package/types/lib/inventory/ciParsers/common.d.ts +11 -0
  490. package/types/lib/inventory/ciParsers/common.d.ts.map +1 -0
  491. package/types/lib/inventory/ciParsers/githubActions.d.ts +38 -0
  492. package/types/lib/inventory/ciParsers/githubActions.d.ts.map +1 -0
  493. package/types/lib/inventory/ciParsers/gitlabCi.d.ts +26 -0
  494. package/types/lib/inventory/ciParsers/gitlabCi.d.ts.map +1 -0
  495. package/types/lib/inventory/ciParsers/jenkins.d.ts +26 -0
  496. package/types/lib/inventory/ciParsers/jenkins.d.ts.map +1 -0
  497. package/types/lib/inventory/citations.d.ts +90 -0
  498. package/types/lib/inventory/citations.d.ts.map +1 -0
  499. package/types/lib/inventory/communityAiConfigParser.d.ts +14 -0
  500. package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -0
  501. package/types/lib/inventory/containerRisk.d.ts +20 -0
  502. package/types/lib/inventory/containerRisk.d.ts.map +1 -0
  503. package/types/lib/inventory/cryptoAlgorithmFamily.d.ts +37 -0
  504. package/types/lib/inventory/cryptoAlgorithmFamily.d.ts.map +1 -0
  505. package/types/lib/inventory/deps.d.ts +140 -0
  506. package/types/lib/inventory/deps.d.ts.map +1 -0
  507. package/types/lib/inventory/depsUtils.d.ts +74 -0
  508. package/types/lib/inventory/depsUtils.d.ts.map +1 -0
  509. package/types/lib/inventory/display.d.ts +227 -0
  510. package/types/lib/inventory/display.d.ts.map +1 -0
  511. package/types/lib/inventory/dosai.d.ts +130 -0
  512. package/types/lib/inventory/dosai.d.ts.map +1 -0
  513. package/types/lib/inventory/dosaiParsers.d.ts +59 -0
  514. package/types/lib/inventory/dosaiParsers.d.ts.map +1 -0
  515. package/types/lib/inventory/dynamic.d.ts +25 -0
  516. package/types/lib/inventory/dynamic.d.ts.map +1 -0
  517. package/types/lib/inventory/envcontext.d.ts +377 -0
  518. package/types/lib/inventory/envcontext.d.ts.map +1 -0
  519. package/types/lib/inventory/evidenceUtils.d.ts +74 -0
  520. package/types/lib/inventory/evidenceUtils.d.ts.map +1 -0
  521. package/types/lib/inventory/fetchBatch.d.ts +127 -0
  522. package/types/lib/inventory/fetchBatch.d.ts.map +1 -0
  523. package/types/lib/inventory/fetchRate.d.ts +118 -0
  524. package/types/lib/inventory/fetchRate.d.ts.map +1 -0
  525. package/types/lib/inventory/forgeEnricher.d.ts +31 -0
  526. package/types/lib/inventory/forgeEnricher.d.ts.map +1 -0
  527. package/types/lib/inventory/formulationParsers.d.ts +50 -0
  528. package/types/lib/inventory/formulationParsers.d.ts.map +1 -0
  529. package/types/lib/inventory/gtfobins.d.ts +27 -0
  530. package/types/lib/inventory/gtfobins.d.ts.map +1 -0
  531. package/types/lib/inventory/hbom.d.ts +58 -0
  532. package/types/lib/inventory/hbom.d.ts.map +1 -0
  533. package/types/lib/inventory/hbomAnalysis.d.ts +56 -0
  534. package/types/lib/inventory/hbomAnalysis.d.ts.map +1 -0
  535. package/types/lib/inventory/hbomLoader.d.ts +7 -0
  536. package/types/lib/inventory/hbomLoader.d.ts.map +1 -0
  537. package/types/lib/inventory/hostTopology.d.ts +47 -0
  538. package/types/lib/inventory/hostTopology.d.ts.map +1 -0
  539. package/types/lib/inventory/inventoryStats.d.ts +42 -0
  540. package/types/lib/inventory/inventoryStats.d.ts.map +1 -0
  541. package/types/lib/inventory/jsonLike.d.ts +23 -0
  542. package/types/lib/inventory/jsonLike.d.ts.map +1 -0
  543. package/types/lib/inventory/licenseEnhancer.d.ts +70 -0
  544. package/types/lib/inventory/licenseEnhancer.d.ts.map +1 -0
  545. package/types/lib/inventory/lolbas.d.ts +16 -0
  546. package/types/lib/inventory/lolbas.d.ts.map +1 -0
  547. package/types/lib/inventory/mcp.d.ts +29 -0
  548. package/types/lib/inventory/mcp.d.ts.map +1 -0
  549. package/types/lib/inventory/mcpConfigParser.d.ts +20 -0
  550. package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -0
  551. package/types/lib/inventory/mcpDiscovery.d.ts +33 -0
  552. package/types/lib/inventory/mcpDiscovery.d.ts.map +1 -0
  553. package/types/lib/inventory/mcpPinning.d.ts +11 -0
  554. package/types/lib/inventory/mcpPinning.d.ts.map +1 -0
  555. package/types/lib/inventory/osPackageResolver.d.ts +49 -0
  556. package/types/lib/inventory/osPackageResolver.d.ts.map +1 -0
  557. package/types/lib/inventory/osinfo.d.ts +201 -0
  558. package/types/lib/inventory/osinfo.d.ts.map +1 -0
  559. package/types/lib/inventory/osqueryTransform.d.ts +84 -0
  560. package/types/lib/inventory/osqueryTransform.d.ts.map +1 -0
  561. package/types/lib/inventory/plugins.d.ts +58 -0
  562. package/types/lib/inventory/plugins.d.ts.map +1 -0
  563. package/types/lib/inventory/protobom.d.ts +71 -0
  564. package/types/lib/inventory/protobom.d.ts.map +1 -0
  565. package/types/lib/inventory/protobomLoader.d.ts +17 -0
  566. package/types/lib/inventory/protobomLoader.d.ts.map +1 -0
  567. package/types/lib/inventory/provenanceUtils.d.ts +98 -0
  568. package/types/lib/inventory/provenanceUtils.d.ts.map +1 -0
  569. package/types/lib/inventory/purl.d.ts +313 -0
  570. package/types/lib/inventory/purl.d.ts.map +1 -0
  571. package/types/lib/inventory/rustFormulationParser.d.ts +17 -0
  572. package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -0
  573. package/types/lib/inventory/sbomDocument.d.ts +59 -0
  574. package/types/lib/inventory/sbomDocument.d.ts.map +1 -0
  575. package/types/lib/inventory/source.d.ts +163 -0
  576. package/types/lib/inventory/source.d.ts.map +1 -0
  577. package/types/lib/inventory/spdx.d.ts +66 -0
  578. package/types/lib/inventory/spdx.d.ts.map +1 -0
  579. package/types/lib/inventory/spdxExpression.d.ts +58 -0
  580. package/types/lib/inventory/spdxExpression.d.ts.map +1 -0
  581. package/types/lib/inventory/spdxUtils.d.ts +12 -0
  582. package/types/lib/inventory/spdxUtils.d.ts.map +1 -0
  583. package/types/lib/inventory/table.d.ts +22 -0
  584. package/types/lib/inventory/table.d.ts.map +1 -0
  585. package/types/lib/inventory/traceRunner.d.ts +80 -0
  586. package/types/lib/inventory/traceRunner.d.ts.map +1 -0
  587. package/types/lib/inventory/unicodeScan.d.ts +46 -0
  588. package/types/lib/inventory/unicodeScan.d.ts.map +1 -0
  589. package/types/lib/managers/binary.d.ts +147 -0
  590. package/types/lib/managers/binary.d.ts.map +1 -0
  591. package/types/lib/managers/containerutils.d.ts +30 -0
  592. package/types/lib/managers/containerutils.d.ts.map +1 -0
  593. package/types/lib/managers/docker.d.ts +157 -0
  594. package/types/lib/managers/docker.d.ts.map +1 -0
  595. package/types/lib/managers/dockerConnection.d.ts +42 -0
  596. package/types/lib/managers/dockerConnection.d.ts.map +1 -0
  597. package/types/lib/managers/oci.d.ts +21 -0
  598. package/types/lib/managers/oci.d.ts.map +1 -0
  599. package/types/lib/managers/piptree.d.ts +13 -0
  600. package/types/lib/managers/piptree.d.ts.map +1 -0
  601. package/types/lib/parsers/cmakeCache.d.ts +70 -0
  602. package/types/lib/parsers/cmakeCache.d.ts.map +1 -0
  603. package/types/lib/parsers/gguf.d.ts +39 -0
  604. package/types/lib/parsers/gguf.d.ts.map +1 -0
  605. package/types/lib/parsers/gitAiNotes.d.ts +15 -0
  606. package/types/lib/parsers/gitAiNotes.d.ts.map +1 -0
  607. package/types/lib/parsers/gitmodules.d.ts +88 -0
  608. package/types/lib/parsers/gitmodules.d.ts.map +1 -0
  609. package/types/lib/parsers/htmlExtract.d.ts +34 -0
  610. package/types/lib/parsers/htmlExtract.d.ts.map +1 -0
  611. package/types/lib/parsers/huggingfaceManifest.d.ts +153 -0
  612. package/types/lib/parsers/huggingfaceManifest.d.ts.map +1 -0
  613. package/types/lib/parsers/huggingfaceUtils.d.ts +155 -0
  614. package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -0
  615. package/types/lib/parsers/iri.d.ts +68 -0
  616. package/types/lib/parsers/iri.d.ts.map +1 -0
  617. package/types/lib/parsers/npmrc.d.ts +33 -0
  618. package/types/lib/parsers/npmrc.d.ts.map +1 -0
  619. package/types/lib/parsers/ollama.d.ts +22 -0
  620. package/types/lib/parsers/ollama.d.ts.map +1 -0
  621. package/types/lib/parsers/xml.d.ts +47 -0
  622. package/types/lib/parsers/xml.d.ts.map +1 -0
  623. package/types/lib/server/server.d.ts +51 -0
  624. package/types/lib/server/server.d.ts.map +1 -0
  625. package/types/lib/stages/postgen/annotator.d.ts +36 -0
  626. package/types/lib/stages/postgen/annotator.d.ts.map +1 -0
  627. package/types/lib/stages/postgen/auditBom.d.ts +92 -0
  628. package/types/lib/stages/postgen/auditBom.d.ts.map +1 -0
  629. package/types/lib/stages/postgen/postgen.d.ts +59 -0
  630. package/types/lib/stages/postgen/postgen.d.ts.map +1 -0
  631. package/types/lib/stages/postgen/ruleEngine.d.ts +18 -0
  632. package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -0
  633. package/types/lib/stages/postgen/sortBom.d.ts +34 -0
  634. package/types/lib/stages/postgen/sortBom.d.ts.map +1 -0
  635. package/types/lib/stages/postgen/spdxConverter.d.ts +11 -0
  636. package/types/lib/stages/postgen/spdxConverter.d.ts.map +1 -0
  637. package/types/lib/stages/postgen/specVersionCompat.d.ts +71 -0
  638. package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -0
  639. package/types/lib/stages/pregen/envAudit.d.ts +14 -0
  640. package/types/lib/stages/pregen/envAudit.d.ts.map +1 -0
  641. package/types/lib/stages/pregen/pregen.d.ts +59 -0
  642. package/types/lib/stages/pregen/pregen.d.ts.map +1 -0
  643. package/types/lib/third-party/arborist/lib/arborist/index.d.ts +47 -0
  644. package/types/lib/third-party/arborist/lib/arborist/index.d.ts.map +1 -0
  645. package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts +4 -0
  646. package/types/lib/third-party/arborist/lib/arborist/load-actual.d.ts.map +1 -0
  647. package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts +4 -0
  648. package/types/lib/third-party/arborist/lib/arborist/load-virtual.d.ts.map +1 -0
  649. package/types/lib/third-party/arborist/lib/bin-links.d.ts +18 -0
  650. package/types/lib/third-party/arborist/lib/bin-links.d.ts.map +1 -0
  651. package/types/lib/third-party/arborist/lib/calc-dep-flags.d.ts +3 -0
  652. package/types/lib/third-party/arborist/lib/calc-dep-flags.d.ts.map +1 -0
  653. package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts +9 -0
  654. package/types/lib/third-party/arborist/lib/case-insensitive-map.d.ts.map +1 -0
  655. package/types/lib/third-party/arborist/lib/consistent-resolve.d.ts +3 -0
  656. package/types/lib/third-party/arborist/lib/consistent-resolve.d.ts.map +1 -0
  657. package/types/lib/third-party/arborist/lib/debug.d.ts +3 -0
  658. package/types/lib/third-party/arborist/lib/debug.d.ts.map +1 -0
  659. package/types/lib/third-party/arborist/lib/dep-valid.d.ts +3 -0
  660. package/types/lib/third-party/arborist/lib/dep-valid.d.ts.map +1 -0
  661. package/types/lib/third-party/arborist/lib/edge.d.ts +46 -0
  662. package/types/lib/third-party/arborist/lib/edge.d.ts.map +1 -0
  663. package/types/lib/third-party/arborist/lib/from-path.d.ts +3 -0
  664. package/types/lib/third-party/arborist/lib/from-path.d.ts.map +1 -0
  665. package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts +3 -0
  666. package/types/lib/third-party/arborist/lib/gather-dep-set.d.ts.map +1 -0
  667. package/types/lib/third-party/arborist/lib/index.d.ts +3 -0
  668. package/types/lib/third-party/arborist/lib/index.d.ts.map +1 -0
  669. package/types/lib/third-party/arborist/lib/inventory.d.ts +14 -0
  670. package/types/lib/third-party/arborist/lib/inventory.d.ts.map +1 -0
  671. package/types/lib/third-party/arborist/lib/link.d.ts +18 -0
  672. package/types/lib/third-party/arborist/lib/link.d.ts.map +1 -0
  673. package/types/lib/third-party/arborist/lib/node.d.ts +112 -0
  674. package/types/lib/third-party/arborist/lib/node.d.ts.map +1 -0
  675. package/types/lib/third-party/arborist/lib/npm-extension.d.ts +18 -0
  676. package/types/lib/third-party/arborist/lib/npm-extension.d.ts.map +1 -0
  677. package/types/lib/third-party/arborist/lib/override-resolves.d.ts +3 -0
  678. package/types/lib/third-party/arborist/lib/override-resolves.d.ts.map +1 -0
  679. package/types/lib/third-party/arborist/lib/override-set.d.ts +27 -0
  680. package/types/lib/third-party/arborist/lib/override-set.d.ts.map +1 -0
  681. package/types/lib/third-party/arborist/lib/package-extensions.d.ts +36 -0
  682. package/types/lib/third-party/arborist/lib/package-extensions.d.ts.map +1 -0
  683. package/types/lib/third-party/arborist/lib/printable.d.ts +3 -0
  684. package/types/lib/third-party/arborist/lib/printable.d.ts.map +1 -0
  685. package/types/lib/third-party/arborist/lib/proc-log.d.ts +20 -0
  686. package/types/lib/third-party/arborist/lib/proc-log.d.ts.map +1 -0
  687. package/types/lib/third-party/arborist/lib/realpath.d.ts +3 -0
  688. package/types/lib/third-party/arborist/lib/realpath.d.ts.map +1 -0
  689. package/types/lib/third-party/arborist/lib/relpath.d.ts +3 -0
  690. package/types/lib/third-party/arborist/lib/relpath.d.ts.map +1 -0
  691. package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts +54 -0
  692. package/types/lib/third-party/arborist/lib/shrinkwrap.d.ts.map +1 -0
  693. package/types/lib/third-party/arborist/lib/spec-from-lock.d.ts +3 -0
  694. package/types/lib/third-party/arborist/lib/spec-from-lock.d.ts.map +1 -0
  695. package/types/lib/third-party/arborist/lib/tree-check.d.ts +3 -0
  696. package/types/lib/third-party/arborist/lib/tree-check.d.ts.map +1 -0
  697. package/types/lib/third-party/arborist/lib/validate-npm-package-name.d.ts +13 -0
  698. package/types/lib/third-party/arborist/lib/validate-npm-package-name.d.ts.map +1 -0
  699. package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts +6 -0
  700. package/types/lib/third-party/arborist/lib/version-from-tgz.d.ts.map +1 -0
  701. package/types/lib/third-party/arborist/lib/yarn-lock.d.ts +35 -0
  702. package/types/lib/third-party/arborist/lib/yarn-lock.d.ts.map +1 -0
  703. package/types/lib/validator/bomValidator.d.ts +40 -0
  704. package/types/lib/validator/bomValidator.d.ts.map +1 -0
  705. package/types/lib/validator/complianceEngine.d.ts +72 -0
  706. package/types/lib/validator/complianceEngine.d.ts.map +1 -0
  707. package/types/lib/validator/complianceRules.d.ts +61 -0
  708. package/types/lib/validator/complianceRules.d.ts.map +1 -0
  709. package/types/lib/validator/index.d.ts +101 -0
  710. package/types/lib/validator/index.d.ts.map +1 -0
  711. package/types/lib/validator/reporters/annotations.d.ts +37 -0
  712. package/types/lib/validator/reporters/annotations.d.ts.map +1 -0
  713. package/types/lib/validator/reporters/console.d.ts +34 -0
  714. package/types/lib/validator/reporters/console.d.ts.map +1 -0
  715. package/types/lib/validator/reporters/index.d.ts +30 -0
  716. package/types/lib/validator/reporters/index.d.ts.map +1 -0
  717. package/types/lib/validator/reporters/json.d.ts +11 -0
  718. package/types/lib/validator/reporters/json.d.ts.map +1 -0
  719. package/types/lib/validator/reporters/sarif.d.ts +22 -0
  720. package/types/lib/validator/reporters/sarif.d.ts.map +1 -0
  721. package/mod.d.ts +0 -7
  722. package/mod.js +0 -22
@@ -0,0 +1,1488 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import process from "node:process";
4
+ import { URL } from "node:url";
5
+
6
+ import { Purl } from "@cdxgen/cdx-purl";
7
+ import { coerce, diff, prerelease } from "semver";
8
+
9
+ import {
10
+ cdxgenAgent,
11
+ createDryRunError,
12
+ DEBUG_MODE,
13
+ hasDangerousUnicode,
14
+ isDryRun,
15
+ isSecureMode,
16
+ readEnvironmentVariable,
17
+ recordActivity,
18
+ } from "../core/activity.js";
19
+ import {
20
+ getTmpDir,
21
+ safeMkdtempSync,
22
+ safeRmSync,
23
+ safeSpawnSync,
24
+ } from "../core/fs.js";
25
+ import { thoughtLog } from "../core/logger.js";
26
+ import { isValidDriveRoot, isWin } from "../core/paths.js";
27
+ import {
28
+ prefetchEnabled,
29
+ prefetchedResponse,
30
+ prefetchJson,
31
+ } from "./fetchBatch.js";
32
+
33
+ /** Raised when a caller omits a registry helper that the purl type requires. */
34
+ class MissingRegistryHelperError extends Error {}
35
+
36
+ /** Warning emitted for repository URLs resolved from untrusted package registry metadata. */
37
+ export const PURL_REGISTRY_LOOKUP_WARNING =
38
+ "Resolved repository URL from package registry metadata. This source can be inaccurate or malicious; review before trusting results.";
39
+
40
+ /** Purl types supported for source repository resolution. */
41
+ export const SUPPORTED_PURL_SOURCE_TYPES = [
42
+ "npm",
43
+ "pypi",
44
+ "gem",
45
+ "cargo",
46
+ "pub",
47
+ "github",
48
+ "bitbucket",
49
+ "maven",
50
+ "composer",
51
+ "generic",
52
+ ];
53
+
54
+ const MAX_MONOREPO_PACKAGE_JSON_FILES = 2000;
55
+ const MAX_MONOREPO_DIRECTORIES = 5000;
56
+ const MAX_RELEASE_NOTE_RESOLVES = 50;
57
+
58
+ /**
59
+ * Build a scoped npm package name.
60
+ *
61
+ * @param {string|undefined} namespace package namespace
62
+ * @param {string|undefined} name package name
63
+ * @returns {string|undefined} scoped package name
64
+ */
65
+ function buildScopedNpmPackageName(namespace, name) {
66
+ if (!name) {
67
+ return undefined;
68
+ }
69
+ if (!namespace) {
70
+ return name;
71
+ }
72
+ return `${namespace.startsWith("@") ? namespace : `@${namespace}`}/${name}`;
73
+ }
74
+
75
+ /**
76
+ * Validate git ref names used as branch/tag values.
77
+ *
78
+ * @param {string|undefined} refName branch or tag name
79
+ * @returns {boolean} true if safe
80
+ */
81
+ export function isSafeGitRefName(refName) {
82
+ if (!refName || typeof refName !== "string") {
83
+ return false;
84
+ }
85
+ if (refName.startsWith("-")) {
86
+ return false;
87
+ }
88
+ return /^[A-Za-z0-9._/@+-]+$/.test(refName);
89
+ }
90
+
91
+ function inferGitOperation(args = []) {
92
+ for (let index = 0; index < args.length; index += 1) {
93
+ const arg = args[index];
94
+ if (arg === "-c" || arg === "--config-env") {
95
+ index += 1;
96
+ continue;
97
+ }
98
+ if (typeof arg === "string" && arg.startsWith("-")) {
99
+ continue;
100
+ }
101
+ return arg || "command";
102
+ }
103
+ return "command";
104
+ }
105
+
106
+ /**
107
+ * Execute git with hardened defaults.
108
+ *
109
+ * @param {string[]} args git arguments
110
+ * @param {Object} options command options
111
+ * @param {string|undefined} options.cwd working directory
112
+ * @returns {Object} spawn result
113
+ */
114
+ export function hardenedGitCommand(args, options = {}) {
115
+ const gitOperation = inferGitOperation(args);
116
+ const gitAllowProtocol = getGitAllowProtocol();
117
+ const envConfigs = {
118
+ GIT_CONFIG_COUNT: "2",
119
+ GIT_CONFIG_KEY_0: "core.fsmonitor",
120
+ GIT_CONFIG_VALUE_0: "false",
121
+ GIT_CONFIG_KEY_1: "safe.bareRepository",
122
+ GIT_CONFIG_VALUE_1: "explicit",
123
+ GIT_TERMINAL_PROMPT: "0",
124
+ };
125
+ const env = isSecureMode
126
+ ? {
127
+ ...process.env,
128
+ ...envConfigs,
129
+ GIT_CONFIG_NOSYSTEM: "1",
130
+ GIT_CONFIG_GLOBAL: "/dev/null",
131
+ GIT_ALLOW_PROTOCOL: gitAllowProtocol,
132
+ }
133
+ : {
134
+ ...process.env,
135
+ ...envConfigs,
136
+ GIT_ALLOW_PROTOCOL: gitAllowProtocol,
137
+ };
138
+ return safeSpawnSync("git", args, {
139
+ cdxgenActivity: {
140
+ blockedReason: `Dry run mode blocks git ${gitOperation} operations.`,
141
+ gitOperation,
142
+ kind: `git-${gitOperation}`,
143
+ metadata: {
144
+ capability: "git-operation",
145
+ },
146
+ },
147
+ shell: false,
148
+ cwd: options.cwd,
149
+ env,
150
+ });
151
+ }
152
+
153
+ function normalizeTagName(tagName) {
154
+ if (!tagName || typeof tagName !== "string") {
155
+ return undefined;
156
+ }
157
+ return tagName
158
+ .trim()
159
+ .replace(/^refs\/tags\//, "")
160
+ .replace(/\^\{\}$/, "");
161
+ }
162
+
163
+ function releaseTypeFromTags(currentTag, previousTag) {
164
+ const currentVersion = coerce(currentTag || "");
165
+ const previousVersion = coerce(previousTag || "");
166
+ if (!currentVersion || !previousVersion) {
167
+ return "internal";
168
+ }
169
+ if (prerelease(currentVersion.version)?.length) {
170
+ return "pre-release";
171
+ }
172
+ const versionDiff = diff(previousVersion.version, currentVersion.version);
173
+ if (versionDiff === "major") {
174
+ return "major";
175
+ }
176
+ if (versionDiff === "minor") {
177
+ return "minor";
178
+ }
179
+ if (versionDiff === "patch") {
180
+ return "patch";
181
+ }
182
+ return "internal";
183
+ }
184
+
185
+ function parseTagList(output) {
186
+ return (output || "")
187
+ .split("\n")
188
+ .map((line) => normalizeTagName(line))
189
+ .filter((tagName) => isSafeGitRefName(tagName))
190
+ .filter(Boolean);
191
+ }
192
+
193
+ function parseLsRemoteTags(output) {
194
+ const tags = [];
195
+ for (const line of (output || "").split("\n")) {
196
+ const ref = normalizeTagName(line.trim().split(/\s+/)[1]);
197
+ if (ref && isSafeGitRefName(ref)) {
198
+ tags.push(ref);
199
+ }
200
+ }
201
+ return Array.from(new Set(tags)).sort((a, b) => {
202
+ const av = coerce(a || "");
203
+ const bv = coerce(b || "");
204
+ if (av && bv) {
205
+ return bv.compare(av);
206
+ }
207
+ return b.localeCompare(a);
208
+ });
209
+ }
210
+
211
+ function issueTypeFromCommitMessage(message) {
212
+ const normalized = (message || "").toLowerCase();
213
+ if (
214
+ normalized.includes("security") ||
215
+ normalized.includes("cve-") ||
216
+ normalized.includes("vuln")
217
+ ) {
218
+ return "security";
219
+ }
220
+ if (
221
+ normalized.startsWith("fix") ||
222
+ normalized.includes(" bug") ||
223
+ normalized.includes("defect")
224
+ ) {
225
+ return "defect";
226
+ }
227
+ return "enhancement";
228
+ }
229
+
230
+ /**
231
+ * Build CycloneDX release notes from git tags and commits.
232
+ *
233
+ * @param {string|undefined} repoPath local repository path
234
+ * @param {Object} options options carrying release notes hints
235
+ * @returns {Object|undefined} releaseNotes object
236
+ */
237
+ export function buildReleaseNotesFromGit(repoPath, options = {}) {
238
+ let currentTag = normalizeTagName(options.releaseNotesCurrentTag);
239
+ let previousTag = normalizeTagName(options.releaseNotesPreviousTag);
240
+ let remoteUrl;
241
+ let localRepoAvailable = false;
242
+ if (repoPath && !maybeRemotePath(repoPath)) {
243
+ const repoCheck = hardenedGitCommand(
244
+ ["rev-parse", "--is-inside-work-tree"],
245
+ {
246
+ cwd: repoPath,
247
+ },
248
+ );
249
+ localRepoAvailable = repoCheck.status === 0;
250
+ if (localRepoAvailable) {
251
+ const localTagsResult = hardenedGitCommand(
252
+ ["tag", "--sort=-creatordate", "--merged", "HEAD"],
253
+ { cwd: repoPath },
254
+ );
255
+ const localTags = parseTagList(localTagsResult.stdout);
256
+ if (!currentTag && localTags.length) {
257
+ currentTag = localTags[0];
258
+ }
259
+ if (!previousTag && localTags.length > 1) {
260
+ previousTag = localTags.find((t) => t !== currentTag);
261
+ }
262
+ const remoteResult = hardenedGitCommand(
263
+ ["config", "--get", "remote.origin.url"],
264
+ { cwd: repoPath },
265
+ );
266
+ if (remoteResult.status === 0 && remoteResult.stdout) {
267
+ remoteUrl = remoteResult.stdout.toString().trim();
268
+ }
269
+ }
270
+ }
271
+ remoteUrl = remoteUrl || options.releaseNotesGitUrl;
272
+ const remoteUrlValidationError =
273
+ typeof remoteUrl === "string"
274
+ ? validateAndRejectGitSource(remoteUrl)
275
+ : null;
276
+ const canDiscoverRemoteTags =
277
+ (!currentTag || !previousTag) &&
278
+ typeof remoteUrl === "string" &&
279
+ !remoteUrl.startsWith("-") &&
280
+ !remoteUrlValidationError &&
281
+ /github\.com[:/]/i.test(remoteUrl);
282
+ if (canDiscoverRemoteTags) {
283
+ const remoteTagsResult = hardenedGitCommand(
284
+ [
285
+ "-c",
286
+ "alias.ls-remote=",
287
+ "-c",
288
+ "core.fsmonitor=false",
289
+ "-c",
290
+ "safe.bareRepository=explicit",
291
+ "-c",
292
+ "core.hooksPath=/dev/null",
293
+ "ls-remote",
294
+ "--refs",
295
+ "--tags",
296
+ "--",
297
+ remoteUrl,
298
+ ],
299
+ {},
300
+ );
301
+ const remoteTags = parseLsRemoteTags(remoteTagsResult.stdout);
302
+ if (!currentTag && remoteTags.length) {
303
+ currentTag = remoteTags[0];
304
+ }
305
+ if (!previousTag && remoteTags.length > 1) {
306
+ previousTag = remoteTags.find((t) => t !== currentTag);
307
+ }
308
+ }
309
+ if (!currentTag) {
310
+ return undefined;
311
+ }
312
+ if (!isSafeGitRefName(currentTag)) {
313
+ return undefined;
314
+ }
315
+ if (previousTag && !isSafeGitRefName(previousTag)) {
316
+ previousTag = undefined;
317
+ }
318
+ let timestamp;
319
+ if (localRepoAvailable) {
320
+ const tsResult = hardenedGitCommand(
321
+ ["log", "-1", "--format=%cI", currentTag],
322
+ {
323
+ cwd: repoPath,
324
+ },
325
+ );
326
+ if (tsResult.status === 0 && tsResult.stdout) {
327
+ timestamp = tsResult.stdout.toString().trim();
328
+ }
329
+ }
330
+ if (!timestamp) {
331
+ timestamp = new Date().toISOString();
332
+ }
333
+ const resolves = [];
334
+ if (localRepoAvailable && previousTag) {
335
+ const logResult = hardenedGitCommand(
336
+ ["log", "--pretty=format:%H%x09%s", `${previousTag}..${currentTag}`],
337
+ { cwd: repoPath },
338
+ );
339
+ if (logResult.status === 0 && logResult.stdout) {
340
+ // Keep the resolves list bounded to avoid excessive metadata growth.
341
+ for (const line of logResult.stdout
342
+ .toString()
343
+ .split("\n")
344
+ .filter(Boolean)) {
345
+ const [sha, ...rest] = line.split("\t");
346
+ const message = rest.join("\t").trim();
347
+ if (!sha || !message) {
348
+ continue;
349
+ }
350
+ resolves.push({
351
+ type: issueTypeFromCommitMessage(message),
352
+ id: sha.substring(0, 12),
353
+ name: message,
354
+ description: message,
355
+ });
356
+ }
357
+ if (resolves.length > MAX_RELEASE_NOTE_RESOLVES) {
358
+ resolves.length = MAX_RELEASE_NOTE_RESOLVES;
359
+ }
360
+ }
361
+ }
362
+ const tags = [currentTag];
363
+ if (previousTag && previousTag !== currentTag) {
364
+ tags.push(previousTag);
365
+ }
366
+ return {
367
+ type: releaseTypeFromTags(currentTag, previousTag),
368
+ title: `Release notes for ${currentTag}`,
369
+ description: previousTag
370
+ ? `Changes between ${previousTag} and ${currentTag}.`
371
+ : `Release notes for ${currentTag}.`,
372
+ timestamp,
373
+ tags,
374
+ resolves,
375
+ };
376
+ }
377
+
378
+ /**
379
+ * Return git allow protocol string from the environment variables.
380
+ *
381
+ * @returns {string} git allow protocol string
382
+ */
383
+ export function getGitAllowProtocol() {
384
+ return (
385
+ readEnvironmentVariable("GIT_ALLOW_PROTOCOL") ||
386
+ readEnvironmentVariable("CDXGEN_GIT_ALLOW_PROTOCOL") ||
387
+ readEnvironmentVariable("CDXGEN_SERVER_GIT_ALLOW_PROTOCOL") ||
388
+ (isSecureMode ? "https:ssh" : "https:git:ssh")
389
+ );
390
+ }
391
+
392
+ /**
393
+ * Return configured allowed git hosts.
394
+ *
395
+ * @returns {string[]} list of configured hosts
396
+ */
397
+ function getAllowedHosts() {
398
+ const configuredHosts =
399
+ readEnvironmentVariable("CDXGEN_GIT_ALLOWED_HOSTS") ||
400
+ readEnvironmentVariable("CDXGEN_SERVER_ALLOWED_HOSTS") ||
401
+ "";
402
+ return configuredHosts
403
+ .split(",")
404
+ .map((h) => h.trim())
405
+ .filter(Boolean);
406
+ }
407
+
408
+ /**
409
+ * Checks the given hostname against the allowed list.
410
+ *
411
+ * @param {string} hostname Host name to check
412
+ * @returns {boolean} true if the hostname in its entirety is allowed. false otherwise.
413
+ */
414
+ export function isAllowedHost(hostname) {
415
+ const allowedHosts = getAllowedHosts();
416
+ if (!allowedHosts.length) {
417
+ return true;
418
+ }
419
+ if (hasDangerousUnicode(hostname)) {
420
+ return false;
421
+ }
422
+ return allowedHosts.includes(hostname);
423
+ }
424
+
425
+ /**
426
+ * Return configured allowed paths.
427
+ *
428
+ * @returns {string[]} list of configured paths
429
+ */
430
+ function getAllowedPaths() {
431
+ const configuredPaths =
432
+ readEnvironmentVariable("CDXGEN_ALLOWED_PATHS") ||
433
+ readEnvironmentVariable("CDXGEN_SERVER_ALLOWED_PATHS") ||
434
+ "";
435
+ return configuredPaths
436
+ .split(",")
437
+ .map((p) => p.trim())
438
+ .filter(Boolean);
439
+ }
440
+
441
+ /**
442
+ * Checks the given path string to belong to a drive in Windows.
443
+ *
444
+ * @param {string} p Path string to check
445
+ * @returns {boolean} true if the windows path belongs to a drive. false otherwise (device names)
446
+ */
447
+ export function isAllowedWinPath(p) {
448
+ if (typeof p !== "string") {
449
+ return false;
450
+ }
451
+ if (p === "") {
452
+ return true;
453
+ }
454
+ if (hasDangerousUnicode(p)) {
455
+ return false;
456
+ }
457
+ if (!isWin) {
458
+ return true;
459
+ }
460
+ try {
461
+ const normalized = path.normalize(p);
462
+ if (hasDangerousUnicode(normalized)) {
463
+ return false;
464
+ }
465
+ const { root } = path.parse(normalized);
466
+ if (root === "\\") {
467
+ return true;
468
+ }
469
+ if (root.startsWith("\\\\")) {
470
+ return false;
471
+ }
472
+ return isValidDriveRoot(root);
473
+ } catch (_err) {
474
+ return false;
475
+ }
476
+ }
477
+
478
+ /**
479
+ * Checks the given path against the allowed list.
480
+ *
481
+ * @param {string} p Path string to check
482
+ * @returns {boolean} true if the path is present in the allowed paths. false otherwise.
483
+ */
484
+ export function isAllowedPath(p) {
485
+ if (typeof p !== "string") {
486
+ return false;
487
+ }
488
+ if (hasDangerousUnicode(p)) {
489
+ return false;
490
+ }
491
+ const allowedPaths = getAllowedPaths();
492
+ if (!allowedPaths.length) {
493
+ return true;
494
+ }
495
+ if (isWin && !isAllowedWinPath(p)) {
496
+ return false;
497
+ }
498
+ return allowedPaths.some((ap) => {
499
+ const resolvedP = path.resolve(p);
500
+ const resolvedAp = path.resolve(ap);
501
+ const relativePath = path.relative(resolvedAp, resolvedP);
502
+ return (
503
+ relativePath === "" ||
504
+ (!relativePath.startsWith("..") && !path.isAbsolute(relativePath))
505
+ );
506
+ });
507
+ }
508
+
509
+ /**
510
+ * Determine if the path could be a package URL.
511
+ *
512
+ * @param {string} filePath Path or URL
513
+ * @returns {boolean} true if the file path looks like a purl
514
+ */
515
+ export function maybePurlSource(filePath) {
516
+ return typeof filePath === "string" && filePath.startsWith("pkg:");
517
+ }
518
+
519
+ /**
520
+ * Determine if the file path could be a remote URL.
521
+ *
522
+ * @param {string} filePath The Git URL or local path
523
+ * @returns {boolean} true if the file path is a remote URL. false otherwise.
524
+ */
525
+ export function maybeRemotePath(filePath) {
526
+ return /^[a-zA-Z0-9+.-]+:\/\//.test(filePath) || filePath.startsWith("git@");
527
+ }
528
+
529
+ /**
530
+ * Validates a given Git URL/Path against dangerous protocols and allowed hosts.
531
+ *
532
+ * @param {string} filePath The Git URL or local path
533
+ * @returns {Object|null} Error object if invalid, or null if valid
534
+ */
535
+ export function validateAndRejectGitSource(filePath) {
536
+ if (/^(ext|fd)::/i.test(filePath)) {
537
+ return {
538
+ status: 400,
539
+ error: "Invalid Protocol",
540
+ details: "The provided protocol is not allowed.",
541
+ };
542
+ }
543
+ if (maybeRemotePath(filePath)) {
544
+ let gitUrlObj;
545
+ try {
546
+ let urlToParse = filePath;
547
+ if (filePath.startsWith("git@") && !filePath.includes("://")) {
548
+ urlToParse = `ssh://${filePath.replace(":", "/")}`;
549
+ }
550
+ gitUrlObj = new URL(urlToParse);
551
+ } catch (_err) {
552
+ return {
553
+ status: 400,
554
+ error: "Invalid URL Format",
555
+ details: "The provided Git URL is malformed.",
556
+ };
557
+ }
558
+ const gitAllowProtocol = getGitAllowProtocol();
559
+ const allowedSchemes = gitAllowProtocol
560
+ .split(":")
561
+ .filter(Boolean)
562
+ .map((p) => `${p.toLowerCase()}:`);
563
+
564
+ if (
565
+ allowedSchemes.includes("ssh:") &&
566
+ !allowedSchemes.includes("git+ssh:")
567
+ ) {
568
+ allowedSchemes.push("git+ssh:");
569
+ }
570
+
571
+ if (!allowedSchemes.includes(gitUrlObj.protocol)) {
572
+ return {
573
+ status: 400,
574
+ error: "Protocol Not Allowed",
575
+ details: `The protocol '${gitUrlObj.protocol}' is not permitted by GIT_ALLOW_PROTOCOL.`,
576
+ };
577
+ }
578
+
579
+ if (gitUrlObj.href.includes("::")) {
580
+ return {
581
+ status: 400,
582
+ error: "Invalid URL Syntax",
583
+ details: "Git remote helper syntax (::) is not allowed.",
584
+ };
585
+ }
586
+
587
+ if (!isAllowedHost(gitUrlObj.hostname)) {
588
+ return {
589
+ status: 403,
590
+ error: "Host Not Allowed",
591
+ details: "The Git URL host is not allowed as per the allowlist.",
592
+ };
593
+ }
594
+ }
595
+
596
+ return null;
597
+ }
598
+
599
+ /**
600
+ * Clone a git repository into a temporary directory.
601
+ *
602
+ * @param {string} repoUrl Repository URL
603
+ * @param {string|string[]|null} branch Branch name
604
+ * @returns {string} cloned directory path
605
+ */
606
+ export function gitClone(repoUrl, branch = null) {
607
+ let baseDirName = path.basename(repoUrl);
608
+ if (!/^[a-zA-Z0-9_-]+$/.test(baseDirName)) {
609
+ baseDirName = "repo-";
610
+ }
611
+ if (isDryRun) {
612
+ const error = createDryRunError(
613
+ "clone",
614
+ repoUrl,
615
+ "Dry run mode blocks repository cloning.",
616
+ );
617
+ recordActivity({
618
+ kind: "clone",
619
+ reason: error.message,
620
+ status: "blocked",
621
+ target: repoUrl,
622
+ });
623
+ return path.join(getTmpDir(), `${baseDirName}${path.sep}dry-run-clone`);
624
+ }
625
+ const tempDir = safeMkdtempSync(path.join(getTmpDir(), baseDirName));
626
+
627
+ const gitArgs = [
628
+ "-c",
629
+ "alias.clone=",
630
+ "-c",
631
+ "core.fsmonitor=false",
632
+ "-c",
633
+ "safe.bareRepository=explicit",
634
+ "-c",
635
+ "core.hooksPath=/dev/null",
636
+ "clone",
637
+ "--template=",
638
+ repoUrl,
639
+ "--depth",
640
+ "1",
641
+ tempDir,
642
+ ];
643
+ if (branch) {
644
+ const firstBranchStr = Array.isArray(branch) ? branch[0] : String(branch);
645
+ if (!isSafeGitRefName(firstBranchStr)) {
646
+ console.warn("Skipping branch clone: invalid branch name");
647
+ } else {
648
+ const cloneIndex = gitArgs.indexOf("clone");
649
+ gitArgs.splice(cloneIndex + 1, 0, "--branch", firstBranchStr);
650
+ }
651
+ }
652
+ thoughtLog(
653
+ `Cloning Repo${branch ? ` with branch ${branch}` : ""} to ${tempDir}`,
654
+ );
655
+ const result = hardenedGitCommand(gitArgs);
656
+ if (result.status !== 0) {
657
+ console.error(result.stderr);
658
+ }
659
+
660
+ return tempDir;
661
+ }
662
+
663
+ /**
664
+ * Sanitize remote URL for logging.
665
+ *
666
+ * @param {string|undefined} remoteUrl Repository URL
667
+ * @returns {string|undefined} sanitized URL
668
+ */
669
+ export function sanitizeRemoteUrlForLogs(remoteUrl) {
670
+ if (!remoteUrl || typeof remoteUrl !== "string") {
671
+ return remoteUrl;
672
+ }
673
+ try {
674
+ const parsed = new URL(remoteUrl);
675
+ if (parsed.username || parsed.password) {
676
+ parsed.username = "***";
677
+ parsed.password = "***";
678
+ }
679
+ return parsed.toString();
680
+ } catch (_err) {
681
+ return remoteUrl;
682
+ }
683
+ }
684
+
685
+ /**
686
+ * Find a matching git ref for a package version.
687
+ *
688
+ * @param {string} repoUrl Repository URL
689
+ * @param {Object|undefined} purlResolution purl resolution metadata
690
+ * @returns {string|undefined} matching tag or branch reference
691
+ */
692
+ export function findGitRefForPurlVersion(repoUrl, purlResolution) {
693
+ const packageVersion = purlResolution?.version;
694
+ if (!packageVersion) {
695
+ return undefined;
696
+ }
697
+ const purlType = purlResolution?.type;
698
+ const purlNamespace = purlResolution?.namespace;
699
+ const purlName = purlResolution?.name;
700
+ const refCandidates = [packageVersion, `v${packageVersion}`];
701
+ if (purlType === "npm" && purlName) {
702
+ const scopedName = buildScopedNpmPackageName(purlNamespace, purlName);
703
+ refCandidates.push(
704
+ `${purlName}@${packageVersion}`,
705
+ `${scopedName}@${packageVersion}`,
706
+ `${purlName}-v${packageVersion}`,
707
+ `${scopedName}-v${packageVersion}`,
708
+ );
709
+ }
710
+ const filteredCandidates = [...new Set(refCandidates)].filter((candidate) =>
711
+ isSafeGitRefName(candidate),
712
+ );
713
+ if (!repoUrl || repoUrl.startsWith("-")) {
714
+ return undefined;
715
+ }
716
+ if (validateAndRejectGitSource(repoUrl)) {
717
+ return undefined;
718
+ }
719
+ const result = hardenedGitCommand(
720
+ [
721
+ "-c",
722
+ "alias.ls-remote=",
723
+ "-c",
724
+ "core.fsmonitor=false",
725
+ "-c",
726
+ "safe.bareRepository=explicit",
727
+ "-c",
728
+ "core.hooksPath=/dev/null",
729
+ "ls-remote",
730
+ "--refs",
731
+ "--tags",
732
+ "--heads",
733
+ "--",
734
+ repoUrl,
735
+ ],
736
+ {},
737
+ );
738
+ if (result.status !== 0 || !result.stdout) {
739
+ return undefined;
740
+ }
741
+ const availableRefs = result.stdout
742
+ .split("\n")
743
+ .map((line) => line.trim().split(/\s+/)[1])
744
+ .filter(Boolean)
745
+ .map((ref) => ref.replace(/^refs\/(?:tags|heads)\//, ""));
746
+ for (const candidate of filteredCandidates) {
747
+ if (availableRefs.includes(candidate)) {
748
+ return candidate;
749
+ }
750
+ }
751
+ return undefined;
752
+ }
753
+
754
+ /**
755
+ * Find the best source directory for purl-based npm monorepo scans.
756
+ *
757
+ * @param {string} srcDir cloned source directory
758
+ * @param {Object|undefined} purlResolution purl resolution metadata
759
+ * @returns {string|undefined} preferred source directory
760
+ */
761
+ export function resolvePurlSourceDirectory(srcDir, purlResolution) {
762
+ if (purlResolution?.type !== "npm" || !purlResolution?.name || !srcDir) {
763
+ return undefined;
764
+ }
765
+ const purlNamespace = purlResolution?.namespace;
766
+ const packageNameCandidates = [purlResolution.name];
767
+ if (purlNamespace) {
768
+ packageNameCandidates.push(
769
+ `${purlNamespace}/${purlResolution.name}`,
770
+ buildScopedNpmPackageName(purlNamespace, purlResolution.name),
771
+ );
772
+ }
773
+ const uniquePackageNameCandidates = [
774
+ ...new Set(packageNameCandidates.filter(Boolean)),
775
+ ];
776
+ const skipDirectories = new Set([
777
+ ".git",
778
+ ".idea",
779
+ ".vscode",
780
+ "build",
781
+ "dist",
782
+ "node_modules",
783
+ "out",
784
+ "target",
785
+ "vendor",
786
+ ]);
787
+ const queue = [srcDir];
788
+ const matches = new Set();
789
+ let packageJsonCount = 0;
790
+ let currentIndex = 0;
791
+ while (
792
+ currentIndex < queue.length &&
793
+ packageJsonCount < MAX_MONOREPO_PACKAGE_JSON_FILES
794
+ ) {
795
+ if (currentIndex >= MAX_MONOREPO_DIRECTORIES) {
796
+ break;
797
+ }
798
+ const currentDir = queue[currentIndex];
799
+ currentIndex += 1;
800
+ if (!currentDir) {
801
+ continue;
802
+ }
803
+ let entries = [];
804
+ try {
805
+ entries = fs.readdirSync(currentDir, {
806
+ withFileTypes: true,
807
+ });
808
+ } catch (_err) {
809
+ continue;
810
+ }
811
+ for (const entry of entries) {
812
+ if (entry.isDirectory()) {
813
+ if (skipDirectories.has(entry.name)) {
814
+ continue;
815
+ }
816
+ queue.push(path.join(currentDir, entry.name));
817
+ continue;
818
+ }
819
+ if (!entry.isFile() || entry.name !== "package.json") {
820
+ continue;
821
+ }
822
+ packageJsonCount += 1;
823
+ const packageJsonPath = path.join(currentDir, entry.name);
824
+ try {
825
+ const pkgJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
826
+ if (uniquePackageNameCandidates.includes(pkgJson?.name)) {
827
+ matches.add(currentDir);
828
+ }
829
+ } catch (_err) {
830
+ // Ignore invalid package.json files in monorepos.
831
+ }
832
+ }
833
+ }
834
+ if (!matches.size) {
835
+ return undefined;
836
+ }
837
+ const dedupedMatches = [...matches];
838
+ dedupedMatches.sort((a, b) => a.length - b.length);
839
+ return dedupedMatches[0];
840
+ }
841
+
842
+ /**
843
+ * Normalize repository URL values from registry metadata to a cloneable URL.
844
+ *
845
+ * @param {string|undefined} candidateUrl raw URL candidate
846
+ * @returns {string|undefined} normalized URL
847
+ */
848
+ function normalizeRepositoryUrl(candidateUrl) {
849
+ if (!candidateUrl || typeof candidateUrl !== "string") {
850
+ return undefined;
851
+ }
852
+ let repoUrl = candidateUrl.trim();
853
+ if (!repoUrl) {
854
+ return undefined;
855
+ }
856
+ if (/^git\s+/.test(repoUrl)) {
857
+ repoUrl = repoUrl.replace(/^git\s+/, "git+");
858
+ }
859
+ if (repoUrl.startsWith("git+")) {
860
+ repoUrl = repoUrl.slice(4);
861
+ }
862
+ if (repoUrl.startsWith("scm:git:")) {
863
+ repoUrl = repoUrl.slice(8);
864
+ }
865
+ if (repoUrl.startsWith("github:")) {
866
+ repoUrl = `https://github.com/${repoUrl.slice("github:".length)}`;
867
+ }
868
+ if (repoUrl.startsWith("gitlab:")) {
869
+ repoUrl = `https://gitlab.com/${repoUrl.slice("gitlab:".length)}`;
870
+ }
871
+ if (repoUrl.startsWith("bitbucket:")) {
872
+ repoUrl = `https://bitbucket.org/${repoUrl.slice("bitbucket:".length)}`;
873
+ }
874
+ if (
875
+ !repoUrl.includes("://") &&
876
+ /^(?:[^/]+\.)?github\.com\/.+/.test(repoUrl)
877
+ ) {
878
+ repoUrl = `https://${repoUrl}`;
879
+ }
880
+ if (!repoUrl.includes("://") && repoUrl.startsWith("www.")) {
881
+ repoUrl = `https://${repoUrl}`;
882
+ }
883
+ const hashIndex = repoUrl.indexOf("#");
884
+ if (hashIndex > -1) {
885
+ repoUrl = repoUrl.slice(0, hashIndex);
886
+ }
887
+ return repoUrl;
888
+ }
889
+
890
+ /**
891
+ * Normalize repository URL values represented as string/object metadata fields.
892
+ *
893
+ * @param {string|Object|undefined} candidate repository field value
894
+ * @returns {string|undefined} normalized URL
895
+ */
896
+ function normalizeRepositoryObject(candidate) {
897
+ if (!candidate) {
898
+ return undefined;
899
+ }
900
+ if (typeof candidate === "string") {
901
+ return normalizeRepositoryUrl(candidate);
902
+ }
903
+ if (typeof candidate === "object") {
904
+ return normalizeRepositoryUrl(candidate.url);
905
+ }
906
+ return undefined;
907
+ }
908
+
909
+ /**
910
+ * Build a cloneable repository URL from known download URL patterns.
911
+ *
912
+ * @param {string|undefined} candidateUrl raw download URL
913
+ * @returns {string|undefined} normalized repository URL
914
+ */
915
+ function normalizeDownloadRepositoryUrl(candidateUrl) {
916
+ const normalized = normalizeRepositoryUrl(candidateUrl);
917
+ if (!normalized) {
918
+ return undefined;
919
+ }
920
+ let parsed;
921
+ try {
922
+ parsed = new URL(normalized);
923
+ } catch (_err) {
924
+ return undefined;
925
+ }
926
+ const segments = parsed.pathname.split("/").filter(Boolean);
927
+ if (parsed.hostname === "github.com" && segments.length >= 2) {
928
+ return `https://github.com/${segments[0]}/${segments[1]}`;
929
+ }
930
+ if (parsed.hostname === "codeload.github.com" && segments.length >= 2) {
931
+ return `https://github.com/${segments[0]}/${segments[1]}`;
932
+ }
933
+ if (parsed.hostname === "gitlab.com" && segments.length >= 2) {
934
+ return `https://gitlab.com/${segments[0]}/${segments[1]}`;
935
+ }
936
+ if (normalized.endsWith(".git")) {
937
+ return normalized;
938
+ }
939
+ return undefined;
940
+ }
941
+
942
+ /**
943
+ * Build package name key for registry lookup from a parsed package URL.
944
+ *
945
+ * @param {PackageURL} purlObj parsed package URL object
946
+ * @returns {string} package name suitable for registry API lookup
947
+ */
948
+ function packageNameForLookup(purlObj) {
949
+ const namespace = purlObj.namespace;
950
+ if (!namespace) {
951
+ return purlObj.name;
952
+ }
953
+ return `${namespace}/${purlObj.name}`;
954
+ }
955
+
956
+ /**
957
+ * Validate package URL source input and return an error object when invalid.
958
+ *
959
+ * @param {string} purlString package URL string
960
+ * @returns {{status:number,error:string,details:string}|null} validation error or null
961
+ */
962
+ export function validatePurlSource(purlString) {
963
+ if (!maybePurlSource(purlString)) {
964
+ return null;
965
+ }
966
+ let purlObj;
967
+ try {
968
+ purlObj = Purl.parse(purlString);
969
+ } catch (_err) {
970
+ return {
971
+ status: 400,
972
+ error: "Invalid purl source",
973
+ details: "The provided package URL is malformed.",
974
+ };
975
+ }
976
+ const purlType = purlObj?.type;
977
+ if (!SUPPORTED_PURL_SOURCE_TYPES.includes(purlType)) {
978
+ return {
979
+ status: 400,
980
+ error: "Unsupported purl source type",
981
+ details: `Supported purl types for automatic git URL detection: ${SUPPORTED_PURL_SOURCE_TYPES.join(", ")}.`,
982
+ };
983
+ }
984
+ if (!purlObj?.name) {
985
+ return {
986
+ status: 400,
987
+ error: "Invalid purl source",
988
+ details: "The provided package URL does not include a package name.",
989
+ };
990
+ }
991
+ const purlQualifiers = purlObj?.qualifiers || {};
992
+ if (
993
+ ["github", "bitbucket", "maven", "composer"].includes(purlType) &&
994
+ !purlObj?.namespace
995
+ ) {
996
+ return {
997
+ status: 400,
998
+ error: "Invalid purl source",
999
+ details: `The provided ${purlType} package URL must include a namespace.`,
1000
+ };
1001
+ }
1002
+ if (purlType === "maven" && !purlObj?.version) {
1003
+ return {
1004
+ status: 400,
1005
+ error: "Invalid purl source",
1006
+ details: "The provided maven package URL must include a version.",
1007
+ };
1008
+ }
1009
+ if (
1010
+ purlType === "generic" &&
1011
+ !purlQualifiers.vcs_url &&
1012
+ !purlQualifiers.download_url
1013
+ ) {
1014
+ return {
1015
+ status: 400,
1016
+ error: "Unsupported generic purl source",
1017
+ details:
1018
+ "generic purl sources must include a vcs_url or download_url qualifier.",
1019
+ };
1020
+ }
1021
+ return null;
1022
+ }
1023
+
1024
+ /**
1025
+ * Resolve a git repository URL from a package URL by querying package registries.
1026
+ *
1027
+ * Supported purl types:
1028
+ * - npm -> registry.npmjs.org
1029
+ * - pypi -> pypi.org
1030
+ * - gem -> rubygems.org
1031
+ * - cargo -> crates.io
1032
+ * - pub -> pub.dev
1033
+ * - github -> github.com/{namespace}/{name}
1034
+ * - bitbucket -> bitbucket.org/{namespace}/{name}
1035
+ * - maven -> repo1.maven.org POM scm metadata
1036
+ * - composer -> repo.packagist.org p2 metadata
1037
+ * - generic -> qualifiers: vcs_url, download_url
1038
+ *
1039
+ * `fetchPomXmlAsJson` is injected rather than imported because it is
1040
+ * maven-specific and lives a layer above this module. Every maven resolution
1041
+ * needs it, so it is required rather than optional: omitting it would silently
1042
+ * turn every maven purl into an unresolvable one.
1043
+ *
1044
+ * @param {string} purlString package URL string
1045
+ * @param {{ fetchPomXmlAsJson?: Function }} [helpers] injected registry fetchers
1046
+ * @returns {Promise<{repoUrl:string|undefined, registry:string|undefined, type:string}|undefined>} resolution result
1047
+ */
1048
+ /**
1049
+ * The registry document `resolveGitUrlFromPurl` reads for a purl.
1050
+ *
1051
+ * Extracted so the batch round and the resolution switch cannot drift apart: a
1052
+ * prefetch that spelled a URL even slightly differently would fetch documents
1053
+ * nobody reads and leave the switch making its own serial request. Types that
1054
+ * need no network (`github`, `bitbucket`, `generic`) and `maven`, whose POM is
1055
+ * fetched through an injected helper with its own prefetch, return undefined.
1056
+ *
1057
+ * @param {Object} purlObj Parsed purl.
1058
+ * @returns {{registry: string, url: string, accept?: string}|undefined}
1059
+ */
1060
+ function registryLookupForPurl(purlObj) {
1061
+ const packageName = packageNameForLookup(purlObj);
1062
+ const packageVersion = purlObj.version;
1063
+ switch (purlObj.type) {
1064
+ case "npm": {
1065
+ const registry =
1066
+ readEnvironmentVariable("NPM_URL") || "https://registry.npmjs.org/";
1067
+ return { registry, url: `${registry}${packageName}` };
1068
+ }
1069
+ case "pypi": {
1070
+ const registry =
1071
+ readEnvironmentVariable("PYPI_URL") || "https://pypi.org/pypi/";
1072
+ const suffix = packageVersion
1073
+ ? `${purlObj.name}/${packageVersion}/json`
1074
+ : `${purlObj.name}/json`;
1075
+ return { registry, url: `${registry}${suffix}` };
1076
+ }
1077
+ case "gem": {
1078
+ const v1Url =
1079
+ readEnvironmentVariable("RUBYGEMS_V1_URL") ||
1080
+ "https://rubygems.org/api/v1/gems/";
1081
+ const v2Url =
1082
+ readEnvironmentVariable("RUBYGEMS_V2_URL") ||
1083
+ "https://rubygems.org/api/v2/rubygems/";
1084
+ return {
1085
+ registry: packageVersion ? v2Url : v1Url,
1086
+ url: packageVersion
1087
+ ? `${v2Url}${purlObj.name}/versions/${packageVersion}.json`
1088
+ : `${v1Url}${purlObj.name}.json`,
1089
+ };
1090
+ }
1091
+ case "cargo": {
1092
+ const registry =
1093
+ readEnvironmentVariable("RUST_CRATES_URL") ||
1094
+ "https://crates.io/api/v1/crates/";
1095
+ return { registry, url: `${registry}${purlObj.name}` };
1096
+ }
1097
+ case "pub": {
1098
+ const registry =
1099
+ readEnvironmentVariable("PUB_DEV_URL") || "https://pub.dev";
1100
+ return {
1101
+ accept: "application/vnd.pub.v2+json",
1102
+ registry,
1103
+ url: packageVersion
1104
+ ? `${registry}/api/packages/${purlObj.name}/versions/${packageVersion}`
1105
+ : `${registry}/api/packages/${purlObj.name}`,
1106
+ };
1107
+ }
1108
+ case "composer": {
1109
+ const packagistUrl =
1110
+ readEnvironmentVariable("PACKAGIST_URL") ||
1111
+ "https://repo.packagist.org/p2/";
1112
+ const registry = packagistUrl.endsWith("/")
1113
+ ? packagistUrl
1114
+ : `${packagistUrl}/`;
1115
+ return { registry, url: `${registry}${packageName}.json` };
1116
+ }
1117
+ default:
1118
+ return undefined;
1119
+ }
1120
+ }
1121
+
1122
+ /**
1123
+ * Registry documents, prefetched by {@link prefetchGitUrlSources}.
1124
+ *
1125
+ * Module state rather than a parameter because `resolveGitUrlFromPurl` takes
1126
+ * one purl and is called from three places; threading a map through them would
1127
+ * be a wide change for no gain. A miss means the lookup issues its own request.
1128
+ */
1129
+ let gitUrlSourcePrefetch = new Map();
1130
+
1131
+ /**
1132
+ * Discard prefetched registry documents. Tests only.
1133
+ */
1134
+ export function resetGitUrlSourcePrefetch() {
1135
+ gitUrlSourcePrefetch = new Map();
1136
+ }
1137
+
1138
+ /**
1139
+ * Prefetch the registry documents a list of purls will be resolved from.
1140
+ *
1141
+ * `resolveGitUrlFromPurl` takes a single purl, so on its own it can only ever
1142
+ * make one request at a time. Callers that know the whole list up front — the
1143
+ * predictive audit knows every target before it starts — can hand it over here
1144
+ * and have the documents fetched in one round instead.
1145
+ *
1146
+ * @param {Array<string>} purlStrings Purls about to be resolved. Duplicates,
1147
+ * empties and unparseable entries are fine.
1148
+ * @returns {Promise<void>}
1149
+ */
1150
+ export async function prefetchGitUrlSources(purlStrings) {
1151
+ if (!prefetchEnabled() || !Array.isArray(purlStrings)) {
1152
+ return;
1153
+ }
1154
+ const requests = [];
1155
+ const seen = new Set();
1156
+ for (const purlString of purlStrings) {
1157
+ const purlObj = parsePurlForSourceResolution(purlString);
1158
+ if (!purlObj) {
1159
+ continue;
1160
+ }
1161
+ const lookup = registryLookupForPurl(purlObj);
1162
+ if (!lookup || seen.has(lookup.url)) {
1163
+ continue;
1164
+ }
1165
+ seen.add(lookup.url);
1166
+ requests.push({
1167
+ ...(lookup.accept ? { accept: lookup.accept } : {}),
1168
+ url: lookup.url,
1169
+ });
1170
+ }
1171
+ if (!requests.length) {
1172
+ return;
1173
+ }
1174
+ for (const [key, value] of await prefetchJson(requests)) {
1175
+ gitUrlSourcePrefetch.set(key, value);
1176
+ }
1177
+ }
1178
+
1179
+ /**
1180
+ * Read a registry document, from the batch round when it ran.
1181
+ *
1182
+ * @param {{url: string, accept?: string}} lookup
1183
+ * @returns {Promise<Object>} A response-shaped object with a `body`.
1184
+ */
1185
+ async function fetchRegistryDocument(lookup) {
1186
+ return (
1187
+ prefetchedResponse(gitUrlSourcePrefetch, lookup.url) ||
1188
+ (await cdxgenAgent.get(lookup.url, {
1189
+ ...(lookup.accept ? { headers: { Accept: lookup.accept } } : {}),
1190
+ responseType: "json",
1191
+ }))
1192
+ );
1193
+ }
1194
+
1195
+ /**
1196
+ * Parse a purl for source resolution, applying the same guards and qualifier
1197
+ * normalization {@link resolveGitUrlFromPurl} applies.
1198
+ *
1199
+ * @param {string} purlString
1200
+ * @returns {Object|undefined} Parsed purl, or undefined when unusable.
1201
+ */
1202
+ function parsePurlForSourceResolution(purlString) {
1203
+ if (!maybePurlSource(purlString) || validatePurlSource(purlString)) {
1204
+ return undefined;
1205
+ }
1206
+ let purlObj;
1207
+ try {
1208
+ // Some purls in the wild use unencoded + in qualifier values (e.g.
1209
+ // git+https:// in vcs_url). cdx-purl requires percent-encoding; normalize
1210
+ // the qualifier section before parsing so real-world purls resolve.
1211
+ const qIdx = purlString.indexOf("?");
1212
+ const safePurlString =
1213
+ qIdx >= 0
1214
+ ? purlString.slice(0, qIdx + 1) +
1215
+ purlString.slice(qIdx + 1).replaceAll("+", "%2B")
1216
+ : purlString;
1217
+ purlObj = Purl.parse(safePurlString);
1218
+ } catch (err) {
1219
+ if (DEBUG_MODE) {
1220
+ const errorMessage = err?.message || String(err);
1221
+ thoughtLog("Unable to resolve repository URL for purl.", {
1222
+ purlString,
1223
+ errorMessage,
1224
+ });
1225
+ }
1226
+ return undefined;
1227
+ }
1228
+ if (!purlObj?.type || !purlObj?.name) {
1229
+ return undefined;
1230
+ }
1231
+ return purlObj;
1232
+ }
1233
+
1234
+ /**
1235
+ * Resolve source repository details for a package from its purl.
1236
+ *
1237
+ * Queries the package registry (or constructs the URL directly for VCS-hosted
1238
+ * purl types) and normalizes the repository or homepage URL found in registry
1239
+ * metadata. Network and lookup failures are logged and yield `undefined`.
1240
+ *
1241
+ * @param {string} purlString Package URL string
1242
+ * @param {Object} [helpers={}] Injected registry helpers (e.g. `fetchPomXmlAsJson` required for maven)
1243
+ * @returns {Promise<{type: string, registry: string, repoUrl: string, version: string, namespace: string, name: string}|undefined>} Resolved source details, or `undefined` when no remote repository URL could be resolved
1244
+ */
1245
+ export async function resolveGitUrlFromPurl(purlString, helpers = {}) {
1246
+ const purlObj = parsePurlForSourceResolution(purlString);
1247
+ if (!purlObj) {
1248
+ return undefined;
1249
+ }
1250
+
1251
+ const packageName = packageNameForLookup(purlObj);
1252
+ const packageVersion = purlObj.version;
1253
+ let repoUrl;
1254
+ let registry;
1255
+ const logPurlResolutionError = (err) => {
1256
+ const errorMessage = err?.message || String(err);
1257
+ const errorDetails = [];
1258
+ if (err?.code) {
1259
+ errorDetails.push(`code=${err.code}`);
1260
+ }
1261
+ if (typeof err?.statusCode === "number") {
1262
+ errorDetails.push(`status=${err.statusCode}`);
1263
+ }
1264
+ if (err?.hostname) {
1265
+ errorDetails.push(`host=${err.hostname}`);
1266
+ }
1267
+ const sanitizedRegistry = sanitizeRemoteUrlForLogs(registry);
1268
+ console.error(
1269
+ `Unable to resolve repository URL for purl '${purlString}'${sanitizedRegistry ? ` using registry '${sanitizedRegistry}'` : ""}: ${errorMessage}${errorDetails.length ? ` (${errorDetails.join(", ")})` : ""}`,
1270
+ );
1271
+ if (DEBUG_MODE) {
1272
+ thoughtLog("Unable to resolve repository URL for purl.", {
1273
+ purlString,
1274
+ errorMessage,
1275
+ errorDetails,
1276
+ registry: sanitizedRegistry,
1277
+ });
1278
+ }
1279
+ };
1280
+
1281
+ try {
1282
+ switch (purlObj.type) {
1283
+ case "npm": {
1284
+ const lookup = registryLookupForPurl(purlObj);
1285
+ registry = lookup.registry;
1286
+ const res = await fetchRegistryDocument(lookup);
1287
+ const body = res.body;
1288
+ const versionBody = packageVersion
1289
+ ? body.versions?.[packageVersion]
1290
+ : undefined;
1291
+ repoUrl =
1292
+ normalizeRepositoryObject(versionBody?.repository) ||
1293
+ normalizeRepositoryObject(body.repository) ||
1294
+ normalizeRepositoryUrl(versionBody?.homepage) ||
1295
+ normalizeRepositoryUrl(body.homepage);
1296
+ break;
1297
+ }
1298
+ case "pypi": {
1299
+ const lookup = registryLookupForPurl(purlObj);
1300
+ registry = lookup.registry;
1301
+ const res = await fetchRegistryDocument(lookup);
1302
+ const info = res.body?.info || {};
1303
+ const projectUrls = info.project_urls || {};
1304
+ repoUrl =
1305
+ normalizeRepositoryUrl(projectUrls.Source) ||
1306
+ normalizeRepositoryUrl(projectUrls.Repository) ||
1307
+ normalizeRepositoryUrl(projectUrls["Source Code"]) ||
1308
+ normalizeRepositoryUrl(projectUrls.Code) ||
1309
+ normalizeRepositoryUrl(info.home_page);
1310
+ break;
1311
+ }
1312
+ case "gem": {
1313
+ const lookup = registryLookupForPurl(purlObj);
1314
+ registry = lookup.registry;
1315
+ const res = await fetchRegistryDocument(lookup);
1316
+ const body = Array.isArray(res.body) ? res.body[0] : res.body;
1317
+ repoUrl =
1318
+ normalizeRepositoryUrl(body?.metadata?.source_code_uri) ||
1319
+ normalizeRepositoryUrl(body?.source_code_uri) ||
1320
+ normalizeRepositoryUrl(body?.homepage_uri);
1321
+ break;
1322
+ }
1323
+ case "cargo": {
1324
+ const lookup = registryLookupForPurl(purlObj);
1325
+ registry = lookup.registry;
1326
+ const res = await fetchRegistryDocument(lookup);
1327
+ repoUrl = normalizeRepositoryUrl(res.body?.crate?.repository);
1328
+ break;
1329
+ }
1330
+ case "pub": {
1331
+ const lookup = registryLookupForPurl(purlObj);
1332
+ registry = lookup.registry;
1333
+ const res = await fetchRegistryDocument(lookup);
1334
+ const pubspec = res.body?.pubspec || res.body?.latest?.pubspec || {};
1335
+ repoUrl =
1336
+ normalizeRepositoryUrl(pubspec.repository) ||
1337
+ normalizeRepositoryUrl(pubspec.homepage);
1338
+ break;
1339
+ }
1340
+ case "github": {
1341
+ registry = "https://github.com";
1342
+ if (purlObj.namespace) {
1343
+ repoUrl = normalizeRepositoryUrl(
1344
+ `${registry}/${purlObj.namespace}/${purlObj.name}`,
1345
+ );
1346
+ }
1347
+ break;
1348
+ }
1349
+ case "bitbucket": {
1350
+ registry = "https://bitbucket.org";
1351
+ if (purlObj.namespace) {
1352
+ repoUrl = normalizeRepositoryUrl(
1353
+ `${registry}/${purlObj.namespace}/${purlObj.name}`,
1354
+ );
1355
+ }
1356
+ break;
1357
+ }
1358
+ case "maven": {
1359
+ if (!purlObj.namespace || !packageVersion) {
1360
+ break;
1361
+ }
1362
+ const mavenCentralUrl =
1363
+ readEnvironmentVariable("MAVEN_CENTRAL_URL") ||
1364
+ "https://repo1.maven.org/maven2/";
1365
+ registry = mavenCentralUrl.endsWith("/")
1366
+ ? mavenCentralUrl
1367
+ : `${mavenCentralUrl}/`;
1368
+ if (typeof helpers.fetchPomXmlAsJson !== "function") {
1369
+ throw new MissingRegistryHelperError(
1370
+ "resolveGitUrlFromPurl cannot resolve a maven purl without an injected fetchPomXmlAsJson.",
1371
+ );
1372
+ }
1373
+ const pomJson = await helpers.fetchPomXmlAsJson({
1374
+ urlPrefix: registry,
1375
+ group: purlObj.namespace,
1376
+ name: purlObj.name,
1377
+ version: packageVersion,
1378
+ });
1379
+ repoUrl =
1380
+ normalizeRepositoryUrl(pomJson?.scm?.url?._) ||
1381
+ normalizeRepositoryUrl(pomJson?.scm?.connection?._) ||
1382
+ normalizeRepositoryUrl(pomJson?.scm?.developerConnection?._);
1383
+ break;
1384
+ }
1385
+ case "composer": {
1386
+ const lookup = registryLookupForPurl(purlObj);
1387
+ registry = lookup.registry;
1388
+ const res = await fetchRegistryDocument(lookup);
1389
+ const packageVersions = res.body?.packages?.[packageName];
1390
+ if (!Array.isArray(packageVersions) || !packageVersions.length) {
1391
+ break;
1392
+ }
1393
+ const selectedVersion = packageVersion
1394
+ ? packageVersions.find(
1395
+ (v) =>
1396
+ v?.version === packageVersion ||
1397
+ v?.version_normalized === packageVersion,
1398
+ )
1399
+ : packageVersions[0];
1400
+ repoUrl =
1401
+ normalizeRepositoryUrl(selectedVersion?.source?.url) ||
1402
+ normalizeRepositoryUrl(selectedVersion?.homepage);
1403
+ break;
1404
+ }
1405
+ case "generic": {
1406
+ const genericVcsUrl = purlObj.qualifiers?.vcs_url;
1407
+ const genericDownloadUrl = purlObj.qualifiers?.download_url;
1408
+ repoUrl =
1409
+ normalizeRepositoryUrl(genericVcsUrl) ||
1410
+ normalizeDownloadRepositoryUrl(genericDownloadUrl);
1411
+ break;
1412
+ }
1413
+ default:
1414
+ return undefined;
1415
+ }
1416
+ } catch (err) {
1417
+ // Network and registry failures are expected and non-fatal. A missing
1418
+ // injected helper is a wiring bug in the caller, so it must not be
1419
+ // swallowed by the same handler.
1420
+ if (err instanceof MissingRegistryHelperError) {
1421
+ throw err;
1422
+ }
1423
+ logPurlResolutionError(err);
1424
+ return undefined;
1425
+ }
1426
+
1427
+ if (!repoUrl) {
1428
+ return undefined;
1429
+ }
1430
+ if (!maybeRemotePath(repoUrl)) {
1431
+ if (DEBUG_MODE) {
1432
+ console.log(
1433
+ `Ignoring non-remote repository URL '${repoUrl}' from purl lookup.`,
1434
+ );
1435
+ }
1436
+ return undefined;
1437
+ }
1438
+
1439
+ return {
1440
+ type: purlObj.type,
1441
+ registry,
1442
+ repoUrl,
1443
+ version: purlObj.version,
1444
+ namespace: purlObj.namespace,
1445
+ name: purlObj.name,
1446
+ };
1447
+ }
1448
+
1449
+ /**
1450
+ * Clean up cloned source directories.
1451
+ *
1452
+ * @param {string} srcDir directory path to remove
1453
+ */
1454
+ export function cleanupSourceDir(srcDir) {
1455
+ const normalizePath = (candidatePath) => {
1456
+ if (!candidatePath) {
1457
+ return undefined;
1458
+ }
1459
+ try {
1460
+ return fs.realpathSync.native
1461
+ ? fs.realpathSync.native(candidatePath)
1462
+ : fs.realpathSync(candidatePath);
1463
+ } catch {
1464
+ return path.resolve(candidatePath);
1465
+ }
1466
+ };
1467
+ const normalizedSrcDir = normalizePath(srcDir);
1468
+ const tempRoots = [getTmpDir()];
1469
+ if (process.platform !== "win32") {
1470
+ tempRoots.push("/tmp");
1471
+ tempRoots.push("/private/tmp");
1472
+ }
1473
+ const normalizedTmpDirs = tempRoots
1474
+ .map((candidatePath) => normalizePath(candidatePath))
1475
+ .filter(Boolean);
1476
+ if (
1477
+ normalizedSrcDir &&
1478
+ normalizedTmpDirs.some(
1479
+ (normalizedTmpDir) =>
1480
+ normalizedSrcDir === normalizedTmpDir ||
1481
+ normalizedSrcDir.startsWith(`${normalizedTmpDir}${path.sep}`),
1482
+ ) &&
1483
+ fs.rmSync
1484
+ ) {
1485
+ thoughtLog(`Cleaning up ${srcDir}`);
1486
+ safeRmSync(srcDir, { recursive: true, force: true });
1487
+ }
1488
+ }