@cdxgen/cdxgen 13.3.0 → 13.5.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 (372) hide show
  1. package/README.md +12 -9
  2. package/bin/cdxgen-secure.js +15 -0
  3. package/bin/cdxgen.js +115 -31
  4. package/bin/evinse.js +23 -1
  5. package/bin/hbom.js +15 -7
  6. package/bin/repl.js +115 -0
  7. package/bin/sign.js +45 -15
  8. package/bin/tracebom.js +5 -1
  9. package/bin/validate.js +84 -18
  10. package/bin/verify.js +155 -86
  11. package/data/cbomosdb-queries.json +13 -1
  12. package/data/component-tags.json +8 -0
  13. package/data/helpers/init.gradle +46 -21
  14. package/data/queries-darwin.json +25 -1
  15. package/data/queries-win.json +19 -1
  16. package/data/queries.json +41 -0
  17. package/data/remediations.json +344 -1
  18. package/data/rules/cbom-security.yaml +235 -4
  19. package/data/rules/dependency-sources.yaml +67 -0
  20. package/data/rules/go-binaries.yaml +46 -0
  21. package/data/rules/golem-go.yaml +80 -0
  22. package/data/rules/hbom-compliance.yaml +40 -22
  23. package/data/rules/hbom-performance.yaml +7 -1
  24. package/data/rules/host-topology.yaml +1 -1
  25. package/data/rules/obom-runtime.yaml +31 -2
  26. package/data/rules/php-runtime.yaml +143 -0
  27. package/data/rules/scala-evidence.yaml +115 -0
  28. package/lib/audit/index.js +52 -6
  29. package/lib/cli/bomAssembly.js +28 -3
  30. package/lib/cli/cliOptions.js +110 -3
  31. package/lib/cli/index.js +186 -58
  32. package/lib/cli/jsBom.js +50 -29
  33. package/lib/cli/jvmBom.js +779 -146
  34. package/lib/cli/managedBom.js +1021 -261
  35. package/lib/cli/nativeBom.js +364 -58
  36. package/lib/core/activity.js +12 -0
  37. package/lib/core/env.js +47 -17
  38. package/lib/core/fs.js +31 -21
  39. package/lib/core/httpClient.js +233 -69
  40. package/lib/core/pluginRun.js +184 -0
  41. package/lib/core/processTree.js +100 -0
  42. package/lib/core/projectConfig.js +1 -0
  43. package/lib/core/projectTooling.js +97 -0
  44. package/lib/core/propertySanitizer.js +72 -0
  45. package/lib/core/runState.js +39 -0
  46. package/lib/core/toml.js +72 -0
  47. package/lib/ecosystems/asarutils.js +4 -2
  48. package/lib/ecosystems/bunutils.js +5 -7
  49. package/lib/ecosystems/cargoCache.js +231 -8
  50. package/lib/ecosystems/cmakeResolver.js +10 -21
  51. package/lib/ecosystems/cppBuildContext.js +631 -0
  52. package/lib/ecosystems/cppEvidence.js +337 -22
  53. package/lib/ecosystems/cppIncludeResolver.js +294 -0
  54. package/lib/ecosystems/denoutils.js +93 -66
  55. package/lib/ecosystems/ecosystems.js +1967 -788
  56. package/lib/ecosystems/golem.js +578 -18
  57. package/lib/ecosystems/gradleutils.js +340 -46
  58. package/lib/ecosystems/jsEvidence.js +85 -24
  59. package/lib/ecosystems/kosi.js +21 -4
  60. package/lib/ecosystems/npmutils.js +64 -0
  61. package/lib/ecosystems/parsers-dotnet.js +668 -153
  62. package/lib/ecosystems/parsers-elm.js +46 -28
  63. package/lib/ecosystems/parsers-gleam.js +3 -4
  64. package/lib/ecosystems/parsers-go.js +1283 -297
  65. package/lib/ecosystems/parsers-js.js +92 -26
  66. package/lib/ecosystems/parsers-julia.js +2 -3
  67. package/lib/ecosystems/parsers-jvm.js +463 -29
  68. package/lib/ecosystems/parsers-misc.js +405 -93
  69. package/lib/ecosystems/parsers-python.js +152 -20
  70. package/lib/ecosystems/parsers-rust.js +4 -4
  71. package/lib/ecosystems/parsers-terraform.js +1573 -19
  72. package/lib/ecosystems/pythonutils.js +102 -6
  73. package/lib/ecosystems/remote/huggingface.js +3 -0
  74. package/lib/ecosystems/rubyutils.js +73 -20
  75. package/lib/ecosystems/rusi.js +32 -9
  76. package/lib/ecosystems/sbtutils.js +243 -187
  77. package/lib/ecosystems/scalacliutils.js +343 -0
  78. package/lib/ecosystems/scalasem.js +2620 -0
  79. package/lib/ecosystems/terraformRegistry.js +288 -0
  80. package/lib/ecosystems/utils.js +2 -0
  81. package/lib/ecosystems/vendoredCode.js +156 -0
  82. package/lib/evinser/evinser.js +695 -78
  83. package/lib/evinser/swiftsem.js +68 -5
  84. package/lib/helpers/agenticToolutils.js +2 -2
  85. package/lib/helpers/bomSigner.js +576 -128
  86. package/lib/inventory/agentSkillSpec.js +17 -0
  87. package/lib/inventory/aiCollector.js +4 -1
  88. package/lib/inventory/analyzer.js +110 -127
  89. package/lib/inventory/apkInstalledDb.js +243 -0
  90. package/lib/inventory/atomUtils.js +204 -48
  91. package/lib/inventory/auditCategories.js +10 -3
  92. package/lib/inventory/buildToolRateLimit.js +144 -0
  93. package/lib/inventory/cacheCommands.js +2 -1
  94. package/lib/inventory/cacheDir.js +52 -9
  95. package/lib/inventory/certificates.js +2371 -0
  96. package/lib/inventory/cmakeBuildDirs.js +254 -0
  97. package/lib/inventory/communityAiConfigParser.js +4 -9
  98. package/lib/inventory/deps.js +507 -128
  99. package/lib/inventory/display.js +200 -3
  100. package/lib/inventory/dosai.js +747 -101
  101. package/lib/inventory/dosaiParsers.js +310 -15
  102. package/lib/inventory/dynamic.js +96 -8
  103. package/lib/inventory/envcontext.js +168 -5
  104. package/lib/inventory/evidenceUtils.js +590 -132
  105. package/lib/inventory/fetchBatch.js +574 -38
  106. package/lib/inventory/fetchDiskCache.js +597 -0
  107. package/lib/inventory/forgeEnricher.js +14 -5
  108. package/lib/inventory/formulationParsers.js +3 -2
  109. package/lib/inventory/goBuildInfo.js +140 -0
  110. package/lib/inventory/hbom.js +67 -7
  111. package/lib/inventory/hbomAnalysis.js +16 -0
  112. package/lib/inventory/hostTopology.js +21 -0
  113. package/lib/inventory/jvmLocalRepos.js +917 -0
  114. package/lib/inventory/mcpConfigParser.js +2 -3
  115. package/lib/inventory/osPackagePurl.js +244 -0
  116. package/lib/inventory/osPackageResolver.js +89 -87
  117. package/lib/inventory/osinfo.js +79 -31
  118. package/lib/inventory/osqueryTransform.js +114 -5
  119. package/lib/inventory/parentSelection.js +146 -0
  120. package/lib/inventory/phpBuildInfo.js +487 -0
  121. package/lib/inventory/phpHostProbe.js +641 -0
  122. package/lib/inventory/rootfsCerts.js +426 -0
  123. package/lib/inventory/rustFormulationParser.js +3 -4
  124. package/lib/inventory/scalaCoords.js +153 -0
  125. package/lib/inventory/source.js +215 -11
  126. package/lib/inventory/spdx.js +245 -0
  127. package/lib/inventory/traceRunner.js +93 -8
  128. package/lib/inventory/tracedCrypto.js +423 -0
  129. package/lib/managers/binary.js +529 -183
  130. package/lib/managers/docker.js +199 -44
  131. package/lib/managers/oci.js +24 -2
  132. package/lib/parsers/cmakeCache.js +69 -0
  133. package/lib/parsers/cmakeLists.js +16 -2
  134. package/lib/parsers/cmakePresets.js +400 -0
  135. package/lib/parsers/compileCommands.js +557 -0
  136. package/lib/parsers/email.js +277 -0
  137. package/lib/parsers/largeJson.js +34 -2
  138. package/lib/parsers/strictJson.js +322 -0
  139. package/lib/parsers/terraformConfig.js +1073 -0
  140. package/lib/parsers/terraformSource.js +652 -0
  141. package/lib/server/server.js +209 -1
  142. package/lib/stages/postgen/annotator.js +17 -1
  143. package/lib/stages/postgen/introspection/markers.js +1 -1
  144. package/lib/stages/postgen/introspection/reflect.js +4 -1
  145. package/lib/stages/postgen/postgen.js +20 -6
  146. package/lib/stages/postgen/ruleEngine.js +58 -1
  147. package/lib/stages/postgen/specVersionCompat.js +62 -0
  148. package/lib/stages/pregen/pregen.js +117 -5
  149. package/lib/validator/bomValidator.js +26 -5
  150. package/lib/validator/generated/runtime.mjs +13 -0
  151. package/lib/validator/generated/validate-1.6.mjs +26 -7
  152. package/lib/validator/generated/validate-1.7.mjs +31 -12
  153. package/lib/validator/generated/validate-2.0.mjs +30 -11
  154. package/lib/validator/index.js +25 -10
  155. package/lib/validator/reporters/json.js +1 -0
  156. package/package.json +23 -23
  157. package/types/bin/cdxgen-secure.d.ts +3 -0
  158. package/types/bin/cdxgen-secure.d.ts.map +1 -0
  159. package/types/bin/repl.d.ts.map +1 -1
  160. package/types/lib/audit/index.d.ts.map +1 -1
  161. package/types/lib/cli/bomAssembly.d.ts +9 -2
  162. package/types/lib/cli/bomAssembly.d.ts.map +1 -1
  163. package/types/lib/cli/cliOptions.d.ts +43 -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.map +1 -1
  167. package/types/lib/cli/jvmBom.d.ts +44 -1
  168. package/types/lib/cli/jvmBom.d.ts.map +1 -1
  169. package/types/lib/cli/managedBom.d.ts +7 -4
  170. package/types/lib/cli/managedBom.d.ts.map +1 -1
  171. package/types/lib/cli/nativeBom.d.ts +3 -1
  172. package/types/lib/cli/nativeBom.d.ts.map +1 -1
  173. package/types/lib/core/activity.d.ts.map +1 -1
  174. package/types/lib/core/env.d.ts +27 -2
  175. package/types/lib/core/env.d.ts.map +1 -1
  176. package/types/lib/core/fs.d.ts.map +1 -1
  177. package/types/lib/core/httpClient.d.ts +13 -8
  178. package/types/lib/core/httpClient.d.ts.map +1 -1
  179. package/types/lib/core/pluginRun.d.ts +97 -0
  180. package/types/lib/core/pluginRun.d.ts.map +1 -0
  181. package/types/lib/core/processTree.d.ts +36 -0
  182. package/types/lib/core/processTree.d.ts.map +1 -0
  183. package/types/lib/core/projectConfig.d.ts.map +1 -1
  184. package/types/lib/core/projectTooling.d.ts +41 -0
  185. package/types/lib/core/projectTooling.d.ts.map +1 -0
  186. package/types/lib/core/propertySanitizer.d.ts +26 -0
  187. package/types/lib/core/propertySanitizer.d.ts.map +1 -1
  188. package/types/lib/core/runState.d.ts +29 -0
  189. package/types/lib/core/runState.d.ts.map +1 -0
  190. package/types/lib/core/toml.d.ts +20 -0
  191. package/types/lib/core/toml.d.ts.map +1 -0
  192. package/types/lib/ecosystems/asarutils.d.ts.map +1 -1
  193. package/types/lib/ecosystems/bunutils.d.ts.map +1 -1
  194. package/types/lib/ecosystems/cargoCache.d.ts +12 -0
  195. package/types/lib/ecosystems/cargoCache.d.ts.map +1 -1
  196. package/types/lib/ecosystems/cmakeResolver.d.ts +5 -3
  197. package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -1
  198. package/types/lib/ecosystems/cppBuildContext.d.ts +55 -0
  199. package/types/lib/ecosystems/cppBuildContext.d.ts.map +1 -0
  200. package/types/lib/ecosystems/cppEvidence.d.ts +19 -3
  201. package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
  202. package/types/lib/ecosystems/cppIncludeResolver.d.ts +92 -0
  203. package/types/lib/ecosystems/cppIncludeResolver.d.ts.map +1 -0
  204. package/types/lib/ecosystems/denoutils.d.ts +9 -3
  205. package/types/lib/ecosystems/denoutils.d.ts.map +1 -1
  206. package/types/lib/ecosystems/ecosystems.d.ts +62 -13
  207. package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
  208. package/types/lib/ecosystems/golem.d.ts +81 -1
  209. package/types/lib/ecosystems/golem.d.ts.map +1 -1
  210. package/types/lib/ecosystems/gradleutils.d.ts +59 -7
  211. package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
  212. package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
  213. package/types/lib/ecosystems/kosi.d.ts.map +1 -1
  214. package/types/lib/ecosystems/npmutils.d.ts +15 -0
  215. package/types/lib/ecosystems/npmutils.d.ts.map +1 -1
  216. package/types/lib/ecosystems/parsers-dotnet.d.ts +155 -5
  217. package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
  218. package/types/lib/ecosystems/parsers-elm.d.ts.map +1 -1
  219. package/types/lib/ecosystems/parsers-gleam.d.ts.map +1 -1
  220. package/types/lib/ecosystems/parsers-go.d.ts +119 -5
  221. package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
  222. package/types/lib/ecosystems/parsers-js.d.ts +6 -1
  223. package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
  224. package/types/lib/ecosystems/parsers-julia.d.ts.map +1 -1
  225. package/types/lib/ecosystems/parsers-jvm.d.ts +74 -3
  226. package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
  227. package/types/lib/ecosystems/parsers-misc.d.ts +21 -59
  228. package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
  229. package/types/lib/ecosystems/parsers-python.d.ts +57 -6
  230. package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
  231. package/types/lib/ecosystems/parsers-terraform.d.ts +38 -21
  232. package/types/lib/ecosystems/parsers-terraform.d.ts.map +1 -1
  233. package/types/lib/ecosystems/pythonutils.d.ts +26 -1
  234. package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
  235. package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -1
  236. package/types/lib/ecosystems/rubyutils.d.ts +21 -1
  237. package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
  238. package/types/lib/ecosystems/rusi.d.ts.map +1 -1
  239. package/types/lib/ecosystems/sbtutils.d.ts +88 -2
  240. package/types/lib/ecosystems/sbtutils.d.ts.map +1 -1
  241. package/types/lib/ecosystems/scalacliutils.d.ts +56 -0
  242. package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -0
  243. package/types/lib/ecosystems/scalasem.d.ts +311 -0
  244. package/types/lib/ecosystems/scalasem.d.ts.map +1 -0
  245. package/types/lib/ecosystems/terraformRegistry.d.ts +9 -0
  246. package/types/lib/ecosystems/terraformRegistry.d.ts.map +1 -0
  247. package/types/lib/ecosystems/utils.d.ts +2 -2
  248. package/types/lib/ecosystems/utils.d.ts.map +1 -1
  249. package/types/lib/ecosystems/vendoredCode.d.ts +32 -0
  250. package/types/lib/ecosystems/vendoredCode.d.ts.map +1 -0
  251. package/types/lib/evinser/evinser.d.ts +100 -8
  252. package/types/lib/evinser/evinser.d.ts.map +1 -1
  253. package/types/lib/evinser/swiftsem.d.ts +10 -0
  254. package/types/lib/evinser/swiftsem.d.ts.map +1 -1
  255. package/types/lib/helpers/bomSigner.d.ts +80 -4
  256. package/types/lib/helpers/bomSigner.d.ts.map +1 -1
  257. package/types/lib/inventory/agentSkillSpec.d.ts +13 -0
  258. package/types/lib/inventory/agentSkillSpec.d.ts.map +1 -0
  259. package/types/lib/inventory/aiCollector.d.ts.map +1 -1
  260. package/types/lib/inventory/analyzer.d.ts.map +1 -1
  261. package/types/lib/inventory/apkInstalledDb.d.ts +42 -0
  262. package/types/lib/inventory/apkInstalledDb.d.ts.map +1 -0
  263. package/types/lib/inventory/atomUtils.d.ts +96 -10
  264. package/types/lib/inventory/atomUtils.d.ts.map +1 -1
  265. package/types/lib/inventory/auditCategories.d.ts +3 -0
  266. package/types/lib/inventory/auditCategories.d.ts.map +1 -1
  267. package/types/lib/inventory/buildToolRateLimit.d.ts +38 -0
  268. package/types/lib/inventory/buildToolRateLimit.d.ts.map +1 -0
  269. package/types/lib/inventory/cacheCommands.d.ts +2 -1
  270. package/types/lib/inventory/cacheCommands.d.ts.map +1 -1
  271. package/types/lib/inventory/cacheDir.d.ts +12 -4
  272. package/types/lib/inventory/cacheDir.d.ts.map +1 -1
  273. package/types/lib/inventory/certificates.d.ts +205 -0
  274. package/types/lib/inventory/certificates.d.ts.map +1 -0
  275. package/types/lib/inventory/cmakeBuildDirs.d.ts +58 -0
  276. package/types/lib/inventory/cmakeBuildDirs.d.ts.map +1 -0
  277. package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
  278. package/types/lib/inventory/deps.d.ts +61 -2
  279. package/types/lib/inventory/deps.d.ts.map +1 -1
  280. package/types/lib/inventory/display.d.ts +18 -0
  281. package/types/lib/inventory/display.d.ts.map +1 -1
  282. package/types/lib/inventory/dosai.d.ts +202 -14
  283. package/types/lib/inventory/dosai.d.ts.map +1 -1
  284. package/types/lib/inventory/dosaiParsers.d.ts +53 -7
  285. package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
  286. package/types/lib/inventory/dynamic.d.ts +16 -1
  287. package/types/lib/inventory/dynamic.d.ts.map +1 -1
  288. package/types/lib/inventory/envcontext.d.ts +40 -2
  289. package/types/lib/inventory/envcontext.d.ts.map +1 -1
  290. package/types/lib/inventory/evidenceUtils.d.ts +48 -14
  291. package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
  292. package/types/lib/inventory/fetchBatch.d.ts +83 -14
  293. package/types/lib/inventory/fetchBatch.d.ts.map +1 -1
  294. package/types/lib/inventory/fetchDiskCache.d.ts +169 -0
  295. package/types/lib/inventory/fetchDiskCache.d.ts.map +1 -0
  296. package/types/lib/inventory/forgeEnricher.d.ts.map +1 -1
  297. package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
  298. package/types/lib/inventory/goBuildInfo.d.ts +10 -0
  299. package/types/lib/inventory/goBuildInfo.d.ts.map +1 -0
  300. package/types/lib/inventory/hbom.d.ts.map +1 -1
  301. package/types/lib/inventory/hbomAnalysis.d.ts +10 -0
  302. package/types/lib/inventory/hbomAnalysis.d.ts.map +1 -1
  303. package/types/lib/inventory/hostTopology.d.ts.map +1 -1
  304. package/types/lib/inventory/jvmLocalRepos.d.ts +178 -0
  305. package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -0
  306. package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
  307. package/types/lib/inventory/osPackagePurl.d.ts +99 -0
  308. package/types/lib/inventory/osPackagePurl.d.ts.map +1 -0
  309. package/types/lib/inventory/osPackageResolver.d.ts +6 -2
  310. package/types/lib/inventory/osPackageResolver.d.ts.map +1 -1
  311. package/types/lib/inventory/osinfo.d.ts +31 -6
  312. package/types/lib/inventory/osinfo.d.ts.map +1 -1
  313. package/types/lib/inventory/osqueryTransform.d.ts +51 -0
  314. package/types/lib/inventory/osqueryTransform.d.ts.map +1 -1
  315. package/types/lib/inventory/parentSelection.d.ts +34 -0
  316. package/types/lib/inventory/parentSelection.d.ts.map +1 -0
  317. package/types/lib/inventory/phpBuildInfo.d.ts +142 -0
  318. package/types/lib/inventory/phpBuildInfo.d.ts.map +1 -0
  319. package/types/lib/inventory/phpHostProbe.d.ts +35 -0
  320. package/types/lib/inventory/phpHostProbe.d.ts.map +1 -0
  321. package/types/lib/inventory/rootfsCerts.d.ts +27 -0
  322. package/types/lib/inventory/rootfsCerts.d.ts.map +1 -0
  323. package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
  324. package/types/lib/inventory/scalaCoords.d.ts +80 -0
  325. package/types/lib/inventory/scalaCoords.d.ts.map +1 -0
  326. package/types/lib/inventory/source.d.ts +28 -0
  327. package/types/lib/inventory/source.d.ts.map +1 -1
  328. package/types/lib/inventory/spdx.d.ts +24 -0
  329. package/types/lib/inventory/spdx.d.ts.map +1 -1
  330. package/types/lib/inventory/traceRunner.d.ts +16 -1
  331. package/types/lib/inventory/traceRunner.d.ts.map +1 -1
  332. package/types/lib/inventory/tracedCrypto.d.ts +64 -0
  333. package/types/lib/inventory/tracedCrypto.d.ts.map +1 -0
  334. package/types/lib/managers/binary.d.ts +10 -0
  335. package/types/lib/managers/binary.d.ts.map +1 -1
  336. package/types/lib/managers/docker.d.ts +12 -0
  337. package/types/lib/managers/docker.d.ts.map +1 -1
  338. package/types/lib/managers/oci.d.ts +3 -1
  339. package/types/lib/managers/oci.d.ts.map +1 -1
  340. package/types/lib/parsers/cmakeCache.d.ts +16 -0
  341. package/types/lib/parsers/cmakeCache.d.ts.map +1 -1
  342. package/types/lib/parsers/cmakeLists.d.ts +2 -1
  343. package/types/lib/parsers/cmakeLists.d.ts.map +1 -1
  344. package/types/lib/parsers/cmakePresets.d.ts +78 -0
  345. package/types/lib/parsers/cmakePresets.d.ts.map +1 -0
  346. package/types/lib/parsers/compileCommands.d.ts +115 -0
  347. package/types/lib/parsers/compileCommands.d.ts.map +1 -0
  348. package/types/lib/parsers/email.d.ts +19 -0
  349. package/types/lib/parsers/email.d.ts.map +1 -0
  350. package/types/lib/parsers/largeJson.d.ts +13 -0
  351. package/types/lib/parsers/largeJson.d.ts.map +1 -1
  352. package/types/lib/parsers/strictJson.d.ts +46 -0
  353. package/types/lib/parsers/strictJson.d.ts.map +1 -0
  354. package/types/lib/parsers/terraformConfig.d.ts +70 -0
  355. package/types/lib/parsers/terraformConfig.d.ts.map +1 -0
  356. package/types/lib/parsers/terraformSource.d.ts +66 -0
  357. package/types/lib/parsers/terraformSource.d.ts.map +1 -0
  358. package/types/lib/server/server.d.ts +8 -0
  359. package/types/lib/server/server.d.ts.map +1 -1
  360. package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
  361. package/types/lib/stages/postgen/introspection/reflect.d.ts.map +1 -1
  362. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  363. package/types/lib/stages/postgen/ruleEngine.d.ts +7 -4
  364. package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
  365. package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
  366. package/types/lib/stages/pregen/pregen.d.ts +14 -1
  367. package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
  368. package/types/lib/validator/bomValidator.d.ts.map +1 -1
  369. package/types/lib/validator/index.d.ts +8 -0
  370. package/types/lib/validator/index.d.ts.map +1 -1
  371. package/types/lib/validator/reporters/json.d.ts.map +1 -1
  372. package/lib/third-party/arborist/snapshots/calc-dep-flags.test.cjs +0 -462
