@cdxgen/cdxgen 0.0.1 → 13.0.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 (722) hide show
  1. package/README.md +921 -87
  2. package/bin/audit.js +239 -0
  3. package/bin/cdxgen.js +2324 -0
  4. package/bin/convert.js +213 -0
  5. package/bin/evinse.js +353 -0
  6. package/bin/hbom.js +495 -0
  7. package/bin/repl.js +2224 -0
  8. package/bin/sign.js +195 -0
  9. package/bin/tracebom.js +295 -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 +1833 -0
  85. package/lib/cli/cliOptions.js +513 -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 +142 -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 +876 -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 +575 -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 +1789 -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 +277 -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 +263 -0
  215. package/lib/inventory/traceRunner.js +439 -0
  216. package/lib/inventory/unicodeScan.js +147 -0
  217. package/lib/managers/binary.js +3307 -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 +315 -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 +28 -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 +120 -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 +19 -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 +76 -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,1636 @@
1
+ import { createHash } from "node:crypto";
2
+ import {
3
+ chmodSync,
4
+ closeSync,
5
+ openSync,
6
+ readFileSync,
7
+ readSync,
8
+ statSync,
9
+ symlinkSync,
10
+ } from "node:fs";
11
+ import { basename, dirname, extname, join, relative, resolve } from "node:path";
12
+ import process from "node:process";
13
+
14
+ import { DEBUG_MODE, isDryRun, recordActivity } from "../core/activity.js";
15
+ import {
16
+ getTmpDir,
17
+ safeCopyFileSync,
18
+ safeExistsSync,
19
+ safeExtractArchive,
20
+ safeMkdirSync,
21
+ safeMkdtempSync,
22
+ safeRmSync,
23
+ safeWriteSync,
24
+ } from "../core/fs.js";
25
+ import { thoughtLog } from "../core/logger.js";
26
+ import { sanitizeBomPropertyValue } from "../core/propertySanitizer.js";
27
+ import {
28
+ analyzeJsCapabilitiesSource,
29
+ analyzeSuspiciousJsSource,
30
+ } from "../inventory/analyzer.js";
31
+ import { tryBuildPurl } from "../inventory/purl.js";
32
+ import { xml2js } from "../parsers/xml.js";
33
+
34
+ const ASAR_JS_ANALYSIS_EXTENSIONS = new Set([
35
+ ".cjs",
36
+ ".cts",
37
+ ".js",
38
+ ".jsx",
39
+ ".mjs",
40
+ ".mts",
41
+ ".ts",
42
+ ".tsx",
43
+ ]);
44
+ const ASAR_LOCKFILE_NAMES = new Set([
45
+ "npm-shrinkwrap.json",
46
+ "package-lock.json",
47
+ "pnpm-lock.yaml",
48
+ "yarn.lock",
49
+ ]);
50
+ const ASAR_LIFECYCLE_SCRIPT_NAMES = new Set([
51
+ "install",
52
+ "postinstall",
53
+ "preinstall",
54
+ "prepare",
55
+ "prepublish",
56
+ ]);
57
+ const PICKLE_UINT32_SIZE = 4;
58
+ const PICKLE_SIZE_PICKLE_BYTES = 8;
59
+ const MAX_ASAR_HEADER_BYTES = 64 * 1024 * 1024;
60
+ const MAX_ASAR_ENTRY_BYTES = 256 * 1024 * 1024;
61
+ const MAX_ASAR_OFFSET = BigInt(Number.MAX_SAFE_INTEGER);
62
+ const MAX_ASAR_HEADER_DEPTH = 256;
63
+ const MAX_ELECTRON_APP_BUNDLE_SEARCH_DEPTH = 20;
64
+
65
+ function addSanitizedProperty(properties, name, value) {
66
+ if (value === undefined || value === null || value === "") {
67
+ return;
68
+ }
69
+ const sanitizedValue = sanitizeBomPropertyValue(name, value);
70
+ if (
71
+ sanitizedValue === undefined ||
72
+ sanitizedValue === null ||
73
+ sanitizedValue === ""
74
+ ) {
75
+ return;
76
+ }
77
+ properties.push({
78
+ name,
79
+ value: String(sanitizedValue),
80
+ });
81
+ }
82
+
83
+ function toArchiveOccurrence(archivePath, entryPath) {
84
+ return `${archivePath}#/${entryPath.replaceAll("\\", "/")}`;
85
+ }
86
+
87
+ function normalizeArchiveRelativePath(entryPath) {
88
+ return String(entryPath || "")
89
+ .replaceAll("\\", "/")
90
+ .replace(/^\/+/, "");
91
+ }
92
+
93
+ function isPathWithin(baseDir, candidatePath) {
94
+ const relativePath = relative(resolve(baseDir), resolve(candidatePath))
95
+ .replaceAll("\\", "/")
96
+ .replace(/^\/+/, "");
97
+ return (
98
+ relativePath === "" ||
99
+ (!relativePath.startsWith("..") && !relativePath.split("/").includes(".."))
100
+ );
101
+ }
102
+
103
+ function parseScopedPackageName(packageName) {
104
+ if (!packageName || typeof packageName !== "string") {
105
+ return { group: "", name: "" };
106
+ }
107
+ if (packageName.startsWith("@")) {
108
+ const [group, ...nameParts] = packageName.slice(1).split("/");
109
+ return {
110
+ group,
111
+ name: nameParts.join("/"),
112
+ };
113
+ }
114
+ return { group: "", name: packageName };
115
+ }
116
+
117
+ function createAsarPackagePurl(packageName, version) {
118
+ const parsedName = parseScopedPackageName(packageName);
119
+ if (!parsedName.name) {
120
+ return undefined;
121
+ }
122
+ // Names come from an untrusted archive header, so a single unrepresentable
123
+ // one must not abort the scan.
124
+ return tryBuildPurl({
125
+ type: "npm",
126
+ namespace: parsedName.group || null,
127
+ name: parsedName.name,
128
+ version: version || null,
129
+ });
130
+ }
131
+
132
+ function createGenericArchivePurl(archivePath, version) {
133
+ // `generic` allows only checksum/download_url/repository_url/vcs_url as
134
+ // qualifiers, so the old `?type=asar` made cdx-purl throw and aborted the
135
+ // whole ASAR scan. The archive kind is already recorded as the
136
+ // `cdx:file:kind=asar-archive` property, so nothing is lost by dropping it.
137
+ return tryBuildPurl({
138
+ type: "generic",
139
+ name: basename(archivePath, ".asar"),
140
+ version: version || null,
141
+ });
142
+ }
143
+
144
+ function parseAsarJson(headerString) {
145
+ return JSON.parse(headerString, (_key, value) => {
146
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
147
+ return value;
148
+ }
149
+ const nullPrototypeObject = Object.create(null);
150
+ for (const [entryKey, entryValue] of Object.entries(value)) {
151
+ nullPrototypeObject[entryKey] = entryValue;
152
+ }
153
+ return nullPrototypeObject;
154
+ });
155
+ }
156
+
157
+ function validateHeaderEntry(entry, entryPath, depth = 0) {
158
+ if (depth > MAX_ASAR_HEADER_DEPTH) {
159
+ throw new Error(
160
+ `ASAR header nesting exceeds ${MAX_ASAR_HEADER_DEPTH} levels at ${entryPath || "/"}`,
161
+ );
162
+ }
163
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
164
+ throw new Error(`Invalid ASAR entry at ${entryPath}`);
165
+ }
166
+ const hasFiles = Object.hasOwn(entry, "files");
167
+ const hasLink = Object.hasOwn(entry, "link");
168
+ const hasOffset = Object.hasOwn(entry, "offset");
169
+ const hasSize = Object.hasOwn(entry, "size");
170
+ if (hasLink) {
171
+ if (
172
+ typeof entry.link !== "string" ||
173
+ !entry.link ||
174
+ hasFiles ||
175
+ entry.unpacked === true ||
176
+ hasOffset ||
177
+ hasSize
178
+ ) {
179
+ throw new Error(`Invalid ASAR symlink entry at ${entryPath}`);
180
+ }
181
+ return;
182
+ }
183
+ if (hasFiles) {
184
+ if (
185
+ !entry.files ||
186
+ typeof entry.files !== "object" ||
187
+ Array.isArray(entry.files) ||
188
+ entry.unpacked === true ||
189
+ hasOffset ||
190
+ hasSize
191
+ ) {
192
+ throw new Error(`Invalid ASAR directory entry at ${entryPath}`);
193
+ }
194
+ for (const [name, child] of Object.entries(entry.files)) {
195
+ if (
196
+ !name ||
197
+ name === "." ||
198
+ name === ".." ||
199
+ name === "__proto__" ||
200
+ name === "constructor" ||
201
+ name === "prototype" ||
202
+ name.includes("/") ||
203
+ name.includes("\\")
204
+ ) {
205
+ throw new Error(`Invalid ASAR child name "${name}" at ${entryPath}`);
206
+ }
207
+ validateHeaderEntry(child, `${entryPath}/${name}`, depth + 1);
208
+ }
209
+ return;
210
+ }
211
+ if (entry.unpacked === true) {
212
+ if (
213
+ hasOffset ||
214
+ typeof entry.size !== "number" ||
215
+ !Number.isSafeInteger(entry.size) ||
216
+ entry.size < 0 ||
217
+ entry.size > MAX_ASAR_ENTRY_BYTES
218
+ ) {
219
+ throw new Error(`Invalid ASAR unpacked file entry at ${entryPath}`);
220
+ }
221
+ return;
222
+ }
223
+ if (
224
+ typeof entry.offset !== "string" ||
225
+ !/^\d+$/.test(entry.offset) ||
226
+ typeof entry.size !== "number" ||
227
+ !Number.isSafeInteger(entry.size) ||
228
+ entry.size < 0 ||
229
+ entry.size > MAX_ASAR_ENTRY_BYTES
230
+ ) {
231
+ throw new Error(`Invalid ASAR file entry at ${entryPath}`);
232
+ }
233
+ }
234
+
235
+ function parseAsarHeaderString(headerBuffer) {
236
+ if (headerBuffer.length < PICKLE_UINT32_SIZE * 2) {
237
+ throw new Error("ASAR header pickle is too small.");
238
+ }
239
+ const payloadSize = headerBuffer.readUInt32LE(0);
240
+ if (payloadSize > headerBuffer.length - PICKLE_UINT32_SIZE) {
241
+ throw new Error("ASAR header payload exceeds archive header size.");
242
+ }
243
+ const stringLength = headerBuffer.readInt32LE(PICKLE_UINT32_SIZE);
244
+ if (stringLength < 0 || stringLength > payloadSize - PICKLE_UINT32_SIZE) {
245
+ throw new Error("ASAR header string length is invalid.");
246
+ }
247
+ return headerBuffer.toString(
248
+ "utf8",
249
+ PICKLE_UINT32_SIZE * 2,
250
+ PICKLE_UINT32_SIZE * 2 + stringLength,
251
+ );
252
+ }
253
+
254
+ /**
255
+ * Synchronously checks if a file is a valid Electron ASAR archive by sniffing its header.
256
+ *
257
+ * @param {string} archivePath - Path to the file to check
258
+ * @returns {boolean} True if the file has a valid ASAR header, false otherwise
259
+ */
260
+ export function isAsarArchiveSync(archivePath) {
261
+ try {
262
+ const fd = openSync(archivePath, "r");
263
+ try {
264
+ const sizeBuffer = Buffer.alloc(PICKLE_SIZE_PICKLE_BYTES);
265
+ const sizeRead = readSync(fd, sizeBuffer, 0, PICKLE_SIZE_PICKLE_BYTES, 0);
266
+ if (sizeRead !== PICKLE_SIZE_PICKLE_BYTES) {
267
+ return false;
268
+ }
269
+ const firstUInt = sizeBuffer.readUInt32LE(0);
270
+ if (firstUInt !== 4) {
271
+ return false;
272
+ }
273
+ const headerPickleSize = sizeBuffer.readUInt32LE(PICKLE_UINT32_SIZE);
274
+ if (
275
+ headerPickleSize < PICKLE_UINT32_SIZE * 2 ||
276
+ headerPickleSize > MAX_ASAR_HEADER_BYTES
277
+ ) {
278
+ return false;
279
+ }
280
+ return true;
281
+ } finally {
282
+ closeSync(fd);
283
+ }
284
+ } catch (_err) {
285
+ return false;
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Synchronously reads and parses the header of an Electron ASAR archive.
291
+ *
292
+ * @param {string} archivePath - Path to the ASAR archive
293
+ * @returns {Object} Object containing archiveDataOffset, header files node, headerSize, and headerString
294
+ * @throws {Error} If the archive is invalid or header cannot be parsed
295
+ */
296
+ export function readAsarArchiveHeaderSync(archivePath) {
297
+ const fd = openSync(archivePath, "r");
298
+ try {
299
+ const sizeBuffer = Buffer.alloc(PICKLE_SIZE_PICKLE_BYTES);
300
+ const sizeRead = readSync(fd, sizeBuffer, 0, PICKLE_SIZE_PICKLE_BYTES, 0);
301
+ if (sizeRead !== PICKLE_SIZE_PICKLE_BYTES) {
302
+ throw new Error(
303
+ `Unable to read ASAR header size from ${archivePath}: expected ${PICKLE_SIZE_PICKLE_BYTES} bytes, got ${sizeRead}`,
304
+ );
305
+ }
306
+ const firstUInt = sizeBuffer.readUInt32LE(0);
307
+ if (firstUInt !== 4) {
308
+ throw new Error(
309
+ `Invalid ASAR header size check (expected 4, got ${firstUInt}) for ${archivePath}`,
310
+ );
311
+ }
312
+ const headerPickleSize = sizeBuffer.readUInt32LE(PICKLE_UINT32_SIZE);
313
+ if (
314
+ headerPickleSize < PICKLE_UINT32_SIZE * 2 ||
315
+ headerPickleSize > MAX_ASAR_HEADER_BYTES
316
+ ) {
317
+ throw new Error(
318
+ `Unsupported ASAR header size ${headerPickleSize} for ${archivePath}`,
319
+ );
320
+ }
321
+ const headerBuffer = Buffer.alloc(headerPickleSize);
322
+ const headerRead = readSync(
323
+ fd,
324
+ headerBuffer,
325
+ 0,
326
+ headerPickleSize,
327
+ PICKLE_SIZE_PICKLE_BYTES,
328
+ );
329
+ if (headerRead !== headerPickleSize) {
330
+ throw new Error(
331
+ `Unable to read ASAR header from ${archivePath}: expected ${headerPickleSize} bytes, got ${headerRead}`,
332
+ );
333
+ }
334
+ const headerString = parseAsarHeaderString(headerBuffer);
335
+ const header = parseAsarJson(headerString);
336
+ if (!header?.files || typeof header.files !== "object") {
337
+ throw new Error(`Invalid ASAR header root for ${archivePath}`);
338
+ }
339
+ validateHeaderEntry(header, "", 0);
340
+ return {
341
+ archiveDataOffset: BigInt(PICKLE_SIZE_PICKLE_BYTES + headerPickleSize),
342
+ header,
343
+ headerSize: headerPickleSize,
344
+ headerString,
345
+ };
346
+ } finally {
347
+ closeSync(fd);
348
+ }
349
+ }
350
+
351
+ /**
352
+ * Synchronously lists all entries (files, directories, symlinks) in an Electron ASAR archive.
353
+ *
354
+ * @param {string} archivePath - Path to the ASAR archive
355
+ * @returns {Object} Object containing the archive header info and list of entries
356
+ * @throws {Error} If the archive is invalid or header parsing fails
357
+ */
358
+ export function listAsarEntries(archivePath) {
359
+ const parsedHeader = readAsarArchiveHeaderSync(archivePath);
360
+ const entries = [];
361
+ const visitEntries = (filesNode, currentPath = "") => {
362
+ for (const [name, child] of Object.entries(filesNode || {})) {
363
+ const childPath = currentPath ? `${currentPath}/${name}` : name;
364
+ if (child?.files) {
365
+ entries.push({
366
+ path: childPath,
367
+ type: "directory",
368
+ unpacked: child.unpacked === true,
369
+ });
370
+ visitEntries(child.files, childPath);
371
+ continue;
372
+ }
373
+ if (child?.link) {
374
+ entries.push({
375
+ link: child.link,
376
+ path: childPath,
377
+ type: "link",
378
+ unpacked: child.unpacked === true,
379
+ });
380
+ continue;
381
+ }
382
+ entries.push({
383
+ executable: child?.executable === true,
384
+ integrity: child?.integrity,
385
+ offset: child?.offset,
386
+ path: childPath,
387
+ size: Number(child?.size || 0),
388
+ type: "file",
389
+ unpacked: child?.unpacked === true,
390
+ });
391
+ }
392
+ };
393
+ visitEntries(parsedHeader.header.files);
394
+ return {
395
+ ...parsedHeader,
396
+ entries: entries.sort((left, right) => left.path.localeCompare(right.path)),
397
+ };
398
+ }
399
+
400
+ function resolveUnpackedEntryPath(archivePath, entryPath) {
401
+ const unpackedBaseDir = `${archivePath}.unpacked`;
402
+ const normalizedEntryPath = normalizeArchiveRelativePath(entryPath);
403
+ const resolvedEntryPath = resolve(
404
+ unpackedBaseDir,
405
+ ...normalizedEntryPath.split("/"),
406
+ );
407
+ if (!isPathWithin(unpackedBaseDir, resolvedEntryPath)) {
408
+ throw new Error(
409
+ `Unpacked ASAR entry path escapes archive root: ${normalizedEntryPath}`,
410
+ );
411
+ }
412
+ return resolvedEntryPath;
413
+ }
414
+
415
+ function resolveArchiveLinkPath(entryPath, linkTarget) {
416
+ if (!linkTarget || typeof linkTarget !== "string") {
417
+ throw new Error(`Invalid ASAR symlink target for ${entryPath}`);
418
+ }
419
+ const normalizedEntryPath = normalizeArchiveRelativePath(entryPath);
420
+ const archiveRoot = "/__asar_root__";
421
+ const resolvedLinkPath = resolve(
422
+ archiveRoot,
423
+ dirname(normalizedEntryPath),
424
+ linkTarget,
425
+ );
426
+ if (!isPathWithin(archiveRoot, resolvedLinkPath)) {
427
+ throw new Error(
428
+ `ASAR symlink ${entryPath} target escapes archive root: ${linkTarget}`,
429
+ );
430
+ }
431
+ const archiveRelativeLinkPath = normalizeArchiveRelativePath(
432
+ relative(archiveRoot, resolvedLinkPath),
433
+ );
434
+ if (!archiveRelativeLinkPath || archiveRelativeLinkPath.startsWith("..")) {
435
+ throw new Error(
436
+ `ASAR symlink ${entryPath} target escapes archive root: ${linkTarget}`,
437
+ );
438
+ }
439
+ return archiveRelativeLinkPath;
440
+ }
441
+
442
+ function validateArchiveSymlinkEntries(entries) {
443
+ const symlinkTargets = new Map();
444
+ for (const entry of entries) {
445
+ if (entry.type !== "link") {
446
+ continue;
447
+ }
448
+ symlinkTargets.set(
449
+ normalizeArchiveRelativePath(entry.path),
450
+ resolveArchiveLinkPath(entry.path, entry.link),
451
+ );
452
+ }
453
+ const visitedPaths = new Set();
454
+ const visitingPaths = new Set();
455
+ const detectCycle = (entryPath) => {
456
+ if (visitedPaths.has(entryPath)) {
457
+ return;
458
+ }
459
+ if (visitingPaths.has(entryPath)) {
460
+ throw new Error(`Circular ASAR symlink chain detected at ${entryPath}`);
461
+ }
462
+ const linkTarget = symlinkTargets.get(entryPath);
463
+ if (!linkTarget) {
464
+ return;
465
+ }
466
+ visitingPaths.add(entryPath);
467
+ detectCycle(linkTarget);
468
+ visitingPaths.delete(entryPath);
469
+ visitedPaths.add(entryPath);
470
+ };
471
+ for (const entryPath of symlinkTargets.keys()) {
472
+ detectCycle(entryPath);
473
+ }
474
+ return symlinkTargets;
475
+ }
476
+
477
+ function readPackedEntryBuffer(archivePath, archiveDataOffset, entry, fd) {
478
+ const archiveFd = fd ?? openSync(archivePath, "r");
479
+ try {
480
+ if (!Number.isSafeInteger(entry.size) || entry.size < 0) {
481
+ throw new Error(
482
+ `Invalid packed ASAR entry size ${entry.size} for ${entry.path}`,
483
+ );
484
+ }
485
+ if (entry.size > MAX_ASAR_ENTRY_BYTES) {
486
+ throw new Error(
487
+ `ASAR entry ${entry.path} exceeds the maximum supported size of ${MAX_ASAR_ENTRY_BYTES} bytes`,
488
+ );
489
+ }
490
+ const absoluteOffset =
491
+ archiveDataOffset + BigInt(String(entry.offset || "0"));
492
+ if (absoluteOffset > MAX_ASAR_OFFSET) {
493
+ throw new Error(
494
+ `ASAR entry ${entry.path} offset exceeds the safe read limit`,
495
+ );
496
+ }
497
+ const buffer = Buffer.alloc(entry.size);
498
+ const bytesRead = readSync(
499
+ archiveFd,
500
+ buffer,
501
+ 0,
502
+ entry.size,
503
+ Number(absoluteOffset),
504
+ );
505
+ if (bytesRead !== entry.size) {
506
+ throw new Error(
507
+ `Unable to read complete ASAR entry ${entry.path} from ${archivePath}: expected ${entry.size} bytes, got ${bytesRead}`,
508
+ );
509
+ }
510
+ return buffer;
511
+ } finally {
512
+ if (fd === undefined) {
513
+ closeSync(archiveFd);
514
+ }
515
+ }
516
+ }
517
+
518
+ function readAsarEntryBufferSync(archivePath, archiveDataOffset, entry, fd) {
519
+ if (entry.unpacked) {
520
+ return readFileSync(resolveUnpackedEntryPath(archivePath, entry.path));
521
+ }
522
+ return readPackedEntryBuffer(archivePath, archiveDataOffset, entry, fd);
523
+ }
524
+
525
+ function sha256Buffer(buffer) {
526
+ return createHash("sha256").update(buffer).digest("hex");
527
+ }
528
+
529
+ function readXmlText(node) {
530
+ return (node?.elements || [])
531
+ .filter((child) => ["text", "cdata"].includes(child?.type))
532
+ .map((child) => child.text || child.cdata || "")
533
+ .join("");
534
+ }
535
+
536
+ function parsePlistElement(node) {
537
+ if (node?.type !== "element") {
538
+ return undefined;
539
+ }
540
+ switch (node.name) {
541
+ case "array":
542
+ return (node.elements || [])
543
+ .filter((child) => child?.type === "element")
544
+ .map((child) => parsePlistElement(child));
545
+ case "data":
546
+ case "date":
547
+ case "string":
548
+ return readXmlText(node);
549
+ case "dict": {
550
+ const plistObject = Object.create(null);
551
+ const childElements = (node.elements || []).filter(
552
+ (child) => child?.type === "element",
553
+ );
554
+ for (let index = 0; index < childElements.length - 1; index += 2) {
555
+ const keyElement = childElements[index];
556
+ const valueElement = childElements[index + 1];
557
+ if (keyElement?.name !== "key" || !valueElement) {
558
+ continue;
559
+ }
560
+ const keyName = readXmlText(keyElement);
561
+ if (!keyName) {
562
+ continue;
563
+ }
564
+ plistObject[keyName] = parsePlistElement(valueElement);
565
+ }
566
+ return plistObject;
567
+ }
568
+ case "false":
569
+ return false;
570
+ case "integer":
571
+ return Number.parseInt(readXmlText(node), 10);
572
+ case "true":
573
+ return true;
574
+ default:
575
+ return readXmlText(node);
576
+ }
577
+ }
578
+
579
+ function parsePlistFile(plistPath) {
580
+ const plistXml = readFileSync(plistPath, "utf8");
581
+ const plistJson = xml2js(plistXml, {
582
+ compact: false,
583
+ ignoreCdata: false,
584
+ ignoreComment: true,
585
+ ignoreDoctype: true,
586
+ ignoreInstruction: true,
587
+ trim: true,
588
+ });
589
+ const plistElement = plistJson?.elements?.find(
590
+ (element) => element?.type === "element" && element?.name === "plist",
591
+ );
592
+ const rootElement = plistElement?.elements?.find(
593
+ (element) => element?.type === "element",
594
+ );
595
+ return parsePlistElement(rootElement);
596
+ }
597
+
598
+ function findEnclosingElectronInfoPlist(archivePath) {
599
+ let currentDir = dirname(resolve(archivePath));
600
+ let currentDepth = 0;
601
+ while (currentDir && currentDir !== dirname(currentDir)) {
602
+ if (currentDepth >= MAX_ELECTRON_APP_BUNDLE_SEARCH_DEPTH) {
603
+ thoughtLog(
604
+ "Stopping Electron app bundle search after",
605
+ MAX_ELECTRON_APP_BUNDLE_SEARCH_DEPTH,
606
+ "levels for",
607
+ archivePath,
608
+ );
609
+ return undefined;
610
+ }
611
+ if (basename(currentDir).endsWith(".app")) {
612
+ const infoPlistPath = join(currentDir, "Contents", "Info.plist");
613
+ if (safeExistsSync(infoPlistPath)) {
614
+ return {
615
+ appDir: currentDir,
616
+ infoPlistPath,
617
+ };
618
+ }
619
+ }
620
+ currentDepth += 1;
621
+ currentDir = dirname(currentDir);
622
+ }
623
+ return undefined;
624
+ }
625
+
626
+ function collectAsarSigningInfo(archivePath, headerString) {
627
+ const bundleInfo = findEnclosingElectronInfoPlist(archivePath);
628
+ if (!bundleInfo?.infoPlistPath) {
629
+ return undefined;
630
+ }
631
+ const archiveRelativePath = relative(
632
+ join(bundleInfo.appDir, "Contents"),
633
+ resolve(archivePath),
634
+ ).replaceAll("\\", "/");
635
+ if (!archiveRelativePath || archiveRelativePath.startsWith("..")) {
636
+ return undefined;
637
+ }
638
+ let plistData;
639
+ try {
640
+ plistData = parsePlistFile(bundleInfo.infoPlistPath);
641
+ } catch {
642
+ return undefined;
643
+ }
644
+ const asarIntegrityRecord =
645
+ plistData?.ElectronAsarIntegrity?.[archiveRelativePath];
646
+ if (!asarIntegrityRecord || typeof asarIntegrityRecord !== "object") {
647
+ return undefined;
648
+ }
649
+ const computedHash = sha256Buffer(Buffer.from(headerString, "utf8"));
650
+ const algorithm = String(asarIntegrityRecord.algorithm || "").toUpperCase();
651
+ const declaredHash = String(asarIntegrityRecord.hash || "").toLowerCase();
652
+ return {
653
+ algorithm,
654
+ archiveRelativePath,
655
+ computedHash,
656
+ declaredHash,
657
+ infoPlistPath: bundleInfo.infoPlistPath,
658
+ scope: "header-only",
659
+ source: "electron-info-plist",
660
+ verified:
661
+ algorithm === "SHA256" &&
662
+ /^[a-f0-9]{64}$/i.test(declaredHash) &&
663
+ declaredHash === computedHash,
664
+ };
665
+ }
666
+
667
+ function createAsarSigningComponent(archivePath, signingInfo, options = {}) {
668
+ const specVersionNumber = Number(options.specVersion || 0);
669
+ const componentType =
670
+ specVersionNumber > 0 && specVersionNumber < 1.6
671
+ ? "data"
672
+ : "cryptographic-asset";
673
+ const properties = [{ name: "internal:SrcFile", value: archivePath }];
674
+ addSanitizedProperty(
675
+ properties,
676
+ "cdx:asar:signingAlgorithm",
677
+ signingInfo.algorithm,
678
+ );
679
+ addSanitizedProperty(
680
+ properties,
681
+ "cdx:asar:signingDeclaredHash",
682
+ signingInfo.declaredHash,
683
+ );
684
+ addSanitizedProperty(
685
+ properties,
686
+ "cdx:asar:headerHash",
687
+ signingInfo.computedHash,
688
+ );
689
+ addSanitizedProperty(
690
+ properties,
691
+ "cdx:asar:signingSource",
692
+ signingInfo.source,
693
+ );
694
+ addSanitizedProperty(properties, "cdx:asar:signingScope", signingInfo.scope);
695
+ addSanitizedProperty(
696
+ properties,
697
+ "cdx:asar:signingVerified",
698
+ String(signingInfo.verified),
699
+ );
700
+ addSanitizedProperty(
701
+ properties,
702
+ "cdx:asar:signingArchivePath",
703
+ signingInfo.archiveRelativePath,
704
+ );
705
+ const component = {
706
+ "bom-ref": `crypto/asar-signature/${encodeURIComponent(archivePath)}@sha256:${signingInfo.declaredHash || signingInfo.computedHash}`,
707
+ hashes: [
708
+ {
709
+ alg: "SHA-256",
710
+ content: signingInfo.declaredHash || signingInfo.computedHash,
711
+ },
712
+ ],
713
+ name: `${basename(archivePath)} asar integrity record`,
714
+ properties,
715
+ type: componentType,
716
+ version: signingInfo.declaredHash || signingInfo.computedHash,
717
+ };
718
+ if (componentType === "cryptographic-asset") {
719
+ component.cryptoProperties = {
720
+ assetType: "related-crypto-material",
721
+ relatedCryptoMaterialProperties: {
722
+ type: "digest",
723
+ value: signingInfo.declaredHash || signingInfo.computedHash,
724
+ },
725
+ };
726
+ }
727
+ return component;
728
+ }
729
+
730
+ function toFileComponentRef(archivePath, entryPath) {
731
+ return `file:${archivePath}#/${normalizeArchiveRelativePath(entryPath)}`;
732
+ }
733
+
734
+ function inferPrimaryPackagePath(entries) {
735
+ const packageEntries = entries
736
+ .filter(
737
+ (entry) =>
738
+ entry.type === "file" &&
739
+ basename(entry.path) === "package.json" &&
740
+ !entry.path.includes("/node_modules/"),
741
+ )
742
+ .sort((left, right) => left.path.length - right.path.length);
743
+ return packageEntries[0]?.path;
744
+ }
745
+
746
+ function inferMainEntryFlags(packageJson) {
747
+ const properties = [];
748
+ addSanitizedProperty(properties, "cdx:asar:main", packageJson?.main);
749
+ addSanitizedProperty(properties, "cdx:asar:module", packageJson?.module);
750
+ addSanitizedProperty(properties, "cdx:asar:browser", packageJson?.browser);
751
+ addSanitizedProperty(
752
+ properties,
753
+ "cdx:asar:productName",
754
+ packageJson?.productName,
755
+ );
756
+ const lifecycleScripts = Object.keys(packageJson?.scripts || {}).filter(
757
+ (name) => ASAR_LIFECYCLE_SCRIPT_NAMES.has(name),
758
+ );
759
+ if (lifecycleScripts.length) {
760
+ addSanitizedProperty(
761
+ properties,
762
+ "cdx:asar:lifecycleScripts",
763
+ lifecycleScripts.join(", "),
764
+ );
765
+ }
766
+ return properties;
767
+ }
768
+
769
+ function toArchiveVirtualPath(extractedDir, archivePath, candidatePath) {
770
+ if (!candidatePath || typeof candidatePath !== "string") {
771
+ return candidatePath;
772
+ }
773
+ const normalizedExtractedDir = resolve(extractedDir);
774
+ const normalizedCandidate = resolve(candidatePath);
775
+ if (!isPathWithin(normalizedExtractedDir, normalizedCandidate)) {
776
+ return candidatePath;
777
+ }
778
+ const relativePath = relative(normalizedExtractedDir, normalizedCandidate);
779
+ return `${archivePath}#/${relativePath.replaceAll("\\", "/")}`;
780
+ }
781
+
782
+ /**
783
+ * Recursively rewrites paths within component properties and evidence of an extracted archive
784
+ * to use virtual archive paths instead of local temporary extraction paths.
785
+ *
786
+ * @param {Object|Array} subject - The component, array of components, or component graph to rewrite
787
+ * @param {string} extractedDir - The temporary path where the archive was extracted
788
+ * @param {string} archivePath - The original path of the archive
789
+ * @returns {Object|Array} The updated subject with paths rewritten
790
+ */
791
+ export function rewriteExtractedArchivePaths(
792
+ subject,
793
+ extractedDir,
794
+ archivePath,
795
+ ) {
796
+ if (!subject || typeof subject !== "object") {
797
+ return subject;
798
+ }
799
+ if (Array.isArray(subject)) {
800
+ subject.forEach((entry) => {
801
+ rewriteExtractedArchivePaths(entry, extractedDir, archivePath);
802
+ });
803
+ return subject;
804
+ }
805
+ if (subject.properties?.length) {
806
+ subject.properties.forEach((property) => {
807
+ if (typeof property?.value === "string") {
808
+ property.value = toArchiveVirtualPath(
809
+ extractedDir,
810
+ archivePath,
811
+ property.value,
812
+ );
813
+ }
814
+ });
815
+ }
816
+ if (subject.evidence?.identity?.methods?.length) {
817
+ subject.evidence.identity.methods.forEach((method) => {
818
+ if (typeof method?.value === "string") {
819
+ method.value = toArchiveVirtualPath(
820
+ extractedDir,
821
+ archivePath,
822
+ method.value,
823
+ );
824
+ }
825
+ });
826
+ }
827
+ if (subject.evidence?.occurrences?.length) {
828
+ subject.evidence.occurrences.forEach((occurrence) => {
829
+ if (typeof occurrence?.location === "string") {
830
+ occurrence.location = toArchiveVirtualPath(
831
+ extractedDir,
832
+ archivePath,
833
+ occurrence.location,
834
+ );
835
+ }
836
+ });
837
+ }
838
+ if (subject.components?.length) {
839
+ rewriteExtractedArchivePaths(subject.components, extractedDir, archivePath);
840
+ }
841
+ return subject;
842
+ }
843
+
844
+ function collectArchiveSummaryProperties(
845
+ archivePath,
846
+ summary,
847
+ primaryPackageJson,
848
+ primaryPackagePath,
849
+ ) {
850
+ const properties = [{ name: "internal:SrcFile", value: archivePath }];
851
+ addSanitizedProperty(properties, "cdx:file:kind", "asar-archive");
852
+ addSanitizedProperty(
853
+ properties,
854
+ "cdx:asar:entryCount",
855
+ `${summary.entryCount}`,
856
+ );
857
+ addSanitizedProperty(
858
+ properties,
859
+ "cdx:asar:fileCount",
860
+ `${summary.fileCount}`,
861
+ );
862
+ addSanitizedProperty(
863
+ properties,
864
+ "cdx:asar:directoryCount",
865
+ `${summary.directoryCount}`,
866
+ );
867
+ addSanitizedProperty(
868
+ properties,
869
+ "cdx:asar:symlinkCount",
870
+ `${summary.symlinkCount}`,
871
+ );
872
+ addSanitizedProperty(
873
+ properties,
874
+ "cdx:asar:jsFileCount",
875
+ `${summary.jsFileCount}`,
876
+ );
877
+ addSanitizedProperty(
878
+ properties,
879
+ "cdx:asar:packageJsonCount",
880
+ `${summary.packageJsonCount}`,
881
+ );
882
+ addSanitizedProperty(
883
+ properties,
884
+ "cdx:asar:lockfileCount",
885
+ `${summary.lockfileCount}`,
886
+ );
887
+ if (summary.nestedArchiveCount > 0) {
888
+ addSanitizedProperty(properties, "cdx:asar:hasNestedArchives", "true");
889
+ addSanitizedProperty(
890
+ properties,
891
+ "cdx:asar:nestedArchiveCount",
892
+ `${summary.nestedArchiveCount}`,
893
+ );
894
+ }
895
+ if (summary.unpackedFileCount > 0) {
896
+ addSanitizedProperty(properties, "cdx:asar:hasUnpackedEntries", "true");
897
+ addSanitizedProperty(
898
+ properties,
899
+ "cdx:asar:unpackedFileCount",
900
+ `${summary.unpackedFileCount}`,
901
+ );
902
+ }
903
+ if (summary.nativeAddonCount > 0) {
904
+ addSanitizedProperty(properties, "cdx:asar:hasNativeAddons", "true");
905
+ addSanitizedProperty(
906
+ properties,
907
+ "cdx:asar:nativeAddonCount",
908
+ `${summary.nativeAddonCount}`,
909
+ );
910
+ }
911
+ if (summary.integrityMismatchCount > 0) {
912
+ addSanitizedProperty(properties, "cdx:asar:hasIntegrityMismatch", "true");
913
+ addSanitizedProperty(
914
+ properties,
915
+ "cdx:asar:integrityMismatchCount",
916
+ `${summary.integrityMismatchCount}`,
917
+ );
918
+ }
919
+ if (summary.capabilities.length) {
920
+ addSanitizedProperty(
921
+ properties,
922
+ "cdx:asar:capabilities",
923
+ summary.capabilities.join(", "),
924
+ );
925
+ summary.capabilities.forEach((capability) => {
926
+ addSanitizedProperty(
927
+ properties,
928
+ `cdx:asar:capability:${capability}`,
929
+ "true",
930
+ );
931
+ });
932
+ }
933
+ if (summary.executionIndicators.length) {
934
+ addSanitizedProperty(
935
+ properties,
936
+ "cdx:asar:executionIndicators",
937
+ summary.executionIndicators.join(", "),
938
+ );
939
+ }
940
+ if (summary.networkIndicators.length) {
941
+ addSanitizedProperty(
942
+ properties,
943
+ "cdx:asar:networkIndicators",
944
+ summary.networkIndicators.join(", "),
945
+ );
946
+ }
947
+ if (summary.obfuscationIndicators.length) {
948
+ addSanitizedProperty(
949
+ properties,
950
+ "cdx:asar:obfuscationIndicators",
951
+ summary.obfuscationIndicators.join(", "),
952
+ );
953
+ }
954
+ if (summary.hasEval) {
955
+ addSanitizedProperty(properties, "cdx:asar:hasEval", "true");
956
+ }
957
+ if (summary.hasDynamicFetch) {
958
+ addSanitizedProperty(properties, "cdx:asar:hasDynamicFetch", "true");
959
+ }
960
+ if (summary.hasDynamicImport) {
961
+ addSanitizedProperty(properties, "cdx:asar:hasDynamicImport", "true");
962
+ }
963
+ if (summary.headerHash) {
964
+ addSanitizedProperty(properties, "cdx:asar:headerHash", summary.headerHash);
965
+ }
966
+ if (summary.signingInfo) {
967
+ addSanitizedProperty(properties, "cdx:asar:hasSigningMetadata", "true");
968
+ addSanitizedProperty(
969
+ properties,
970
+ "cdx:asar:signingAlgorithm",
971
+ summary.signingInfo.algorithm,
972
+ );
973
+ addSanitizedProperty(
974
+ properties,
975
+ "cdx:asar:signingDeclaredHash",
976
+ summary.signingInfo.declaredHash,
977
+ );
978
+ addSanitizedProperty(
979
+ properties,
980
+ "cdx:asar:signingSource",
981
+ summary.signingInfo.source,
982
+ );
983
+ addSanitizedProperty(
984
+ properties,
985
+ "cdx:asar:signingScope",
986
+ summary.signingInfo.scope,
987
+ );
988
+ addSanitizedProperty(
989
+ properties,
990
+ "cdx:asar:signingVerified",
991
+ String(summary.signingInfo.verified),
992
+ );
993
+ }
994
+ if (primaryPackagePath) {
995
+ addSanitizedProperty(
996
+ properties,
997
+ "cdx:asar:primaryManifest",
998
+ `${archivePath}#/${primaryPackagePath}`,
999
+ );
1000
+ }
1001
+ if (primaryPackageJson) {
1002
+ inferMainEntryFlags(primaryPackageJson).forEach((property) => {
1003
+ properties.push(property);
1004
+ });
1005
+ }
1006
+ return properties;
1007
+ }
1008
+
1009
+ function createArchiveParentComponent(
1010
+ archivePath,
1011
+ summary,
1012
+ primaryPackageJson,
1013
+ primaryPackagePath,
1014
+ ) {
1015
+ const archivePurl =
1016
+ createAsarPackagePurl(
1017
+ primaryPackageJson?.name,
1018
+ primaryPackageJson?.version,
1019
+ ) || createGenericArchivePurl(archivePath, primaryPackageJson?.version);
1020
+ const component = {
1021
+ "bom-ref": decodeURIComponent(archivePurl),
1022
+ description:
1023
+ primaryPackageJson?.description ||
1024
+ `Electron ASAR archive ${basename(archivePath)}`,
1025
+ name:
1026
+ primaryPackageJson?.productName ||
1027
+ primaryPackageJson?.name ||
1028
+ basename(archivePath, ".asar"),
1029
+ purl: archivePurl,
1030
+ type: "application",
1031
+ version: primaryPackageJson?.version || "",
1032
+ };
1033
+ const parsedName = parseScopedPackageName(primaryPackageJson?.name);
1034
+ if (parsedName.group) {
1035
+ component.group = parsedName.group;
1036
+ }
1037
+ if (primaryPackageJson?.author) {
1038
+ component.author =
1039
+ typeof primaryPackageJson.author === "string"
1040
+ ? primaryPackageJson.author
1041
+ : primaryPackageJson.author?.name || "";
1042
+ }
1043
+ if (primaryPackageJson?.license) {
1044
+ component.license = primaryPackageJson.license;
1045
+ }
1046
+ if (primaryPackageJson?.repository) {
1047
+ const repositoryUrl =
1048
+ typeof primaryPackageJson.repository === "string"
1049
+ ? primaryPackageJson.repository
1050
+ : primaryPackageJson.repository?.url;
1051
+ if (repositoryUrl) {
1052
+ component.externalReferences = component.externalReferences || [];
1053
+ component.externalReferences.push({
1054
+ type: "vcs",
1055
+ url: repositoryUrl,
1056
+ });
1057
+ }
1058
+ }
1059
+ if (primaryPackageJson?.homepage) {
1060
+ component.externalReferences = component.externalReferences || [];
1061
+ component.externalReferences.push({
1062
+ type: "website",
1063
+ url: primaryPackageJson.homepage,
1064
+ });
1065
+ }
1066
+ component.properties = collectArchiveSummaryProperties(
1067
+ archivePath,
1068
+ summary,
1069
+ primaryPackageJson,
1070
+ primaryPackagePath,
1071
+ );
1072
+ component.evidence = {
1073
+ identity: {
1074
+ confidence: 1,
1075
+ field: "purl",
1076
+ methods: [
1077
+ {
1078
+ confidence: 1,
1079
+ technique: primaryPackagePath ? "manifest-analysis" : "filename",
1080
+ value: primaryPackagePath
1081
+ ? `${archivePath}#/${primaryPackagePath}`
1082
+ : archivePath,
1083
+ },
1084
+ ],
1085
+ },
1086
+ };
1087
+ return component;
1088
+ }
1089
+
1090
+ function createArchiveEntryComponent(
1091
+ archivePath,
1092
+ entry,
1093
+ computedHash,
1094
+ jsAnalysis,
1095
+ suspiciousAnalysis,
1096
+ ) {
1097
+ const archiveLocation = toArchiveOccurrence(archivePath, entry.path);
1098
+ const properties = [{ name: "internal:SrcFile", value: archivePath }];
1099
+ addSanitizedProperty(properties, "cdx:file:kind", "asar-entry");
1100
+ addSanitizedProperty(properties, "cdx:asar:path", entry.path);
1101
+ addSanitizedProperty(properties, "cdx:asar:size", `${entry.size || 0}`);
1102
+ addSanitizedProperty(
1103
+ properties,
1104
+ "cdx:asar:unpacked",
1105
+ String(entry.unpacked === true),
1106
+ );
1107
+ if (entry.offset !== undefined) {
1108
+ addSanitizedProperty(properties, "cdx:asar:offset", entry.offset);
1109
+ }
1110
+ if (entry.executable) {
1111
+ addSanitizedProperty(properties, "cdx:asar:executable", "true");
1112
+ }
1113
+ if (entry.link) {
1114
+ addSanitizedProperty(properties, "cdx:asar:linkTarget", entry.link);
1115
+ }
1116
+ if (entry.integrity?.algorithm) {
1117
+ addSanitizedProperty(
1118
+ properties,
1119
+ "cdx:asar:integrityAlgorithm",
1120
+ entry.integrity.algorithm,
1121
+ );
1122
+ }
1123
+ if (entry.integrity?.hash) {
1124
+ addSanitizedProperty(
1125
+ properties,
1126
+ "cdx:asar:declaredIntegrityHash",
1127
+ entry.integrity.hash,
1128
+ );
1129
+ }
1130
+ if (entry.integrity?.blockSize) {
1131
+ addSanitizedProperty(
1132
+ properties,
1133
+ "cdx:asar:integrityBlockSize",
1134
+ `${entry.integrity.blockSize}`,
1135
+ );
1136
+ }
1137
+ if (Array.isArray(entry.integrity?.blocks)) {
1138
+ addSanitizedProperty(
1139
+ properties,
1140
+ "cdx:asar:integrityBlockCount",
1141
+ `${entry.integrity.blocks.length}`,
1142
+ );
1143
+ }
1144
+ if (computedHash && entry.integrity?.hash) {
1145
+ addSanitizedProperty(
1146
+ properties,
1147
+ "cdx:asar:integrityVerified",
1148
+ String(computedHash === String(entry.integrity.hash).toLowerCase()),
1149
+ );
1150
+ }
1151
+ if (jsAnalysis?.capabilities?.length) {
1152
+ addSanitizedProperty(
1153
+ properties,
1154
+ "cdx:asar:js:capabilities",
1155
+ jsAnalysis.capabilities.join(", "),
1156
+ );
1157
+ jsAnalysis.capabilities.forEach((capability) => {
1158
+ addSanitizedProperty(
1159
+ properties,
1160
+ `cdx:asar:js:capability:${capability}`,
1161
+ "true",
1162
+ );
1163
+ });
1164
+ }
1165
+ if (jsAnalysis?.hasEval) {
1166
+ addSanitizedProperty(properties, "cdx:asar:js:hasEval", "true");
1167
+ }
1168
+ if (jsAnalysis?.hasDynamicFetch) {
1169
+ addSanitizedProperty(properties, "cdx:asar:js:hasDynamicFetch", "true");
1170
+ }
1171
+ if (jsAnalysis?.hasDynamicImport) {
1172
+ addSanitizedProperty(properties, "cdx:asar:js:hasDynamicImport", "true");
1173
+ }
1174
+ if (jsAnalysis?.indicatorMap?.fileAccess?.length) {
1175
+ addSanitizedProperty(
1176
+ properties,
1177
+ "cdx:asar:js:fileAccessIndicators",
1178
+ jsAnalysis.indicatorMap.fileAccess.join(", "),
1179
+ );
1180
+ }
1181
+ if (jsAnalysis?.indicatorMap?.network?.length) {
1182
+ addSanitizedProperty(
1183
+ properties,
1184
+ "cdx:asar:js:networkIndicators",
1185
+ jsAnalysis.indicatorMap.network.join(", "),
1186
+ );
1187
+ }
1188
+ if (jsAnalysis?.indicatorMap?.hardware?.length) {
1189
+ addSanitizedProperty(
1190
+ properties,
1191
+ "cdx:asar:js:hardwareIndicators",
1192
+ jsAnalysis.indicatorMap.hardware.join(", "),
1193
+ );
1194
+ }
1195
+ if (suspiciousAnalysis?.executionIndicators?.length) {
1196
+ addSanitizedProperty(
1197
+ properties,
1198
+ "cdx:asar:js:executionIndicators",
1199
+ suspiciousAnalysis.executionIndicators.join(", "),
1200
+ );
1201
+ }
1202
+ if (suspiciousAnalysis?.obfuscationIndicators?.length) {
1203
+ addSanitizedProperty(
1204
+ properties,
1205
+ "cdx:asar:js:obfuscationIndicators",
1206
+ suspiciousAnalysis.obfuscationIndicators.join(", "),
1207
+ );
1208
+ }
1209
+ return {
1210
+ "bom-ref": toFileComponentRef(archivePath, entry.path),
1211
+ evidence: {
1212
+ identity: {
1213
+ confidence: 1,
1214
+ field: "name",
1215
+ methods: [
1216
+ {
1217
+ confidence: 1,
1218
+ technique: "filename",
1219
+ value: archiveLocation,
1220
+ },
1221
+ ],
1222
+ },
1223
+ occurrences: [{ location: archiveLocation }],
1224
+ },
1225
+ hashes: computedHash
1226
+ ? [{ alg: "SHA-256", content: computedHash }]
1227
+ : undefined,
1228
+ name: basename(entry.path),
1229
+ properties,
1230
+ type: "file",
1231
+ version: computedHash || undefined,
1232
+ };
1233
+ }
1234
+
1235
+ /**
1236
+ * Parse an Electron ASAR archive and emit inventory, metadata, and optional
1237
+ * signing information.
1238
+ *
1239
+ * @param {string} archivePath Absolute or relative path to an ASAR archive
1240
+ * @param {Object} [options={}] Parse options
1241
+ * @param {string} [options.asarVirtualPath] Virtual archive identity to use in
1242
+ * BOM references and evidence for nested ASAR recursion
1243
+ * @param {number} [options.specVersion] CycloneDX spec version used to choose
1244
+ * compatible component types
1245
+ * @returns {Promise<Object>} Parsed archive analysis result
1246
+ */
1247
+ export async function parseAsarArchive(archivePath, options = {}) {
1248
+ const resolvedArchivePath = resolve(archivePath);
1249
+ const parsedArchive = listAsarEntries(resolvedArchivePath);
1250
+ const archiveIdentityPath =
1251
+ typeof options?.asarVirtualPath === "string" && options.asarVirtualPath
1252
+ ? options.asarVirtualPath
1253
+ : resolvedArchivePath;
1254
+ const signingInfo = collectAsarSigningInfo(
1255
+ resolvedArchivePath,
1256
+ parsedArchive.headerString,
1257
+ );
1258
+ const summary = {
1259
+ capabilities: new Set(),
1260
+ directoryCount: 0,
1261
+ entryCount: parsedArchive.entries.length,
1262
+ executionIndicators: new Set(),
1263
+ fileCount: 0,
1264
+ headerHash: sha256Buffer(Buffer.from(parsedArchive.headerString, "utf8")),
1265
+ hasDynamicFetch: false,
1266
+ hasDynamicImport: false,
1267
+ hasEval: false,
1268
+ integrityMismatchCount: 0,
1269
+ jsFileCount: 0,
1270
+ lockfileCount: 0,
1271
+ nativeAddonCount: 0,
1272
+ nestedArchiveCount: 0,
1273
+ networkIndicators: new Set(),
1274
+ obfuscationIndicators: new Set(),
1275
+ packageJsonCount: 0,
1276
+ signingInfo,
1277
+ symlinkCount: 0,
1278
+ unpackedFileCount: 0,
1279
+ };
1280
+ const components = [];
1281
+ const dependencies = [];
1282
+ const packageManifestPaths = [];
1283
+ let primaryPackageJson;
1284
+ const primaryPackagePath = inferPrimaryPackagePath(parsedArchive.entries);
1285
+ let archiveFd;
1286
+ try {
1287
+ for (const entry of parsedArchive.entries) {
1288
+ if (entry.type === "directory") {
1289
+ summary.directoryCount += 1;
1290
+ continue;
1291
+ }
1292
+ if (entry.type === "link") {
1293
+ summary.symlinkCount += 1;
1294
+ components.push(
1295
+ createArchiveEntryComponent(archiveIdentityPath, entry, undefined),
1296
+ );
1297
+ continue;
1298
+ }
1299
+ summary.fileCount += 1;
1300
+ if (entry.unpacked) {
1301
+ summary.unpackedFileCount += 1;
1302
+ }
1303
+ if (basename(entry.path) === "package.json") {
1304
+ summary.packageJsonCount += 1;
1305
+ packageManifestPaths.push(entry.path);
1306
+ }
1307
+ if (ASAR_LOCKFILE_NAMES.has(basename(entry.path))) {
1308
+ summary.lockfileCount += 1;
1309
+ }
1310
+ if (extname(entry.path) === ".asar") {
1311
+ summary.nestedArchiveCount += 1;
1312
+ }
1313
+ if (extname(entry.path) === ".node") {
1314
+ summary.nativeAddonCount += 1;
1315
+ }
1316
+ let computedHash;
1317
+ let fileBuffer;
1318
+ let jsAnalysis;
1319
+ let suspiciousAnalysis;
1320
+ try {
1321
+ if (!entry.unpacked && archiveFd === undefined) {
1322
+ archiveFd = openSync(resolvedArchivePath, "r");
1323
+ }
1324
+ fileBuffer = readAsarEntryBufferSync(
1325
+ resolvedArchivePath,
1326
+ parsedArchive.archiveDataOffset,
1327
+ entry,
1328
+ archiveFd,
1329
+ );
1330
+ computedHash = sha256Buffer(fileBuffer);
1331
+ if (
1332
+ entry.integrity?.hash &&
1333
+ computedHash !== String(entry.integrity.hash).toLowerCase()
1334
+ ) {
1335
+ summary.integrityMismatchCount += 1;
1336
+ }
1337
+ if (
1338
+ entry.path === primaryPackagePath &&
1339
+ basename(entry.path) === "package.json"
1340
+ ) {
1341
+ try {
1342
+ primaryPackageJson = JSON.parse(fileBuffer.toString("utf8"));
1343
+ } catch {
1344
+ // Ignore malformed package metadata and fall back to archive name.
1345
+ }
1346
+ }
1347
+ } catch (error) {
1348
+ thoughtLog("Error reading ASAR entry", entry.path, error.message);
1349
+ throw error;
1350
+ }
1351
+ if (ASAR_JS_ANALYSIS_EXTENSIONS.has(extname(entry.path))) {
1352
+ summary.jsFileCount += 1;
1353
+ const sourceBuffer =
1354
+ fileBuffer ||
1355
+ (entry.unpacked
1356
+ ? readFileSync(
1357
+ resolveUnpackedEntryPath(resolvedArchivePath, entry.path),
1358
+ )
1359
+ : undefined);
1360
+ if (sourceBuffer) {
1361
+ const sourceText = sourceBuffer.toString("utf8");
1362
+ jsAnalysis = analyzeJsCapabilitiesSource(sourceText);
1363
+ suspiciousAnalysis = analyzeSuspiciousJsSource(sourceText);
1364
+ }
1365
+ }
1366
+ jsAnalysis?.capabilities?.forEach((capability) => {
1367
+ summary.capabilities.add(capability);
1368
+ });
1369
+ suspiciousAnalysis?.executionIndicators?.forEach((indicator) => {
1370
+ summary.executionIndicators.add(indicator);
1371
+ if (indicator === "eval") {
1372
+ summary.hasEval = true;
1373
+ }
1374
+ });
1375
+ suspiciousAnalysis?.networkIndicators?.forEach((indicator) => {
1376
+ summary.networkIndicators.add(indicator);
1377
+ });
1378
+ suspiciousAnalysis?.obfuscationIndicators?.forEach((indicator) => {
1379
+ summary.obfuscationIndicators.add(indicator);
1380
+ });
1381
+ if (jsAnalysis?.hasDynamicFetch) {
1382
+ summary.hasDynamicFetch = true;
1383
+ }
1384
+ if (jsAnalysis?.hasDynamicImport) {
1385
+ summary.hasDynamicImport = true;
1386
+ }
1387
+ components.push(
1388
+ createArchiveEntryComponent(
1389
+ archiveIdentityPath,
1390
+ entry,
1391
+ computedHash,
1392
+ jsAnalysis,
1393
+ suspiciousAnalysis,
1394
+ ),
1395
+ );
1396
+ }
1397
+ } finally {
1398
+ if (archiveFd !== undefined) {
1399
+ closeSync(archiveFd);
1400
+ }
1401
+ }
1402
+ const normalizedSummary = {
1403
+ ...summary,
1404
+ capabilities: Array.from(summary.capabilities).sort(),
1405
+ executionIndicators: Array.from(summary.executionIndicators).sort(),
1406
+ networkIndicators: Array.from(summary.networkIndicators).sort(),
1407
+ obfuscationIndicators: Array.from(summary.obfuscationIndicators).sort(),
1408
+ };
1409
+ const parentComponent = createArchiveParentComponent(
1410
+ archiveIdentityPath,
1411
+ normalizedSummary,
1412
+ primaryPackageJson,
1413
+ primaryPackagePath,
1414
+ );
1415
+ if (signingInfo) {
1416
+ const signingComponent = createAsarSigningComponent(
1417
+ archiveIdentityPath,
1418
+ signingInfo,
1419
+ options,
1420
+ );
1421
+ components.push(signingComponent);
1422
+ if (parentComponent?.["bom-ref"] && signingComponent?.["bom-ref"]) {
1423
+ dependencies.push({
1424
+ ref: parentComponent["bom-ref"],
1425
+ dependsOn: [signingComponent["bom-ref"]],
1426
+ });
1427
+ }
1428
+ }
1429
+ recordActivity({
1430
+ capability: "archive-analysis",
1431
+ kind: "read",
1432
+ reason: `Cataloged ${normalizedSummary.fileCount} ASAR file entr${normalizedSummary.fileCount === 1 ? "y" : "ies"} from ${resolvedArchivePath}.`,
1433
+ status: "completed",
1434
+ target: resolvedArchivePath,
1435
+ });
1436
+ return {
1437
+ components,
1438
+ dependencies,
1439
+ entries: parsedArchive.entries,
1440
+ packageManifestPaths,
1441
+ parentComponent,
1442
+ primaryPackageJson,
1443
+ primaryPackagePath,
1444
+ summary: normalizedSummary,
1445
+ };
1446
+ }
1447
+
1448
+ function extractAsarArchive(archivePath, targetDir) {
1449
+ const parsedArchive = listAsarEntries(archivePath);
1450
+ const validatedSymlinkTargets = validateArchiveSymlinkEntries(
1451
+ parsedArchive.entries,
1452
+ );
1453
+ safeMkdirSync(targetDir, { recursive: true });
1454
+ let archiveFd;
1455
+ try {
1456
+ for (const entry of parsedArchive.entries) {
1457
+ const destinationPath = resolve(
1458
+ targetDir,
1459
+ ...normalizeArchiveRelativePath(entry.path).split("/"),
1460
+ );
1461
+ if (!isPathWithin(targetDir, destinationPath)) {
1462
+ throw new Error(
1463
+ `Refusing to extract ASAR entry outside target dir: ${entry.path}`,
1464
+ );
1465
+ }
1466
+ if (entry.type === "directory") {
1467
+ safeMkdirSync(destinationPath, { recursive: true });
1468
+ continue;
1469
+ }
1470
+ safeMkdirSync(dirname(destinationPath), { recursive: true });
1471
+ if (entry.type === "link") {
1472
+ const validatedLinkTarget = validatedSymlinkTargets.get(
1473
+ normalizeArchiveRelativePath(entry.path),
1474
+ );
1475
+ const resolvedLinkTargetPath = resolve(
1476
+ targetDir,
1477
+ ...validatedLinkTarget.split("/"),
1478
+ );
1479
+ if (!isPathWithin(targetDir, resolvedLinkTargetPath)) {
1480
+ throw new Error(
1481
+ `ASAR symlink ${entry.path} target escapes extraction root: ${validatedLinkTarget}`,
1482
+ );
1483
+ }
1484
+ const relativeLinkTarget = relative(
1485
+ dirname(destinationPath),
1486
+ resolvedLinkTargetPath,
1487
+ );
1488
+ try {
1489
+ symlinkSync(relativeLinkTarget, destinationPath);
1490
+ } catch (error) {
1491
+ if (process.platform === "win32") {
1492
+ thoughtLog(
1493
+ "Unable to recreate ASAR symlink on Windows; falling back",
1494
+ entry.path,
1495
+ error.message,
1496
+ );
1497
+ try {
1498
+ const linkTargetStats = statSync(resolvedLinkTargetPath);
1499
+ if (linkTargetStats.isDirectory()) {
1500
+ safeMkdirSync(destinationPath, { recursive: true });
1501
+ } else if (linkTargetStats.isFile()) {
1502
+ safeCopyFileSync(resolvedLinkTargetPath, destinationPath);
1503
+ }
1504
+ continue;
1505
+ } catch {
1506
+ continue;
1507
+ }
1508
+ }
1509
+ throw new Error(
1510
+ `Failed to recreate ASAR symlink ${entry.path} -> ${validatedLinkTarget} at ${destinationPath}: ${error.message}`,
1511
+ );
1512
+ }
1513
+ continue;
1514
+ }
1515
+ if (entry.unpacked) {
1516
+ safeCopyFileSync(
1517
+ resolveUnpackedEntryPath(archivePath, entry.path),
1518
+ destinationPath,
1519
+ );
1520
+ continue;
1521
+ }
1522
+ if (archiveFd === undefined) {
1523
+ archiveFd = openSync(archivePath, "r");
1524
+ }
1525
+ const fileBuffer = readPackedEntryBuffer(
1526
+ archivePath,
1527
+ parsedArchive.archiveDataOffset,
1528
+ entry,
1529
+ archiveFd,
1530
+ );
1531
+ safeWriteSync(destinationPath, fileBuffer);
1532
+ if (entry.executable && process.platform !== "win32") {
1533
+ try {
1534
+ chmodSync(destinationPath, 0o755);
1535
+ } catch (error) {
1536
+ throw new Error(
1537
+ `Failed to mark extracted ASAR entry ${entry.path} executable at ${destinationPath}: ${error.message}`,
1538
+ );
1539
+ }
1540
+ }
1541
+ }
1542
+ } finally {
1543
+ if (archiveFd !== undefined) {
1544
+ closeSync(archiveFd);
1545
+ }
1546
+ }
1547
+ }
1548
+
1549
+ /**
1550
+ * Synchronously extracts an Electron ASAR archive to a temporary directory.
1551
+ *
1552
+ * @param {string} archivePath - Path to the ASAR archive to extract
1553
+ * @returns {Promise<string|undefined>} Resolves to the path of the temporary directory, or undefined if extraction fails
1554
+ */
1555
+ export async function extractAsarToTempDir(archivePath) {
1556
+ let tempDir;
1557
+ try {
1558
+ tempDir = safeMkdtempSync(join(getTmpDir(), "asar-deps-"));
1559
+ const extracted = await safeExtractArchive(
1560
+ archivePath,
1561
+ tempDir,
1562
+ async () => {
1563
+ extractAsarArchive(archivePath, tempDir);
1564
+ },
1565
+ "asar",
1566
+ {
1567
+ metadata: { archivePath },
1568
+ },
1569
+ );
1570
+ if (!extracted) {
1571
+ return undefined;
1572
+ }
1573
+ return tempDir;
1574
+ } catch (error) {
1575
+ if (DEBUG_MODE) {
1576
+ console.log(
1577
+ `Error extracting ASAR archive ${archivePath}:`,
1578
+ error.message,
1579
+ );
1580
+ }
1581
+ cleanupAsarTempDir(tempDir);
1582
+ return undefined;
1583
+ }
1584
+ }
1585
+
1586
+ /**
1587
+ * Cleans up a temporary directory that was used for ASAR extraction.
1588
+ *
1589
+ * @param {string} tempDir - Path to the temporary directory to remove
1590
+ */
1591
+ export function cleanupAsarTempDir(tempDir) {
1592
+ if (!tempDir) {
1593
+ return;
1594
+ }
1595
+ const resolvedDir = resolve(tempDir);
1596
+ const expectedBase = resolve(getTmpDir());
1597
+ if (
1598
+ basename(resolvedDir).startsWith("asar-deps-") &&
1599
+ resolve(resolvedDir, "..") === expectedBase
1600
+ ) {
1601
+ safeRmSync(resolvedDir, { force: true, recursive: true });
1602
+ }
1603
+ }
1604
+
1605
+ /**
1606
+ * Builds BOM properties summarizing the extraction status and manifest counts of an ASAR archive.
1607
+ *
1608
+ * @param {Object} archiveAnalysis - The parsed archive analysis result
1609
+ * @param {boolean} extractionPerformed - Whether the extraction was actually executed
1610
+ * @returns {Array<Object>} List of CycloneDX component properties
1611
+ */
1612
+ export function buildAsarExtractionSummary(
1613
+ archiveAnalysis,
1614
+ extractionPerformed,
1615
+ ) {
1616
+ const properties = [];
1617
+ if (archiveAnalysis?.packageManifestPaths?.length) {
1618
+ addSanitizedProperty(
1619
+ properties,
1620
+ "cdx:asar:embeddedManifests",
1621
+ archiveAnalysis.packageManifestPaths
1622
+ .map((manifestPath) =>
1623
+ toArchiveOccurrence("", manifestPath).replace(/^#/, ""),
1624
+ )
1625
+ .join(", "),
1626
+ );
1627
+ }
1628
+ if (archiveAnalysis?.summary?.packageJsonCount) {
1629
+ addSanitizedProperty(
1630
+ properties,
1631
+ "cdx:asar:manifestInventoryComplete",
1632
+ String(!isDryRun || extractionPerformed),
1633
+ );
1634
+ }
1635
+ return properties;
1636
+ }