@@ -1,13 +1,12 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import process from "node:process";
4
- import { URL } from "node:url";
4
+ import { fileURLToPath, URL } from "node:url";
5
5
 
6
6
  import { Purl } from "@cdxgen/cdx-purl";
7
7
  import { coerce, diff, prerelease } from "semver";
8
8
 
9
9
  import {
10
- cdxgenAgent,
11
10
  createDryRunError,
12
11
  DEBUG_MODE,
13
12
  hasDangerousUnicode,
@@ -24,11 +23,12 @@ import {
24
23
  } from "../core/fs.js";
25
24
  import { thoughtLog } from "../core/logger.js";
26
25
  import { isValidDriveRoot, isWin } from "../core/paths.js";
26
+ import { registerRunReset } from "../core/runState.js";
27
27
  import {
28
+ gatedGet,
28
29
  prefetchEnabled,
29
30
  prefetchedResponse,
30
31
  prefetchJson,
31
- withHostRateLimit,
32
32
  } from "./fetchBatch.js";
33
33
  import { canonicalPurlFromLooseString } from "./purl.js";
34
34
 
@@ -111,6 +111,9 @@ function inferGitOperation(args = []) {
111
111
  * @param {string[]} args git arguments
112
112
  * @param {Object} options command options
113
113
  * @param {string|undefined} options.cwd working directory
114
+ * @param {boolean|undefined} options.noRepository run outside any repository,
115
+ * so the config of a repository in the working directory, such as url.*.insteadOf
116
+ * or core.sshCommand, cannot change where a remote command connects
114
117
  * @returns {Object} spawn result
115
118
  */
116
119
  export function hardenedGitCommand(args, options = {}) {
@@ -122,8 +125,14 @@ export function hardenedGitCommand(args, options = {}) {
122
125
  GIT_CONFIG_VALUE_0: "false",
123
126
  GIT_CONFIG_KEY_1: "safe.bareRepository",
124
127
  GIT_CONFIG_VALUE_1: "explicit",
128
+ GIT_NO_LAZY_FETCH: "1",
125
129
  GIT_TERMINAL_PROMPT: "0",
126
130
  };
131
+ if (options.noRepository) {
132
+ // ls-remote works without a repository. Pointing GIT_DIR at a path that
133
+ // does not exist stops git from discovering one in the working directory.
134
+ envConfigs.GIT_DIR = path.join(getTmpDir(), "cdxgen-no-repository.invalid");
135
+ }
127
136
  const env = isSecureMode
128
137
  ? {
129
138
  ...process.env,
@@ -275,10 +284,14 @@ export function buildReleaseNotesFromGit(repoPath, options = {}) {
275
284
  typeof remoteUrl === "string"
276
285
  ? validateAndRejectGitSource(remoteUrl)
277
286
  : null;
287
+ // remote.origin.url comes from the scanned repository. Only a remote that
288
+ // validateAndRejectGitSource recognises and checks may reach ls-remote; git
289
+ // also treats forms such as host:path as remotes, which skip that check.
278
290
  const canDiscoverRemoteTags =
279
291
  (!currentTag || !previousTag) &&
280
292
  typeof remoteUrl === "string" &&
281
293
  !remoteUrl.startsWith("-") &&
294
+ maybeRemotePath(remoteUrl) &&
282
295
  !remoteUrlValidationError &&
283
296
  /github\.com[:/]/i.test(remoteUrl);
284
297
  if (canDiscoverRemoteTags) {
@@ -298,7 +311,7 @@ export function buildReleaseNotesFromGit(repoPath, options = {}) {
298
311
  "--",
299
312
  remoteUrl,
300
313
  ],
301
- {},
314
+ { noRepository: true },
302
315
  );
303
316
  const remoteTags = parseLsRemoteTags(remoteTagsResult.stdout);
304
317
  if (!currentTag && remoteTags.length) {
@@ -508,6 +521,59 @@ export function isAllowedPath(p) {
508
521
  });
509
522
  }
510
523
 
524
+ /**
525
+ * Resolve symlinks in a path. When the path does not exist yet, the nearest
526
+ * existing parent is resolved and the remaining segments are appended, so
527
+ * /tmp/new on macOS still becomes /private/tmp/new.
528
+ *
529
+ * @param {string} p Path string
530
+ * @returns {string} real path
531
+ */
532
+ function realPathOrResolved(p) {
533
+ let current = path.resolve(p);
534
+ const missing = [];
535
+ while (true) {
536
+ try {
537
+ return path.join(fs.realpathSync(current), ...missing);
538
+ } catch (_err) {
539
+ const parent = path.dirname(current);
540
+ if (parent === current) {
541
+ return path.resolve(p);
542
+ }
543
+ missing.unshift(path.basename(current));
544
+ current = parent;
545
+ }
546
+ }
547
+ }
548
+
549
+ /**
550
+ * Checks where the given path really points, after following symlinks, against
551
+ * where the allowed paths really point. Both sides are resolved, so an allowed
552
+ * directory that is itself reached through a link (such as /tmp on macOS) still
553
+ * matches, while a link inside an allowed directory that leads outside it does
554
+ * not.
555
+ *
556
+ * @param {string} p Path string to check
557
+ * @returns {boolean} true if the real path is inside a real allowed path
558
+ */
559
+ export function isAllowedRealPath(p) {
560
+ if (typeof p !== "string" || hasDangerousUnicode(p)) {
561
+ return false;
562
+ }
563
+ const allowedPaths = getAllowedPaths();
564
+ if (!allowedPaths.length) {
565
+ return true;
566
+ }
567
+ const realP = realPathOrResolved(p);
568
+ return allowedPaths.some((ap) => {
569
+ const relativePath = path.relative(realPathOrResolved(ap), realP);
570
+ return (
571
+ relativePath === "" ||
572
+ (!relativePath.startsWith("..") && !path.isAbsolute(relativePath))
573
+ );
574
+ });
575
+ }
576
+
511
577
  /**
512
578
  * Determine if the path could be a package URL.
513
579
  *
@@ -586,6 +652,49 @@ export function validateAndRejectGitSource(filePath) {
586
652
  };
587
653
  }
588
654
 
655
+ if (hasAmbiguousRemoteCharacters(filePath)) {
656
+ return {
657
+ status: 400,
658
+ error: "Invalid URL Format",
659
+ details:
660
+ "The provided Git URL contains backslashes, whitespace or control characters.",
661
+ };
662
+ }
663
+
664
+ // git reads file:// URLs from the local disk, so they get the path
665
+ // allowlist rather than the host allowlist.
666
+ if (gitUrlObj.protocol === "file:") {
667
+ let localPath;
668
+ try {
669
+ localPath = fileURLToPath(gitUrlObj);
670
+ } catch (_err) {
671
+ localPath = undefined;
672
+ }
673
+ if (
674
+ gitUrlObj.hostname ||
675
+ !localPath ||
676
+ !isAllowedPath(localPath) ||
677
+ (isWin && !isAllowedWinPath(localPath))
678
+ ) {
679
+ return {
680
+ status: 403,
681
+ error: "Path Not Allowed",
682
+ details: "Path is not allowed as per the allowlist.",
683
+ };
684
+ }
685
+ return null;
686
+ }
687
+
688
+ // git, libcurl and OpenSSH must connect to the host that was checked.
689
+ const gitRemoteHost = getGitRemoteHost(filePath);
690
+ if (!gitRemoteHost || gitUrlObj.hostname.toLowerCase() !== gitRemoteHost) {
691
+ return {
692
+ status: 400,
693
+ error: "Invalid URL Format",
694
+ details: "The host of the provided Git URL is ambiguous.",
695
+ };
696
+ }
697
+
589
698
  if (!isAllowedHost(gitUrlObj.hostname)) {
590
699
  return {
591
700
  status: 403,
@@ -598,6 +707,94 @@ export function validateAndRejectGitSource(filePath) {
598
707
  return null;
599
708
  }
600
709
 
710
+ /**
711
+ * Detect characters that git, libcurl or OpenSSH read differently from the
712
+ * WHATWG URL parser. A backslash ends the host for new URL() but is part of
713
+ * the user name for git, and new URL() silently drops tabs and newlines.
714
+ *
715
+ * @param {string} remote Git URL or SCP-like address
716
+ * @returns {boolean} true if the remote contains such characters
717
+ */
718
+ function hasAmbiguousRemoteCharacters(remote) {
719
+ if (hasDangerousUnicode(remote)) {
720
+ return true;
721
+ }
722
+ for (const ch of remote) {
723
+ const code = ch.codePointAt(0);
724
+ if (ch === "\\" || code <= 0x20 || (code >= 0x7f && code <= 0x9f)) {
725
+ return true;
726
+ }
727
+ }
728
+ return false;
729
+ }
730
+
731
+ /**
732
+ * Return the host a git client connects to for a remote, read the way git,
733
+ * libcurl and OpenSSH read it rather than the way new URL() does. git ends the
734
+ * authority of ssh:// and git:// URLs only at the first slash, percent-decodes
735
+ * it before splitting off the host, and reads a leading "[...]" as the host.
736
+ * OpenSSH takes the host after the last "@". So a "?" or "#" before the first
737
+ * slash, a second "@", brackets in the user name, or a percent sign in an
738
+ * ssh:// or git:// authority make the host ambiguous.
739
+ *
740
+ * @param {string} remote Git URL or SCP-like address
741
+ * @returns {string|undefined} lower-cased host, or undefined when it is ambiguous
742
+ */
743
+ export function getGitRemoteHost(remote) {
744
+ if (typeof remote !== "string") {
745
+ return undefined;
746
+ }
747
+ let authority;
748
+ const schemeEnd = remote.indexOf("://");
749
+ if (schemeEnd > -1) {
750
+ const scheme = remote.slice(0, schemeEnd).toLowerCase();
751
+ const rest = remote.slice(schemeEnd + 3);
752
+ const slash = rest.indexOf("/");
753
+ authority = slash > -1 ? rest.slice(0, slash) : rest;
754
+ // libcurl reads the http(s) authority as written. git decodes the others.
755
+ if (!["http", "https"].includes(scheme) && authority.includes("%")) {
756
+ return undefined;
757
+ }
758
+ } else {
759
+ // git reads user@host:path as SCP-like only when the colon comes before
760
+ // any slash. Otherwise it is a local path.
761
+ const colon = remote.indexOf(":");
762
+ const slash = remote.indexOf("/");
763
+ if (colon < 0 || (slash > -1 && slash < colon)) {
764
+ return undefined;
765
+ }
766
+ authority = remote.slice(0, colon);
767
+ }
768
+ if (authority.includes("?") || authority.includes("#")) {
769
+ return undefined;
770
+ }
771
+ const at = authority.indexOf("@");
772
+ if (at !== authority.lastIndexOf("@")) {
773
+ return undefined;
774
+ }
775
+ const userInfo = at > -1 ? authority.slice(0, at) : "";
776
+ if (userInfo.includes("[") || userInfo.includes("]")) {
777
+ return undefined;
778
+ }
779
+ let host = authority.slice(at + 1);
780
+ if (host.startsWith("[")) {
781
+ const close = host.indexOf("]");
782
+ if (close < 0) {
783
+ return undefined;
784
+ }
785
+ host = host.slice(0, close + 1);
786
+ } else {
787
+ const portSep = host.indexOf(":");
788
+ if (portSep > -1) {
789
+ host = host.slice(0, portSep);
790
+ }
791
+ }
792
+ if (!host || host.startsWith("-")) {
793
+ return undefined;
794
+ }
795
+ return host.toLowerCase();
796
+ }
797
+
601
798
  /**
602
799
  * Clone a git repository into a temporary directory.
603
800
  *
@@ -606,6 +803,11 @@ export function validateAndRejectGitSource(filePath) {
606
803
  * @returns {string} cloned directory path
607
804
  */
608
805
  export function gitClone(repoUrl, branch = null) {
806
+ // Callers validate first, but git must never see a remote that fails it.
807
+ const validationError = validateAndRejectGitSource(repoUrl);
808
+ if (validationError) {
809
+ throw new Error(`${validationError.error}: ${validationError.details}`);
810
+ }
609
811
  let baseDirName = path.basename(repoUrl);
610
812
  if (!/^[a-zA-Z0-9_-]+$/.test(baseDirName)) {
611
813
  baseDirName = "repo-";
@@ -635,6 +837,8 @@ export function gitClone(repoUrl, branch = null) {
635
837
  "safe.bareRepository=explicit",
636
838
  "-c",
637
839
  "core.hooksPath=/dev/null",
840
+ "-c",
841
+ "core.symlinks=false",
638
842
  "clone",
639
843
  "--template=",
640
844
  repoUrl,
@@ -735,7 +939,7 @@ export function findGitRefForPurlVersion(repoUrl, purlResolution) {
735
939
  "--",
736
940
  repoUrl,
737
941
  ],
738
- {},
942
+ { noRepository: true },
739
943
  );
740
944
  if (result.status !== 0 || !result.stdout) {
741
945
  return undefined;
@@ -1165,6 +1369,8 @@ export function resetGitUrlSourcePrefetch() {
1165
1369
  gitUrlSourcePrefetch = new Map();
1166
1370
  }
1167
1371
 
1372
+ registerRunReset("source:registry-documents", resetGitUrlSourcePrefetch);
1373
+
1168
1374
  /**
1169
1375
  * Prefetch the registry documents a list of purls will be resolved from.
1170
1376
  *
@@ -1218,12 +1424,10 @@ async function fetchRegistryDocument(lookup) {
1218
1424
  // whose policy is one request per second however the request was reached.
1219
1425
  return (
1220
1426
  prefetchedResponse(gitUrlSourcePrefetch, lookup.url) ||
1221
- (await withHostRateLimit(lookup.url, () =>
1222
- cdxgenAgent.get(lookup.url, {
1223
- ...(lookup.accept ? { headers: { Accept: lookup.accept } } : {}),
1224
- responseType: "json",
1225
- }),
1226
- ))
1427
+ (await gatedGet(lookup.url, {
1428
+ ...(lookup.accept ? { headers: { Accept: lookup.accept } } : {}),
1429
+ responseType: "json",
1430
+ }))
1227
1431
  );
1228
1432
  }
1229
1433
 
@@ -343,12 +343,257 @@ export function findLicenseId(name) {
343
343
  : name;
344
344
  }
345
345
 
346
+ /**
347
+ * Identify a license from the title and opening of its full text. A license
348
+ * text quotes other licenses (the GNU GPL's text names the GNU Lesser GPL),
349
+ * so the substring scan of `guessLicenseId` alone can name the wrong one.
350
+ *
351
+ * @param {string} content License file contents
352
+ * @returns {string|undefined} SPDX license id or expression
353
+ */
354
+ export function licenseIdFromText(content) {
355
+ if (typeof content !== "string" || !content.trim()) {
356
+ return undefined;
357
+ }
358
+ const head = content.slice(0, 4000).replace(/\s+/g, " ").trim().toUpperCase();
359
+ const version = (prefix) => {
360
+ const at = head.indexOf(prefix);
361
+ if (at < 0) {
362
+ return undefined;
363
+ }
364
+ const tail = head.slice(at + prefix.length, at + prefix.length + 60);
365
+ const match = tail.match(/VERSION (\d(?:\.\d)?)/);
366
+ return match?.[1];
367
+ };
368
+ // the first lines name the license; quotations of others come later, so
369
+ // of the GNU licenses the one named first is the one the text is
370
+ const title = head.slice(0, 200);
371
+ const gnu = [
372
+ ["GNU AFFERO GENERAL PUBLIC LICENSE", { 3: "AGPL-3.0-only" }],
373
+ [
374
+ "GNU LESSER GENERAL PUBLIC LICENSE",
375
+ { 3: "LGPL-3.0-only", 2.1: "LGPL-2.1-only", 2: "LGPL-2.0-only" },
376
+ ],
377
+ [
378
+ "GNU LIBRARY GENERAL PUBLIC LICENSE",
379
+ { 2.1: "LGPL-2.1-only", 2: "LGPL-2.0-only" },
380
+ ],
381
+ [
382
+ "GNU GENERAL PUBLIC LICENSE",
383
+ { 3: "GPL-3.0-only", 2: "GPL-2.0-only", 1: "GPL-1.0-only" },
384
+ ],
385
+ ]
386
+ .map(([name, ids]) => ({ name, ids, at: title.indexOf(name) }))
387
+ .filter((t) => t.at >= 0)
388
+ .sort((a, b) => a.at - b.at)[0];
389
+ if (gnu) {
390
+ return gnu.ids[version(gnu.name)];
391
+ }
392
+ if (head.includes("APACHE LICENSE") && head.includes("VERSION 2.0")) {
393
+ return head.includes("LLVM EXCEPTION")
394
+ ? "Apache-2.0 WITH LLVM-exception"
395
+ : "Apache-2.0";
396
+ }
397
+ if (
398
+ title.includes("MOZILLA PUBLIC LICENSE") &&
399
+ head.includes("VERSION 2.0")
400
+ ) {
401
+ return "MPL-2.0";
402
+ }
403
+ if (title.includes("BOOST SOFTWARE LICENSE - VERSION 1.0")) {
404
+ return "BSL-1.0";
405
+ }
406
+ if (
407
+ head.includes(
408
+ "THIS IS FREE AND UNENCUMBERED SOFTWARE RELEASED INTO THE PUBLIC DOMAIN",
409
+ )
410
+ ) {
411
+ return "Unlicense";
412
+ }
413
+ if (head.includes("PERMISSION IS HEREBY GRANTED, FREE OF CHARGE")) {
414
+ return "MIT";
415
+ }
416
+ if (
417
+ head.includes(
418
+ "PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED",
419
+ )
420
+ ) {
421
+ return "ISC";
422
+ }
423
+ if (
424
+ head.includes("THIS SOFTWARE IS PROVIDED 'AS-IS'") &&
425
+ head.includes(
426
+ "PERMISSION IS GRANTED TO ANYONE TO USE THIS SOFTWARE FOR ANY PURPOSE",
427
+ )
428
+ ) {
429
+ return "Zlib";
430
+ }
431
+ if (head.includes("REDISTRIBUTION AND USE IN SOURCE AND BINARY FORMS")) {
432
+ if (head.includes("ALL ADVERTISING MATERIALS MENTIONING")) {
433
+ return "BSD-4-Clause";
434
+ }
435
+ return head.includes("NEITHER THE NAME") ||
436
+ head.includes("THE NAME OF THE AUTHOR MAY NOT BE USED")
437
+ ? "BSD-3-Clause"
438
+ : "BSD-2-Clause";
439
+ }
440
+ return undefined;
441
+ }
442
+
443
+ // The GNU licenses by the title line their text opens with, and their SPDX
444
+ // ids by version.
445
+ const GNU_LICENSE_TITLES = {
446
+ "GNU AFFERO GENERAL PUBLIC LICENSE": { 3: "AGPL-3.0-only" },
447
+ "GNU LESSER GENERAL PUBLIC LICENSE": {
448
+ 3: "LGPL-3.0-only",
449
+ 2.1: "LGPL-2.1-only",
450
+ 2: "LGPL-2.0-only",
451
+ },
452
+ "GNU LIBRARY GENERAL PUBLIC LICENSE": {
453
+ 2.1: "LGPL-2.1-only",
454
+ 2: "LGPL-2.0-only",
455
+ },
456
+ "GNU GENERAL PUBLIC LICENSE": {
457
+ 3: "GPL-3.0-only",
458
+ 2: "GPL-2.0-only",
459
+ 1: "GPL-1.0-only",
460
+ },
461
+ };
462
+
463
+ // Phrases that only the grant of one license carries, so finding one anywhere
464
+ // in a notice means that license is granted, not merely mentioned.
465
+ const LICENSE_GRANT_PHRASES = [
466
+ ["PERMISSION IS HEREBY GRANTED, FREE OF CHARGE", "MIT"],
467
+ [
468
+ "PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED",
469
+ "ISC",
470
+ ],
471
+ [
472
+ "PERMISSION IS GRANTED TO ANYONE TO USE THIS SOFTWARE FOR ANY PURPOSE",
473
+ "Zlib",
474
+ ],
475
+ [
476
+ "THIS IS FREE AND UNENCUMBERED SOFTWARE RELEASED INTO THE PUBLIC DOMAIN",
477
+ "Unlicense",
478
+ ],
479
+ ["BOOST SOFTWARE LICENSE - VERSION 1.0", "BSL-1.0"],
480
+ ["MOZILLA PUBLIC LICENSE VERSION 2.0", "MPL-2.0"],
481
+ ["MOZILLA PUBLIC LICENSE, VERSION 2.0", "MPL-2.0"],
482
+ ["MOZILLA PUBLIC LICENSE, V. 2.0", "MPL-2.0"],
483
+ [
484
+ "CREATIVE COMMONS ATTRIBUTION 4.0 INTERNATIONAL PUBLIC LICENSE",
485
+ "CC-BY-4.0",
486
+ ],
487
+ [
488
+ "CREATIVE COMMONS ATTRIBUTION-SHAREALIKE 4.0 INTERNATIONAL PUBLIC LICENSE",
489
+ "CC-BY-SA-4.0",
490
+ ],
491
+ ["CC0 1.0 UNIVERSAL", "CC0-1.0"],
492
+ ];
493
+
494
+ /**
495
+ * Identify every license a notice grants, in the order the notice grants
496
+ * them. A notice can grant several: one LICENSE file holding an MIT grant and
497
+ * an Apache-2.0 grant (gopkg.in/yaml.v3), or a choice of licenses followed by
498
+ * each full text (github.com/spdx/tools-golang). A license text quotes others
499
+ * (the GNU GPL names the GNU Lesser GPL, the MPL names the GNU licenses), so
500
+ * only phrases that a grant carries count: a GNU license is found by its title
501
+ * standing on a line of its own, the others by a sentence of their grant.
502
+ * A notice none of these phrases match falls back to {@link guessLicenseId}.
503
+ *
504
+ * @param {string} content License file contents
505
+ * @returns {string[]} SPDX license ids or expressions; empty when none is
506
+ * recognized
507
+ */
508
+ export function guessLicenseIds(content) {
509
+ if (typeof content !== "string" || !content.trim()) {
510
+ return [];
511
+ }
512
+ const text = content.replace(/\s+/g, " ").toUpperCase();
513
+ const found = [];
514
+ const add = (at, id) => {
515
+ if (at >= 0 && id) {
516
+ found.push({ at, id });
517
+ }
518
+ };
519
+ // Walk the lines alongside `text`, so a title line is placed in it.
520
+ let offset = 0;
521
+ for (const line of content.split("\n")) {
522
+ const normalized = line.replace(/\s+/g, " ").trim().toUpperCase();
523
+ const at = normalized ? text.indexOf(normalized, offset) : -1;
524
+ if (at < 0) {
525
+ continue;
526
+ }
527
+ offset = at + normalized.length;
528
+ const ids = GNU_LICENSE_TITLES[normalized];
529
+ if (ids) {
530
+ const version = text
531
+ .slice(offset, offset + 60)
532
+ .match(/VERSION (\d(?:\.\d)?)/)?.[1];
533
+ add(at, ids[version]);
534
+ }
535
+ }
536
+ for (const marker of [
537
+ "APACHE LICENSE VERSION 2.0",
538
+ "APACHE LICENSE, VERSION 2.0",
539
+ "APACHE LICENSE 2.0",
540
+ ]) {
541
+ add(
542
+ text.indexOf(marker),
543
+ text.includes("LLVM EXCEPTION")
544
+ ? "Apache-2.0 WITH LLVM-exception"
545
+ : "Apache-2.0",
546
+ );
547
+ }
548
+ for (const [phrase, id] of LICENSE_GRANT_PHRASES) {
549
+ add(text.indexOf(phrase), id);
550
+ }
551
+ // A notice can hold several BSD texts (one per copyright holder), each read
552
+ // up to where the next one starts.
553
+ const bsdPhrase = "REDISTRIBUTION AND USE IN SOURCE AND BINARY FORMS";
554
+ for (
555
+ let bsdAt = text.indexOf(bsdPhrase);
556
+ bsdAt >= 0;
557
+ bsdAt = text.indexOf(bsdPhrase, bsdAt + bsdPhrase.length)
558
+ ) {
559
+ const nextAt = text.indexOf(bsdPhrase, bsdAt + bsdPhrase.length);
560
+ const clauses = text.slice(
561
+ bsdAt,
562
+ Math.min(bsdAt + 2000, nextAt < 0 ? text.length : nextAt),
563
+ );
564
+ add(
565
+ bsdAt,
566
+ clauses.includes("ALL ADVERTISING MATERIALS MENTIONING")
567
+ ? "BSD-4-Clause"
568
+ : clauses.includes("NEITHER THE NAME") ||
569
+ clauses.includes("THE NAME OF THE AUTHOR MAY NOT BE USED")
570
+ ? "BSD-3-Clause"
571
+ : "BSD-2-Clause",
572
+ );
573
+ }
574
+ const ids = [];
575
+ for (const { id } of found.sort((a, b) => a.at - b.at)) {
576
+ if (!ids.includes(id)) {
577
+ ids.push(id);
578
+ }
579
+ }
580
+ if (ids.length) {
581
+ return ids;
582
+ }
583
+ const guessed = guessLicenseId(content);
584
+ return guessed ? [guessed] : [];
585
+ }
586
+
346
587
  /**
347
588
  * Method to guess the spdx license id from license contents
348
589
  *
349
590
  * @param {string} content License file contents
350
591
  */
351
592
  export function guessLicenseId(content) {
593
+ const fromText = licenseIdFromText(content);
594
+ if (fromText) {
595
+ return fromText;
596
+ }
352
597
  content = content.replace(/\n/g, " ");
353
598
  for (const l of licenseMapping) {
354
599
  for (const j in l.names) {