@js-recon/js-recon 1.4.4 → 2.0.1-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (424) hide show
  1. package/.claude-sync/sync.sh +1 -1
  2. package/.github/workflows/build-and-prettify.yaml +49 -19
  3. package/.github/workflows/codeql.yml +33 -0
  4. package/.github/workflows/exploit-smoke-test.yaml +160 -0
  5. package/.github/workflows/framework-detection-smoke-test.yaml +135 -0
  6. package/.github/workflows/plumber.yml +20 -0
  7. package/.github/workflows/promote-js-recon.yml +5 -3
  8. package/.github/workflows/publish-js-recon.yml +6 -1
  9. package/.github/workflows/rules-smoke-test.yaml +13 -5
  10. package/.nvmrc +1 -0
  11. package/.plumber.yaml +151 -0
  12. package/CHANGELOG.md +35 -0
  13. package/CONTRIBUTING.md +32 -0
  14. package/Dockerfile +1 -0
  15. package/README.md +3 -2
  16. package/SECURITY.md +1 -1
  17. package/build/analyze/engine/astEngine.js +10 -9
  18. package/build/analyze/engine/astEngine.js.map +1 -1
  19. package/build/analyze/engine/csMastSEngine.js +6 -6
  20. package/build/analyze/engine/csMastSEngine.js.map +1 -1
  21. package/build/analyze/engine/index.js +1 -1
  22. package/build/analyze/engine/index.js.map +1 -1
  23. package/build/analyze/engine/requestEngine.js +6 -6
  24. package/build/analyze/engine/requestEngine.js.map +1 -1
  25. package/build/analyze/helpers/determineCompatibleVersion.js +70 -0
  26. package/build/analyze/helpers/determineCompatibleVersion.js.map +1 -0
  27. package/build/analyze/helpers/engineHelpers/findMemberExpressionAssignment.js +9 -3
  28. package/build/analyze/helpers/engineHelpers/findMemberExpressionAssignment.js.map +1 -1
  29. package/build/analyze/helpers/initRules.js +9 -9
  30. package/build/analyze/helpers/initRules.js.map +1 -1
  31. package/build/analyze/helpers/outputHelper.js +3 -3
  32. package/build/analyze/helpers/outputHelper.js.map +1 -1
  33. package/build/analyze/helpers/schemas.js +1 -0
  34. package/build/analyze/helpers/schemas.js.map +1 -1
  35. package/build/analyze/helpers/validate.js +9 -5
  36. package/build/analyze/helpers/validate.js.map +1 -1
  37. package/build/analyze/index.js +26 -16
  38. package/build/analyze/index.js.map +1 -1
  39. package/build/cliProgram.js +710 -0
  40. package/build/cliProgram.js.map +1 -0
  41. package/build/completion/index.js +247 -382
  42. package/build/completion/index.js.map +1 -1
  43. package/build/completion/introspect.js +17 -0
  44. package/build/completion/introspect.js.map +1 -0
  45. package/build/config/applicationConfig.js +3 -2
  46. package/build/config/applicationConfig.js.map +1 -1
  47. package/build/cs_mast/index.js +18 -17
  48. package/build/cs_mast/index.js.map +1 -1
  49. package/build/endpoints/gen_report/gen_json.js +2 -2
  50. package/build/endpoints/gen_report/gen_json.js.map +1 -1
  51. package/build/endpoints/gen_report/utility/iterate_n_store.js +1 -1
  52. package/build/endpoints/gen_report/utility/iterate_n_store.js.map +1 -1
  53. package/build/endpoints/index.js +12 -12
  54. package/build/endpoints/index.js.map +1 -1
  55. package/build/endpoints/next_js/client_jsFilesHref.js +3 -3
  56. package/build/endpoints/next_js/client_jsFilesHref.js.map +1 -1
  57. package/build/endpoints/next_js/client_jsonParse.js +4 -4
  58. package/build/endpoints/next_js/client_jsonParse.js.map +1 -1
  59. package/build/endpoints/next_js/client_mappedJsonFile.js +6 -6
  60. package/build/endpoints/next_js/client_mappedJsonFile.js.map +1 -1
  61. package/build/endpoints/next_js/client_subsequentRequests.js +5 -5
  62. package/build/endpoints/next_js/client_subsequentRequests.js.map +1 -1
  63. package/build/exploit/angular/cve-2026-68945.js +61 -0
  64. package/build/exploit/angular/cve-2026-68945.js.map +1 -0
  65. package/build/exploit/index.js +60 -0
  66. package/build/exploit/index.js.map +1 -0
  67. package/build/exploit/next/cve-2025-29927.js +65 -0
  68. package/build/exploit/next/cve-2025-29927.js.map +1 -0
  69. package/build/exploit/next/cve-2026-64645.js +51 -0
  70. package/build/exploit/next/cve-2026-64645.js.map +1 -0
  71. package/build/exploit/nuxt/cve-2026-71315.js +47 -0
  72. package/build/exploit/nuxt/cve-2026-71315.js.map +1 -0
  73. package/build/exploit/nuxt/cve-2026-71320.js +114 -0
  74. package/build/exploit/nuxt/cve-2026-71320.js.map +1 -0
  75. package/build/exploit/react/cve-2025-55182.js +116 -0
  76. package/build/exploit/react/cve-2025-55182.js.map +1 -0
  77. package/build/exploit/registry/cveRegistry.js +115 -0
  78. package/build/exploit/registry/cveRegistry.js.map +1 -0
  79. package/build/exploit/types.js +2 -0
  80. package/build/exploit/types.js.map +1 -0
  81. package/build/exploit/utility/compareResponses.js +29 -0
  82. package/build/exploit/utility/compareResponses.js.map +1 -0
  83. package/build/exploit/utility/outputHelper.js +22 -0
  84. package/build/exploit/utility/outputHelper.js.map +1 -0
  85. package/build/exploit/utility/rawRequest.js +54 -0
  86. package/build/exploit/utility/rawRequest.js.map +1 -0
  87. package/build/exploit/utility/sandboxRce.js +49 -0
  88. package/build/exploit/utility/sandboxRce.js.map +1 -0
  89. package/build/exploit/utility/toEngineOutput.js +28 -0
  90. package/build/exploit/utility/toEngineOutput.js.map +1 -0
  91. package/build/exploit/utility/wsClient.js +78 -0
  92. package/build/exploit/utility/wsClient.js.map +1 -0
  93. package/build/exploit/vite/cve-2025-30208.js +44 -0
  94. package/build/exploit/vite/cve-2025-30208.js.map +1 -0
  95. package/build/exploit/vite/cve-2026-39363.js +60 -0
  96. package/build/exploit/vite/cve-2026-39363.js.map +1 -0
  97. package/build/fingerprint/index.js +3 -2
  98. package/build/fingerprint/index.js.map +1 -1
  99. package/build/globalConfig.js +2 -2
  100. package/build/globalConfig.js.map +1 -1
  101. package/build/index.js +5 -596
  102. package/build/index.js.map +1 -1
  103. package/build/lazyLoad/angular/angular_getFromPageSource.js +3 -3
  104. package/build/lazyLoad/angular/angular_getFromPageSource.js.map +1 -1
  105. package/build/lazyLoad/downloadFilesUtil.js +14 -11
  106. package/build/lazyLoad/downloadFilesUtil.js.map +1 -1
  107. package/build/lazyLoad/downloadQueue.js +5 -1
  108. package/build/lazyLoad/downloadQueue.js.map +1 -1
  109. package/build/lazyLoad/downloadResponse.js +1 -0
  110. package/build/lazyLoad/downloadResponse.js.map +1 -1
  111. package/build/lazyLoad/generic/generic_crawlPages.js +186 -0
  112. package/build/lazyLoad/generic/generic_crawlPages.js.map +1 -0
  113. package/build/lazyLoad/generic/generic_downloadFiles.js +81 -0
  114. package/build/lazyLoad/generic/generic_downloadFiles.js.map +1 -0
  115. package/build/lazyLoad/generic/generic_extractLinks.js +79 -0
  116. package/build/lazyLoad/generic/generic_extractLinks.js.map +1 -0
  117. package/build/lazyLoad/generic/generic_getScriptTags.js +152 -0
  118. package/build/lazyLoad/generic/generic_getScriptTags.js.map +1 -0
  119. package/build/lazyLoad/generic/generic_importMapDiscovery.js +87 -0
  120. package/build/lazyLoad/generic/generic_importMapDiscovery.js.map +1 -0
  121. package/build/lazyLoad/generic/generic_resolveScope.js +61 -0
  122. package/build/lazyLoad/generic/generic_resolveScope.js.map +1 -0
  123. package/build/lazyLoad/generic/generic_scanAttributesForJs.js +122 -0
  124. package/build/lazyLoad/generic/generic_scanAttributesForJs.js.map +1 -0
  125. package/build/lazyLoad/generic/generic_stringsDiscovery.js +103 -0
  126. package/build/lazyLoad/generic/generic_stringsDiscovery.js.map +1 -0
  127. package/build/lazyLoad/generic/generic_webpackChunkPaths.js +56 -0
  128. package/build/lazyLoad/generic/generic_webpackChunkPaths.js.map +1 -0
  129. package/build/lazyLoad/globals.js +31 -0
  130. package/build/lazyLoad/globals.js.map +1 -1
  131. package/build/lazyLoad/index.js +129 -66
  132. package/build/lazyLoad/index.js.map +1 -1
  133. package/build/lazyLoad/methodFilter.js +2 -0
  134. package/build/lazyLoad/methodFilter.js.map +1 -1
  135. package/build/lazyLoad/next_js/NextJsCrawler.js +38 -14
  136. package/build/lazyLoad/next_js/NextJsCrawler.js.map +1 -1
  137. package/build/lazyLoad/next_js/next_GetJSScript.js +3 -3
  138. package/build/lazyLoad/next_js/next_GetJSScript.js.map +1 -1
  139. package/build/lazyLoad/next_js/next_GetLazyResourcesBuildManifestJs.js +4 -4
  140. package/build/lazyLoad/next_js/next_GetLazyResourcesBuildManifestJs.js.map +1 -1
  141. package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js +13 -11
  142. package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js.map +1 -1
  143. package/build/lazyLoad/next_js/next_SubsequentRequests.js +7 -6
  144. package/build/lazyLoad/next_js/next_SubsequentRequests.js.map +1 -1
  145. package/build/lazyLoad/next_js/next_bruteForceJsFiles.js +1 -1
  146. package/build/lazyLoad/next_js/next_bruteForceJsFiles.js.map +1 -1
  147. package/build/lazyLoad/next_js/next_buildId.js +2 -2
  148. package/build/lazyLoad/next_js/next_buildId.js.map +1 -1
  149. package/build/lazyLoad/next_js/next_getClientSidePaths.js +2 -2
  150. package/build/lazyLoad/next_js/next_getClientSidePaths.js.map +1 -1
  151. package/build/lazyLoad/next_js/next_parseLayoutJs.js +6 -6
  152. package/build/lazyLoad/next_js/next_parseLayoutJs.js.map +1 -1
  153. package/build/lazyLoad/next_js/next_promiseResolve.js +1 -1
  154. package/build/lazyLoad/next_js/next_promiseResolve.js.map +1 -1
  155. package/build/lazyLoad/next_js/next_routerStateForge.js +341 -0
  156. package/build/lazyLoad/next_js/next_routerStateForge.js.map +1 -0
  157. package/build/lazyLoad/next_js/next_scriptTagsSubsequentRequests.js +1 -1
  158. package/build/lazyLoad/next_js/next_scriptTagsSubsequentRequests.js.map +1 -1
  159. package/build/lazyLoad/next_js/next_serverActionIdScan.js +77 -0
  160. package/build/lazyLoad/next_js/next_serverActionIdScan.js.map +1 -0
  161. package/build/lazyLoad/nuxt_js/nuxt_astParse.js +15 -13
  162. package/build/lazyLoad/nuxt_js/nuxt_astParse.js.map +1 -1
  163. package/build/lazyLoad/nuxt_js/nuxt_getBuildsManifest.js +2 -2
  164. package/build/lazyLoad/nuxt_js/nuxt_getBuildsManifest.js.map +1 -1
  165. package/build/lazyLoad/nuxt_js/nuxt_getFromPageSource.js +3 -3
  166. package/build/lazyLoad/nuxt_js/nuxt_getFromPageSource.js.map +1 -1
  167. package/build/lazyLoad/nuxt_js/nuxt_stringAnalysisJSFiles.js +2 -2
  168. package/build/lazyLoad/nuxt_js/nuxt_stringAnalysisJSFiles.js.map +1 -1
  169. package/build/lazyLoad/react/react_webpackChunkPaths.js +10 -202
  170. package/build/lazyLoad/react/react_webpackChunkPaths.js.map +1 -1
  171. package/build/lazyLoad/researchUtils.js +15 -0
  172. package/build/lazyLoad/researchUtils.js.map +1 -0
  173. package/build/lazyLoad/shared/webpackChunkParsers.js +218 -0
  174. package/build/lazyLoad/shared/webpackChunkParsers.js.map +1 -0
  175. package/build/lazyLoad/stagnation/stagnationMonitor.js +63 -0
  176. package/build/lazyLoad/stagnation/stagnationMonitor.js.map +1 -0
  177. package/build/lazyLoad/svelte/svelte_discoverPagesFromJs.js +1 -0
  178. package/build/lazyLoad/svelte/svelte_discoverPagesFromJs.js.map +1 -1
  179. package/build/lazyLoad/svelte/svelte_getFromPageSource.js +5 -5
  180. package/build/lazyLoad/svelte/svelte_getFromPageSource.js.map +1 -1
  181. package/build/lazyLoad/svelte/svelte_getVersionJson.js +2 -2
  182. package/build/lazyLoad/svelte/svelte_getVersionJson.js.map +1 -1
  183. package/build/lazyLoad/svelte/svelte_recursivePageCrawl.js +6 -6
  184. package/build/lazyLoad/svelte/svelte_recursivePageCrawl.js.map +1 -1
  185. package/build/lazyLoad/svelte/svelte_stringAnalysisJSFiles.js +2 -2
  186. package/build/lazyLoad/svelte/svelte_stringAnalysisJSFiles.js.map +1 -1
  187. package/build/lazyLoad/techDetect/checkAngularJS.js +1 -1
  188. package/build/lazyLoad/techDetect/checkAngularJS.js.map +1 -1
  189. package/build/lazyLoad/techDetect/checkNuxtJS.js +3 -3
  190. package/build/lazyLoad/techDetect/checkNuxtJS.js.map +1 -1
  191. package/build/lazyLoad/techDetect/checkSvelte.js +0 -1
  192. package/build/lazyLoad/techDetect/checkSvelte.js.map +1 -1
  193. package/build/lazyLoad/techDetect/checkVueJS.js +6 -6
  194. package/build/lazyLoad/techDetect/checkVueJS.js.map +1 -1
  195. package/build/lazyLoad/techDetect/index.js +13 -1
  196. package/build/lazyLoad/techDetect/index.js.map +1 -1
  197. package/build/lazyLoad/vue/vue_SingleJsFileOnHome.js +2 -2
  198. package/build/lazyLoad/vue/vue_SingleJsFileOnHome.js.map +1 -1
  199. package/build/lazyLoad/vue/vue_discoverJsFiles.js +12 -10
  200. package/build/lazyLoad/vue/vue_discoverJsFiles.js.map +1 -1
  201. package/build/lazyLoad/vue/vue_getClientSidePaths.js +1 -1
  202. package/build/lazyLoad/vue/vue_getClientSidePaths.js.map +1 -1
  203. package/build/lazyLoad/vue/vue_pageSrc.js +1 -1
  204. package/build/lazyLoad/vue/vue_pageSrc.js.map +1 -1
  205. package/build/lazyLoad/vue/vue_reconstructSourceMaps.js +2 -2
  206. package/build/lazyLoad/vue/vue_reconstructSourceMaps.js.map +1 -1
  207. package/build/lazyLoad/vue/vue_recursiveClientSidePathDownload.js +2 -2
  208. package/build/lazyLoad/vue/vue_recursiveClientSidePathDownload.js.map +1 -1
  209. package/build/lazyLoad/vue/vue_severalJsFilesHome.js +3 -3
  210. package/build/lazyLoad/vue/vue_severalJsFilesHome.js.map +1 -1
  211. package/build/load/index.js +8 -7
  212. package/build/load/index.js.map +1 -1
  213. package/build/map/angular_js/getAngularConnections.js +6 -6
  214. package/build/map/angular_js/getAngularConnections.js.map +1 -1
  215. package/build/map/graphql/resolveGraphql.js +6 -6
  216. package/build/map/graphql/resolveGraphql.js.map +1 -1
  217. package/build/map/index.js +17 -17
  218. package/build/map/index.js.map +1 -1
  219. package/build/map/interactive-mode/commandHandler.js +278 -0
  220. package/build/map/interactive-mode/commandHandler.js.map +1 -0
  221. package/build/map/interactive-mode/commandHelpers.js +189 -0
  222. package/build/map/interactive-mode/commandHelpers.js.map +1 -0
  223. package/build/map/interactive-mode/esqueryGen.js.map +1 -0
  224. package/build/map/interactive-mode/helpMenu.js +11 -0
  225. package/build/map/interactive-mode/helpMenu.js.map +1 -0
  226. package/build/map/interactive-mode/inputPatch.js.map +1 -0
  227. package/build/map/interactive-mode/interactive.js +71 -0
  228. package/build/map/interactive-mode/interactive.js.map +1 -0
  229. package/build/map/interactive-mode/keybindings.js.map +1 -0
  230. package/build/map/interactive-mode/printer.js.map +1 -0
  231. package/build/map/interactive-mode/ui.js.map +1 -0
  232. package/build/map/next_js/getAxiosInstances.js +5 -5
  233. package/build/map/next_js/getAxiosInstances.js.map +1 -1
  234. package/build/map/next_js/getExports.js +4 -4
  235. package/build/map/next_js/getExports.js.map +1 -1
  236. package/build/map/next_js/getFetchInstances.js +10 -10
  237. package/build/map/next_js/getFetchInstances.js.map +1 -1
  238. package/build/map/next_js/getTurbopackConnections.js +8 -8
  239. package/build/map/next_js/getTurbopackConnections.js.map +1 -1
  240. package/build/map/next_js/getWebpackConnections.js +27 -16
  241. package/build/map/next_js/getWebpackConnections.js.map +1 -1
  242. package/build/map/next_js/interactive.js +3 -65
  243. package/build/map/next_js/interactive.js.map +1 -1
  244. package/build/map/next_js/interactive_helpers/commandHandler.js +38 -290
  245. package/build/map/next_js/interactive_helpers/commandHandler.js.map +1 -1
  246. package/build/map/next_js/interactive_helpers/commandHelpers.js +0 -184
  247. package/build/map/next_js/interactive_helpers/commandHelpers.js.map +1 -1
  248. package/build/map/next_js/interactive_helpers/helpMenu.js +2 -10
  249. package/build/map/next_js/interactive_helpers/helpMenu.js.map +1 -1
  250. package/build/map/next_js/resolveAxios.js +6 -6
  251. package/build/map/next_js/resolveAxios.js.map +1 -1
  252. package/build/map/next_js/resolveAxiosHelpers/findAxiosClients.js +4 -4
  253. package/build/map/next_js/resolveAxiosHelpers/findAxiosClients.js.map +1 -1
  254. package/build/map/next_js/resolveAxiosHelpers/findAxiosInstance.js +2 -2
  255. package/build/map/next_js/resolveAxiosHelpers/findAxiosInstance.js.map +1 -1
  256. package/build/map/next_js/resolveAxiosHelpers/findCrossChunkParams.js +5 -5
  257. package/build/map/next_js/resolveAxiosHelpers/findCrossChunkParams.js.map +1 -1
  258. package/build/map/next_js/resolveAxiosHelpers/handleAxiosCreate.js +10 -10
  259. package/build/map/next_js/resolveAxiosHelpers/handleAxiosCreate.js.map +1 -1
  260. package/build/map/next_js/resolveAxiosHelpers/handleZDotCreate.js +13 -9
  261. package/build/map/next_js/resolveAxiosHelpers/handleZDotCreate.js.map +1 -1
  262. package/build/map/next_js/resolveAxiosHelpers/processAxiosCall.js +12 -8
  263. package/build/map/next_js/resolveAxiosHelpers/processAxiosCall.js.map +1 -1
  264. package/build/map/next_js/resolveAxiosHelpers/processDirectAxiosCall.js +12 -8
  265. package/build/map/next_js/resolveAxiosHelpers/processDirectAxiosCall.js.map +1 -1
  266. package/build/map/next_js/resolveAxiosHelpers/processExportedEndpoints.js +11 -11
  267. package/build/map/next_js/resolveAxiosHelpers/processExportedEndpoints.js.map +1 -1
  268. package/build/map/next_js/resolveAxiosHelpers/traceAxiosInstanceExports.js +16 -16
  269. package/build/map/next_js/resolveAxiosHelpers/traceAxiosInstanceExports.js.map +1 -1
  270. package/build/map/next_js/resolveFetch.js +23 -23
  271. package/build/map/next_js/resolveFetch.js.map +1 -1
  272. package/build/map/next_js/resolveNewRequest.js +10 -10
  273. package/build/map/next_js/resolveNewRequest.js.map +1 -1
  274. package/build/map/next_js/resolveServerActions.js +4 -4
  275. package/build/map/next_js/resolveServerActions.js.map +1 -1
  276. package/build/map/next_js/utils.js +8 -2
  277. package/build/map/next_js/utils.js.map +1 -1
  278. package/build/map/react_js/getReactConnections.js +21 -14
  279. package/build/map/react_js/getReactConnections.js.map +1 -1
  280. package/build/map/svelte_js/interactive.js +3 -54
  281. package/build/map/svelte_js/interactive.js.map +1 -1
  282. package/build/map/vue_js/getViteConnections.js +23 -16
  283. package/build/map/vue_js/getViteConnections.js.map +1 -1
  284. package/build/map/vue_js/interactive.js +3 -63
  285. package/build/map/vue_js/interactive.js.map +1 -1
  286. package/build/map/vue_js/interactive_helpers/commandHandler.js +34 -283
  287. package/build/map/vue_js/interactive_helpers/commandHandler.js.map +1 -1
  288. package/build/map/vue_js/interactive_helpers/helpMenu.js +2 -10
  289. package/build/map/vue_js/interactive_helpers/helpMenu.js.map +1 -1
  290. package/build/map/vue_js/taint_utils.js +1 -1
  291. package/build/map/vue_js/taint_utils.js.map +1 -1
  292. package/build/map/vue_js/vue_resolveFetch.js +12 -12
  293. package/build/map/vue_js/vue_resolveFetch.js.map +1 -1
  294. package/build/map/vue_js/vue_resolveHttpClient.js +18 -18
  295. package/build/map/vue_js/vue_resolveHttpClient.js.map +1 -1
  296. package/build/map/vue_js/vue_resolveXhr.js +11 -11
  297. package/build/map/vue_js/vue_resolveXhr.js.map +1 -1
  298. package/build/mcp/chatOneShot.js +7 -7
  299. package/build/mcp/chatOneShot.js.map +1 -1
  300. package/build/mcp/claudeCodeCreds.js +5 -5
  301. package/build/mcp/claudeCodeCreds.js.map +1 -1
  302. package/build/mcp/cli.js +36 -35
  303. package/build/mcp/cli.js.map +1 -1
  304. package/build/mcp/config.js +4 -4
  305. package/build/mcp/config.js.map +1 -1
  306. package/build/mcp/index.js +7 -7
  307. package/build/mcp/index.js.map +1 -1
  308. package/build/mcp/mcpServer.js +3 -2
  309. package/build/mcp/mcpServer.js.map +1 -1
  310. package/build/mcp/skills.js +1 -0
  311. package/build/mcp/skills.js.map +1 -1
  312. package/build/mcp/tools.js +5 -4
  313. package/build/mcp/tools.js.map +1 -1
  314. package/build/proxy/detectBlockedResponse.js +2 -0
  315. package/build/proxy/detectBlockedResponse.js.map +1 -1
  316. package/build/proxy/index.js +3 -3
  317. package/build/proxy/index.js.map +1 -1
  318. package/build/refactor/index.js +83 -79
  319. package/build/refactor/index.js.map +1 -1
  320. package/build/refactor/next/index.js +69 -26
  321. package/build/refactor/next/index.js.map +1 -1
  322. package/build/refactor/next/transform.js +11 -4
  323. package/build/refactor/next/transform.js.map +1 -1
  324. package/build/refactor/next/validator.js +7 -7
  325. package/build/refactor/next/validator.js.map +1 -1
  326. package/build/refactor/react/index.js +13 -13
  327. package/build/refactor/react/index.js.map +1 -1
  328. package/build/refactor/react/validator.js +7 -7
  329. package/build/refactor/react/validator.js.map +1 -1
  330. package/build/refactor/react-vite/index.js +3 -3
  331. package/build/refactor/react-vite/index.js.map +1 -1
  332. package/build/refactor/remote/hf-client.js +1 -0
  333. package/build/refactor/remote/hf-client.js.map +1 -1
  334. package/build/refactor/remote/version-detect.js +12 -12
  335. package/build/refactor/remote/version-detect.js.map +1 -1
  336. package/build/refactor/vue/index.js +6 -6
  337. package/build/refactor/vue/index.js.map +1 -1
  338. package/build/refactor/vue/vite.js +6 -6
  339. package/build/refactor/vue/vite.js.map +1 -1
  340. package/build/report/index.js +30 -8
  341. package/build/report/index.js.map +1 -1
  342. package/build/report/swaggerJacker.js +63 -0
  343. package/build/report/swaggerJacker.js.map +1 -0
  344. package/build/report/utility/genHtml.js +7 -7
  345. package/build/report/utility/genHtml.js.map +1 -1
  346. package/build/report/utility/populateDb/populateAnalysisFindings.js +2 -2
  347. package/build/report/utility/populateDb/populateAnalysisFindings.js.map +1 -1
  348. package/build/report/utility/populateDb/populateEndpoints.js +3 -3
  349. package/build/report/utility/populateDb/populateEndpoints.js.map +1 -1
  350. package/build/report/utility/populateDb/populateMappedJson.js +2 -2
  351. package/build/report/utility/populateDb/populateMappedJson.js.map +1 -1
  352. package/build/report/utility/populateDb/populateMappedOpenapi.js +3 -3
  353. package/build/report/utility/populateDb/populateMappedOpenapi.js.map +1 -1
  354. package/build/run/bundler-detect.js +45 -9
  355. package/build/run/bundler-detect.js.map +1 -1
  356. package/build/run/dashboard/dashboardHtml.js +150 -0
  357. package/build/run/dashboard/dashboardHtml.js.map +1 -0
  358. package/build/run/dashboard/fsBrowser.js +43 -0
  359. package/build/run/dashboard/fsBrowser.js.map +1 -0
  360. package/build/run/dashboard/server.js +123 -0
  361. package/build/run/dashboard/server.js.map +1 -0
  362. package/build/run/dashboard/state.js +97 -0
  363. package/build/run/dashboard/state.js.map +1 -0
  364. package/build/run/index.js +177 -110
  365. package/build/run/index.js.map +1 -1
  366. package/build/run/interruptHandler.js +18 -0
  367. package/build/run/interruptHandler.js.map +1 -1
  368. package/build/sourcemaps/index.js +7 -6
  369. package/build/sourcemaps/index.js.map +1 -1
  370. package/build/strings/index.js +27 -24
  371. package/build/strings/index.js.map +1 -1
  372. package/build/strings/openapi.js +4 -4
  373. package/build/strings/openapi.js.map +1 -1
  374. package/build/strings/permutate.js +4 -4
  375. package/build/strings/permutate.js.map +1 -1
  376. package/build/strings/secrets.js +1 -0
  377. package/build/strings/secrets.js.map +1 -1
  378. package/build/strings/trufflehog.js +66 -19
  379. package/build/strings/trufflehog.js.map +1 -1
  380. package/build/strings/trufflehogConfig.js +36 -0
  381. package/build/strings/trufflehogConfig.js.map +1 -0
  382. package/build/strings/trufflehogDownload.js +115 -0
  383. package/build/strings/trufflehogDownload.js.map +1 -0
  384. package/build/utility/ai.js +33 -4
  385. package/build/utility/ai.js.map +1 -1
  386. package/build/utility/banner.js +4 -3
  387. package/build/utility/banner.js.map +1 -1
  388. package/build/utility/configureSandbox.js +2 -2
  389. package/build/utility/configureSandbox.js.map +1 -1
  390. package/build/utility/globals.js +19 -11
  391. package/build/utility/globals.js.map +1 -1
  392. package/build/utility/heap.js +2 -1
  393. package/build/utility/heap.js.map +1 -1
  394. package/build/utility/makeReq.js +1 -1
  395. package/build/utility/makeReq.js.map +1 -1
  396. package/build/utility/openapiGenerator.js +2 -2
  397. package/build/utility/openapiGenerator.js.map +1 -1
  398. package/build/utility/printMsg.js +53 -0
  399. package/build/utility/printMsg.js.map +1 -0
  400. package/build/utility/progressLog.js +4 -3
  401. package/build/utility/progressLog.js.map +1 -1
  402. package/build/utility/resolvePath.js +2 -1
  403. package/build/utility/resolvePath.js.map +1 -1
  404. package/build/utility/ruleVersionMap.js +73 -0
  405. package/build/utility/ruleVersionMap.js.map +1 -0
  406. package/contributing/testing.md +106 -0
  407. package/eslint.config.js +24 -0
  408. package/package.json +22 -5
  409. package/scripts/exploit-smoke-test.js +82 -0
  410. package/scripts/framework-detect-smoke-test.js +64 -0
  411. package/scripts/postinstall-completion.mjs +40 -0
  412. package/scripts/smoke-test.js +12 -0
  413. package/build/lazyLoad/downloadLoadedJsUtil.js +0 -98
  414. package/build/lazyLoad/downloadLoadedJsUtil.js.map +0 -1
  415. package/build/map/next_js/interactive_helpers/esqueryGen.js.map +0 -1
  416. package/build/map/next_js/interactive_helpers/inputPatch.js.map +0 -1
  417. package/build/map/next_js/interactive_helpers/keybindings.js.map +0 -1
  418. package/build/map/next_js/interactive_helpers/printer.js.map +0 -1
  419. package/build/map/next_js/interactive_helpers/ui.js.map +0 -1
  420. /package/build/map/{next_js/interactive_helpers → interactive-mode}/esqueryGen.js +0 -0
  421. /package/build/map/{next_js/interactive_helpers → interactive-mode}/inputPatch.js +0 -0
  422. /package/build/map/{next_js/interactive_helpers → interactive-mode}/keybindings.js +0 -0
  423. /package/build/map/{next_js/interactive_helpers → interactive-mode}/printer.js +0 -0
  424. /package/build/map/{next_js/interactive_helpers → interactive-mode}/ui.js +0 -0
@@ -0,0 +1,56 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import fs from "fs";
11
+ import path from "path";
12
+ import { extractWebpackChunkUrls } from "../shared/webpackChunkParsers.js";
13
+ import { extractFileSourceUrl } from "./generic_stringsDiscovery.js";
14
+ import { confirmJsContentType } from "./generic_scanAttributesForJs.js";
15
+ /**
16
+ * Scans every JS file `generic` tech has already downloaded under outputDir for the
17
+ * same webpack chunk-path-builder patterns the React crawler already resolves (see
18
+ * `src/lazyLoad/shared/webpackChunkParsers.ts`). Internal#75: without this, a webpack
19
+ * or module-federation entry chunk downloaded under `generic` tech only ever yields the
20
+ * chunks that happened to fire live during the crawl — its own async-chunk hash-map is
21
+ * never statically enumerated the way React's `react_webpackChunkPaths.ts` already does.
22
+ *
23
+ * Reads from disk (recovering each file's source URL via the same
24
+ * `// File Source: <url>` header `generic_stringsDiscovery.ts` relies on) rather than
25
+ * re-fetching over the network, since the file is already on disk from an earlier
26
+ * download pass.
27
+ */
28
+ const generic_webpackChunkPaths = (outputDir_1, ...args_1) => __awaiter(void 0, [outputDir_1, ...args_1], void 0, function* (outputDir, alreadyKnownUrls = new Set(), threads = 1) {
29
+ if (!fs.existsSync(outputDir))
30
+ return [];
31
+ const files = fs.readdirSync(outputDir, { recursive: true, encoding: "utf8" });
32
+ const jsFiles = files.filter((f) => f.endsWith(".js") || f.endsWith(".mjs"));
33
+ const candidates = new Set();
34
+ for (const relPath of jsFiles) {
35
+ const filePath = path.join(outputDir, relPath);
36
+ let content;
37
+ try {
38
+ content = fs.readFileSync(filePath, "utf-8");
39
+ }
40
+ catch (_a) {
41
+ continue;
42
+ }
43
+ const sourceUrl = extractFileSourceUrl(content);
44
+ if (!sourceUrl)
45
+ continue;
46
+ for (const url of extractWebpackChunkUrls(content, sourceUrl)) {
47
+ if (!alreadyKnownUrls.has(url))
48
+ candidates.add(url);
49
+ }
50
+ }
51
+ if (candidates.size === 0)
52
+ return [];
53
+ return confirmJsContentType([...candidates], threads);
54
+ });
55
+ export default generic_webpackChunkPaths;
56
+ //# sourceMappingURL=generic_webpackChunkPaths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generic_webpackChunkPaths.js","sourceRoot":"","sources":["../../../src/lazyLoad/generic/generic_webpackChunkPaths.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAExE;;;;;;;;;;;;GAYG;AACH,MAAM,yBAAyB,GAAG,yBAIb,EAAE,gEAHnB,SAAiB,EACjB,mBAAgC,IAAI,GAAG,EAAE,EACzC,UAAkB,CAAC;IAEnB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IAEzC,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAa,CAAC;IAC3F,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAE7E,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IACrC,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC/C,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACD,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjD,CAAC;QAAC,WAAM,CAAC;YACL,SAAS;QACb,CAAC;QAED,MAAM,SAAS,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAChD,IAAI,CAAC,SAAS;YAAE,SAAS;QAEzB,KAAK,MAAM,GAAG,IAAI,uBAAuB,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;YAC5D,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxD,CAAC;IACL,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,OAAO,oBAAoB,CAAC,CAAC,GAAG,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC;AAC1D,CAAC,CAAA,CAAC;AAEF,eAAe,yBAAyB,CAAC"}
@@ -8,6 +8,10 @@ let json_urls = [];
8
8
  let max_req_queue;
9
9
  /** List of URLs which has been crawled */
10
10
  let crawled_urls = [];
11
+ /** Global map of JS file content hash -> count of files seen with that hash (used by generic-tech stagnation detection) */
12
+ let js_file_hash_counts = new Map();
13
+ /** Total number of JS files whose content hash has been recorded */
14
+ let js_file_total_count = 0;
11
15
  /**
12
16
  * Gets the current scope configuration.
13
17
  * @returns Array of domains in scope
@@ -108,4 +112,31 @@ export const addCrawledUrl = (url) => {
108
112
  export const clearCrawledUrls = () => {
109
113
  crawled_urls = [];
110
114
  };
115
+ /**
116
+ * Records a JS file's content hash, incrementing both its per-hash count and the total count.
117
+ * Used by generic-tech stagnation detection to track how much discovered content is duplicate.
118
+ * @param hash - Content hash (e.g. sha256) of a discovered JS file
119
+ */
120
+ export const recordJsFileHash = (hash) => {
121
+ var _a;
122
+ js_file_hash_counts.set(hash, ((_a = js_file_hash_counts.get(hash)) !== null && _a !== void 0 ? _a : 0) + 1);
123
+ js_file_total_count++;
124
+ };
125
+ /**
126
+ * Gets the current map of JS file content hash -> count.
127
+ * @returns Map of content hash to occurrence count
128
+ */
129
+ export const getJsFileHashCounts = () => js_file_hash_counts;
130
+ /**
131
+ * Gets the total number of JS files whose content hash has been recorded.
132
+ * @returns Total recorded JS file count
133
+ */
134
+ export const getJsFileTotalCount = () => js_file_total_count;
135
+ /**
136
+ * Clears all recorded JS file content hashes and resets the total count.
137
+ */
138
+ export const clearJsFileHashCounts = () => {
139
+ js_file_hash_counts = new Map();
140
+ js_file_total_count = 0;
141
+ };
111
142
  //# sourceMappingURL=globals.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"globals.js","sourceRoot":"","sources":["../../src/lazyLoad/globals.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,IAAI,KAAK,GAAa,EAAE,CAAC;AACzB,qEAAqE;AACrE,IAAI,OAAO,GAAa,EAAE,CAAC;AAC3B,+DAA+D;AAC/D,IAAI,SAAS,GAAa,EAAE,CAAC;AAC7B,oDAAoD;AACpD,IAAI,aAAqB,CAAC;AAC1B,0CAA0C;AAC1C,IAAI,YAAY,GAAa,EAAE,CAAC;AAEhC;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAa,EAAE,CAAC,KAAK,CAAC;AAE9C;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,QAAkB,EAAQ,EAAE;IACjD,KAAK,GAAG,QAAQ,CAAC;AACrB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAQ,EAAE;IAC9C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,GAAa,EAAE,CAAC,OAAO,CAAC;AAEjD;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAS,EAAE;IAClC,OAAO,GAAG,EAAE,CAAC;AACjB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAsB,EAAQ,EAAE;IACzD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACJ,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAED,oBAAoB;IACpB,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AACpC,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAa,EAAE,CAAC,SAAS,CAAC;AAErD;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAS,EAAE;IACpC,SAAS,GAAG,EAAE,CAAC;AACnB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAW,EAAQ,EAAE;IAChD,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,GAAW,EAAE,CAAC,aAAa,CAAC;AAE1D;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAc,EAAQ,EAAE;IACnD,aAAa,GAAG,MAAM,CAAC;AAC3B,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,GAAW,EAAW,EAAE;IACzD,OAAO,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACtC,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAsB,EAAQ,EAAE;IAC1D,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,YAAY,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;IAC9B,CAAC;SAAM,CAAC;QACJ,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACL,CAAC;AACL,CAAC,CAAC;AAEF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAS,EAAE;IACvC,YAAY,GAAG,EAAE,CAAC;AACtB,CAAC,CAAC"}
1
+ {"version":3,"file":"globals.js","sourceRoot":"","sources":["../../src/lazyLoad/globals.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,IAAI,KAAK,GAAa,EAAE,CAAC;AACzB,qEAAqE;AACrE,IAAI,OAAO,GAAa,EAAE,CAAC;AAC3B,+DAA+D;AAC/D,IAAI,SAAS,GAAa,EAAE,CAAC;AAC7B,oDAAoD;AACpD,IAAI,aAAqB,CAAC;AAC1B,0CAA0C;AAC1C,IAAI,YAAY,GAAa,EAAE,CAAC;AAChC,2HAA2H;AAC3H,IAAI,mBAAmB,GAAwB,IAAI,GAAG,EAAE,CAAC;AACzD,oEAAoE;AACpE,IAAI,mBAAmB,GAAG,CAAC,CAAC;AAE5B;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAa,EAAE,CAAC,KAAK,CAAC;AAE9C;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,QAAkB,EAAQ,EAAE;IACjD,KAAK,GAAG,QAAQ,CAAC;AACrB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAQ,EAAE;IAC9C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,GAAa,EAAE,CAAC,OAAO,CAAC;AAEjD;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAS,EAAE;IAClC,OAAO,GAAG,EAAE,CAAC;AACjB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAsB,EAAQ,EAAE;IACzD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACJ,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAED,oBAAoB;IACpB,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AACpC,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAa,EAAE,CAAC,SAAS,CAAC;AAErD;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAS,EAAE;IACpC,SAAS,GAAG,EAAE,CAAC;AACnB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAW,EAAQ,EAAE;IAChD,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,GAAW,EAAE,CAAC,aAAa,CAAC;AAE1D;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAc,EAAQ,EAAE;IACnD,aAAa,GAAG,MAAM,CAAC;AAC3B,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,GAAW,EAAW,EAAE;IACzD,OAAO,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACtC,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAsB,EAAQ,EAAE;IAC1D,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,YAAY,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;IAC9B,CAAC;SAAM,CAAC;QACJ,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACL,CAAC;AACL,CAAC,CAAC;AAEF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAS,EAAE;IACvC,YAAY,GAAG,EAAE,CAAC;AACtB,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAQ,EAAE;;IACnD,mBAAmB,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,MAAA,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,mCAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxE,mBAAmB,EAAE,CAAC;AAC1B,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAwB,EAAE,CAAC,mBAAmB,CAAC;AAElF;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAW,EAAE,CAAC,mBAAmB,CAAC;AAErE;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAS,EAAE;IAC5C,mBAAmB,GAAG,IAAI,GAAG,EAAE,CAAC;IAChC,mBAAmB,GAAG,CAAC,CAAC;AAC5B,CAAC,CAAC"}
@@ -10,13 +10,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  var _a;
11
11
  import chalk from "chalk";
12
12
  import fs from "fs";
13
- import frameworkDetect from "./techDetect/index.js";
14
- import CONFIG from "../globalConfig.js";
13
+ import frameworkDetect, { getLastInterceptedUrls } from "./techDetect/index.js";
15
14
  import _traverse from "@babel/traverse";
16
15
  const traverse = ((_a = _traverse.default) !== null && _a !== void 0 ? _a : _traverse);
17
16
  import { URL } from "url";
18
17
  // Next.js
19
18
  import NextJsCrawler from "./next_js/NextJsCrawler.js";
19
+ import next_serverActionIdScan from "./next_js/next_serverActionIdScan.js";
20
20
  import { next_buildId_RSC } from "./next_js/next_buildId.js";
21
21
  // Nuxt.js
22
22
  import nuxt_getFromPageSource from "./nuxt_js/nuxt_getFromPageSource.js";
@@ -41,8 +41,9 @@ import react_getScriptTags from "./react/react_getScriptTags.js";
41
41
  import react_webpackChunkPaths from "./react/react_webpackChunkPaths.js";
42
42
  import react_sourcemapUrls from "./react/react_sourcemapUrls.js";
43
43
  import react_followImports from "./react/react_followImports.js";
44
- import downloadLoadedJs from "./downloadLoadedJsUtil.js";
45
44
  import { DownloadQueue } from "./downloadQueue.js";
45
+ import generic_crawlPages from "./generic/generic_crawlPages.js";
46
+ import resolveGenericScope from "./generic/generic_resolveScope.js";
46
47
  import path from "path";
47
48
  import { join } from "path";
48
49
  import { extractSourceMaps } from "../sourcemaps/index.js";
@@ -55,6 +56,8 @@ import { progressLog, progressWarn } from "../utility/progressLog.js";
55
56
  import { resolveHostOutputDirectory } from "./outputPath.js";
56
57
  import { withRequestSignal } from "../utility/makeReq.js";
57
58
  import { resolveTargetInputs } from "../utility/targetInputs.js";
59
+ import { accumulateTechnique, createTechniqueRecorder } from "./researchUtils.js";
60
+ import { printMsg, MSG } from "../utility/printMsg.js";
58
61
  /**
59
62
  * Downloads the required JavaScript files for a given URL
60
63
  * @param {string} url The URL to download the JS files from
@@ -67,7 +70,7 @@ import { resolveTargetInputs } from "../utility/targetInputs.js";
67
70
  * @param {boolean} insecure If true, then disable SSL certificate verification
68
71
  * @returns {Promise<void>} A Promise that resolves when the download is complete
69
72
  */
70
- const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subsequentRequestsFlag_1, urlsFile_1, insecure_1, buildId_1, sourcemapDir_1, research_1, researchOutput_1, maxIterations_1, ...args_1) => __awaiter(void 0, [url_1, output_1, strictScope_1, inputScope_1, threads_1, subsequentRequestsFlag_1, urlsFile_1, insecure_1, buildId_1, sourcemapDir_1, research_1, researchOutput_1, maxIterations_1, ...args_1], void 0, function* (url, output, strictScope, inputScope, threads, subsequentRequestsFlag, urlsFile, insecure, buildId, sourcemapDir, research, researchOutput, maxIterations, maxJsSizeMb = 2, hardTimeoutMs = 30 * 60 * 1000, maxPageVisits = 200, includeMethods = [], excludeMethods = [], detectionTimeoutMs = 30 * 1000, cancellationSignal, isBatch = false) {
73
+ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subsequentRequestsFlag_1, urlsFile_1, insecure_1, buildId_1, sourcemapDir_1, research_1, researchOutput_1, maxIterations_1, ...args_1) => __awaiter(void 0, [url_1, output_1, strictScope_1, inputScope_1, threads_1, subsequentRequestsFlag_1, urlsFile_1, insecure_1, buildId_1, sourcemapDir_1, research_1, researchOutput_1, maxIterations_1, ...args_1], void 0, function* (url, output, strictScope, inputScope, threads, subsequentRequestsFlag, urlsFile, insecure, buildId, sourcemapDir, research, researchOutput, maxIterations, maxJsSizeMb = 2, hardTimeoutMs = 30 * 60 * 1000, maxPageVisits = 200, includeMethods = [], excludeMethods = [], detectionTimeoutMs = 30 * 1000, cancellationSignal, isBatch = false, maxRedirects = 20, stringsEnabled = false, stringsMaxIterations = 5, stagnationTimeinMs = 0, stagnationPercentage = 80, stagnationMonitorMs = 60 * 1000, rscParamBruteforceLimit = 20) {
71
74
  const resolvedTargets = resolveTargetInputs(url);
72
75
  // Hoisted so the timeout handler can stop discovery and drain downloads.
73
76
  let activeCrawler = null;
@@ -99,14 +102,14 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
99
102
  if (cancellationSignal === null || cancellationSignal === void 0 ? void 0 : cancellationSignal.aborted)
100
103
  requestCancellation();
101
104
  const work = () => __awaiter(void 0, void 0, void 0, function* () {
102
- console.log(chalk.cyan("[i] Loading 'Lazy Load' module"));
105
+ printMsg(MSG.Header, "[i] Loading 'Lazy Load' module");
103
106
  if (globals.getDisableSandbox()) {
104
- console.error(chalk.yellow("[!] Browser sandbox disabled"));
107
+ printMsg(MSG.Warn, "[!] Browser sandbox disabled");
105
108
  }
106
109
  globals.setInsecure(insecure);
107
110
  if (insecure) {
108
111
  process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
109
- console.error(chalk.yellow("[!] Running in insecure mode. SSL certificate verification disabled"));
112
+ printMsg(MSG.Warn, "[!] Running in insecure mode. SSL certificate verification disabled");
110
113
  }
111
114
  // if cache enabled, check if the cache file exists or not. If no, then create a new one
112
115
  if (!globals.getDisableCache()) {
@@ -117,7 +120,7 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
117
120
  for (const url of resolvedTargets.targets) {
118
121
  if (hardTimeoutReached)
119
122
  break;
120
- console.log(chalk.cyan(`[i] Processing ${url}`));
123
+ printMsg(MSG.Header, `[i] Processing ${url}`);
121
124
  lazyLoadGlobals.clearJsUrls();
122
125
  lazyLoadGlobals.clearJsonUrls();
123
126
  lazyLoadGlobals.clearCrawledUrls();
@@ -149,15 +152,15 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
149
152
  activeDetectionController = null;
150
153
  }
151
154
  if (detectionTimedOut) {
152
- console.error(chalk.yellow(`[!] Framework detection timed out after ${detectionTimeoutMs}ms; treating as not detected`));
155
+ printMsg(MSG.Warn, `[!] Framework detection timed out after ${detectionTimeoutMs}ms; treating as not detected`);
153
156
  }
154
157
  if (hardTimeoutReached)
155
158
  break;
156
159
  globals.setTech(tech ? tech.name : "");
157
160
  if (tech) {
158
161
  if (tech.name === "next") {
159
- console.log(chalk.green("[✓] Next.js detected"));
160
- console.log(chalk.yellow(`Evidence: ${tech.evidence}`));
162
+ printMsg(MSG.Run, "[✓] Next.js detected");
163
+ printMsg(MSG.Warn, `Evidence: ${tech.evidence}`);
161
164
  activeQueue = new DownloadQueue(output, threads, { alreadyBatchTargetRoot: isBatch });
162
165
  const crawler = new NextJsCrawler({
163
166
  url,
@@ -168,6 +171,7 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
168
171
  research,
169
172
  maxIterations,
170
173
  maxPageVisits,
174
+ rscParamBruteforceLimit,
171
175
  onUrlsDiscovered: (urls) => enqueue(activeQueue, urls),
172
176
  includeMethods,
173
177
  excludeMethods,
@@ -187,6 +191,14 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
187
191
  return;
188
192
  activeQueue.printSummary();
189
193
  activeQueue = null;
194
+ if (shouldRunMethod("next_serverActionIdScan", includeMethods, excludeMethods)) {
195
+ const scanDir = resolveHostOutputDirectory(output, new URL(url).host, isBatch);
196
+ const scanResult = yield next_serverActionIdScan(scanDir);
197
+ if (scanResult.allActionIds.length > 0) {
198
+ printMsg(MSG.Run, `[✓] Found ${scanResult.allActionIds.length} Server Action ID(s) referenced in downloaded chunks (disclosure only — not invoked)`);
199
+ fs.writeFileSync(path.join(scanDir, "server_action_ids.json"), JSON.stringify(scanResult, null, 4));
200
+ }
201
+ }
190
202
  if (buildId) {
191
203
  // get the buildId
192
204
  // the directory is the output <output>/<host.replace(":", "_")>/___subsequent_requests
@@ -195,7 +207,7 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
195
207
  if (hardTimeoutReached)
196
208
  return;
197
209
  if (buildId) {
198
- console.log(chalk.cyan("[+] Found buildId: " + buildId));
210
+ printMsg(MSG.Header, "[+] Found buildId: " + buildId);
199
211
  // now, write it to a file
200
212
  fs.writeFileSync(path.join(targetOutputDir, "BUILD_ID"), buildId);
201
213
  }
@@ -204,75 +216,97 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
204
216
  if (research) {
205
217
  // prettify the JSON and write
206
218
  fs.writeFileSync(researchOutput, JSON.stringify(crawler.techniqueEfficiencyMapping, null, 4));
207
- console.log(chalk.green("[✓] Research mode enabled. Technique efficiency written to " + researchOutput));
219
+ printMsg(MSG.Run, "[✓] Research mode enabled. Technique efficiency written to " + researchOutput);
208
220
  }
209
221
  // extract the source maps
210
222
  yield extractSourceMaps(output, join(output, sourcemapDir));
211
223
  }
212
224
  else if (tech.name === "vue") {
213
- console.log(chalk.green("[✓] Vue.js detected"));
214
- console.log(chalk.yellow(`Evidence: ${tech.evidence}`));
225
+ printMsg(MSG.Run, "[✓] Vue.js detected");
226
+ printMsg(MSG.Warn, `Evidence: ${tech.evidence}`);
215
227
  activeQueue = new DownloadQueue(output, threads, { alreadyBatchTargetRoot: isBatch });
216
228
  const queue = activeQueue;
217
229
  const onFilesDiscovered = (files) => enqueue(queue, files);
230
+ const vueResearchMap = {};
231
+ const vueOnTechnique = research ? createTechniqueRecorder(vueResearchMap) : undefined;
218
232
  // run the full discovery pipeline against the entry URL
219
- const { clientSidePaths } = yield vue_discoverJsFiles(url, maxJsSizeMb, onFilesDiscovered, includeMethods, excludeMethods, threads);
233
+ const { clientSidePaths } = yield vue_discoverJsFiles(url, maxJsSizeMb, onFilesDiscovered, includeMethods, excludeMethods, threads, true, true, vueOnTechnique);
220
234
  if (hardTimeoutReached)
221
235
  return;
222
236
  // recurse the same pipeline through every client-side path we found
223
- yield vue_recursiveClientSidePathDownload(clientSidePaths, threads, maxJsSizeMb, onFilesDiscovered, includeMethods, excludeMethods);
237
+ yield vue_recursiveClientSidePathDownload(clientSidePaths, threads, maxJsSizeMb, onFilesDiscovered, includeMethods, excludeMethods, vueOnTechnique);
224
238
  if (hardTimeoutReached)
225
239
  return;
226
240
  yield queue.drain();
227
241
  if (hardTimeoutReached)
228
242
  return;
229
243
  queue.printSummary();
244
+ if (research) {
245
+ fs.writeFileSync(researchOutput, JSON.stringify(vueResearchMap, null, 4));
246
+ printMsg(MSG.Run, "[✓] Research mode enabled. Technique efficiency written to " + researchOutput);
247
+ }
230
248
  // extract the source maps
231
249
  yield extractSourceMaps(output, join(output, sourcemapDir));
232
250
  }
233
251
  else if (tech.name === "nuxt") {
234
- console.log(chalk.green("[✓] Nuxt.js detected"));
235
- console.log(chalk.yellow(`Evidence: ${tech.evidence}`));
252
+ printMsg(MSG.Run, "[✓] Nuxt.js detected");
253
+ printMsg(MSG.Warn, `Evidence: ${tech.evidence}`);
236
254
  const queue = new DownloadQueue(output, threads, { alreadyBatchTargetRoot: isBatch });
237
255
  activeQueue = queue;
256
+ const nuxtResearchMap = {};
238
257
  // find the files from the page source
239
258
  const jsFilesFromPageSource = shouldRunMethod("nuxt_getFromPageSource", includeMethods, excludeMethods)
240
259
  ? yield nuxt_getFromPageSource(url)
241
260
  : [];
242
261
  enqueue(queue, jsFilesFromPageSource);
262
+ if (research)
263
+ accumulateTechnique(nuxtResearchMap, "nuxt_getFromPageSource", jsFilesFromPageSource);
243
264
  const jsFilesFromStringAnalysis = shouldRunMethod("nuxt_stringAnalysisJSFiles", includeMethods, excludeMethods)
244
265
  ? yield nuxt_stringAnalysisJSFiles(url, threads)
245
266
  : [];
246
267
  enqueue(queue, jsFilesFromStringAnalysis);
268
+ if (research)
269
+ accumulateTechnique(nuxtResearchMap, "nuxt_stringAnalysisJSFiles", jsFilesFromStringAnalysis);
247
270
  const firstBatch = [...new Set([...jsFilesFromPageSource, ...jsFilesFromStringAnalysis])];
248
- let jsFilesFromAST = [];
271
+ const jsFilesFromAST = [];
249
272
  if (shouldRunMethod("nuxt_astParse", includeMethods, excludeMethods)) {
250
- console.log(chalk.cyan("[i] Analyzing functions in the files found"));
273
+ printMsg(MSG.Header, "[i] Analyzing functions in the files found");
251
274
  for (const jsFile of firstBatch) {
252
275
  jsFilesFromAST.push(...(yield nuxt_astParse(jsFile)));
253
276
  }
254
277
  }
255
278
  enqueue(queue, jsFilesFromAST);
279
+ if (research)
280
+ accumulateTechnique(nuxtResearchMap, "nuxt_astParse", jsFilesFromAST);
256
281
  enqueue(queue, lazyLoadGlobals.getJsUrls());
257
282
  const buildsManifestFiles = shouldRunMethod("nuxt_getBuildsManifest", includeMethods, excludeMethods)
258
283
  ? yield nuxt_getBuildsManifest(url)
259
284
  : [];
260
285
  enqueue(queue, buildsManifestFiles);
286
+ if (research)
287
+ accumulateTechnique(nuxtResearchMap, "nuxt_getBuildsManifest", buildsManifestFiles);
261
288
  yield queue.drain();
262
289
  if (hardTimeoutReached)
263
290
  return;
264
291
  queue.printSummary();
292
+ if (research) {
293
+ fs.writeFileSync(researchOutput, JSON.stringify(nuxtResearchMap, null, 4));
294
+ printMsg(MSG.Run, "[✓] Research mode enabled. Technique efficiency written to " + researchOutput);
295
+ }
265
296
  }
266
297
  else if (tech.name === "svelte") {
267
- console.log(chalk.green("[✓] Svelte detected"));
268
- console.log(chalk.yellow(`Evidence: ${tech.evidence}`));
298
+ printMsg(MSG.Run, "[✓] Svelte detected");
299
+ printMsg(MSG.Warn, `Evidence: ${tech.evidence}`);
269
300
  const queue = new DownloadQueue(output, threads, { alreadyBatchTargetRoot: isBatch });
270
301
  activeQueue = queue;
302
+ const svelteResearchMap = {};
271
303
  // find the files from the page source
272
304
  const jsFilesFromPageSource = shouldRunMethod("svelte_getFromPageSource", includeMethods, excludeMethods)
273
305
  ? yield svelte_getFromPageSource(url)
274
306
  : [];
275
307
  enqueue(queue, jsFilesFromPageSource);
308
+ if (research)
309
+ accumulateTechnique(svelteResearchMap, "svelte_getFromPageSource", jsFilesFromPageSource);
276
310
  // probe /<appDir>/version.json — SvelteKit serves this for the `updated` store
277
311
  // but never references it from HTML or JS, so it is invisible to all other steps
278
312
  const appDir = (() => {
@@ -292,6 +326,8 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
292
326
  if (versionJsonFiles.length > 0) {
293
327
  enqueue(queue, versionJsonFiles);
294
328
  }
329
+ if (research)
330
+ accumulateTechnique(svelteResearchMap, "svelte_getVersionJson", versionJsonFiles);
295
331
  // analyze the strings now
296
332
  let jsFilesFromStringAnalysis = [];
297
333
  let mapFilesFromStringAnalysis = [];
@@ -303,16 +339,23 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
303
339
  if (mapFilesFromStringAnalysis.length > 0) {
304
340
  enqueue(queue, mapFilesFromStringAnalysis);
305
341
  }
342
+ if (research) {
343
+ accumulateTechnique(svelteResearchMap, "svelte_stringAnalysisJSFiles", jsFilesFromStringAnalysis);
344
+ accumulateTechnique(svelteResearchMap, "svelte_stringAnalysisJSFiles", mapFilesFromStringAnalysis);
345
+ }
306
346
  }
307
347
  // recursively follow ESM static imports (import ... from "./chunk.js")
348
+ // svelte_followImports reuses react_followImports — tracked under react_followImports key
308
349
  const visited = new Set();
309
350
  let toFollow = [...new Set([...jsFilesFromPageSource, ...jsFilesFromStringAnalysis])];
310
351
  while (toFollow.length > 0) {
311
352
  const newFiles = yield react_followImports(toFollow, maxJsSizeMb, url, visited, threads);
312
353
  if (newFiles.length === 0)
313
354
  break;
314
- console.log(chalk.green(`[✓] Discovered ${newFiles.length} more JS file(s) via imports`));
355
+ printMsg(MSG.Run, `[✓] Discovered ${newFiles.length} more JS file(s) via imports`);
315
356
  enqueue(queue, newFiles);
357
+ if (research)
358
+ accumulateTechnique(svelteResearchMap, "react_followImports", newFiles);
316
359
  toFollow = newFiles;
317
360
  }
318
361
  // crawl same-origin HTML pages found via <a href> and <link href>,
@@ -320,6 +363,8 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
320
363
  const jsFilesFromPageCrawl = shouldRunMethod("svelte_recursivePageCrawl", includeMethods, excludeMethods)
321
364
  ? yield svelte_recursivePageCrawl(url, maxJsSizeMb, (files) => enqueue(queue, files))
322
365
  : [];
366
+ if (research)
367
+ accumulateTechnique(svelteResearchMap, "svelte_recursivePageCrawl", jsFilesFromPageCrawl);
323
368
  // Svelte/Astro apps use client-side routing — the home page rarely has
324
369
  // <a href> links in its server-rendered HTML. Scan downloaded JS for
325
370
  // embedded page path strings (e.g. "/admin", "/debug") and visit each
@@ -331,6 +376,8 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
331
376
  if (jsFilesFromPathScan.length > 0) {
332
377
  enqueue(queue, jsFilesFromPathScan);
333
378
  }
379
+ if (research)
380
+ accumulateTechnique(svelteResearchMap, "svelte_discoverPagesFromJs", jsFilesFromPathScan);
334
381
  // run string analysis once more to catch JS files discovered during page crawl
335
382
  if ((jsFilesFromPageCrawl.length > 0 || jsFilesFromPathScan.length > 0) &&
336
383
  shouldRunMethod("svelte_stringAnalysisJSFiles", includeMethods, excludeMethods)) {
@@ -339,23 +386,34 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
339
386
  if (mapFilesFromStringAnalysis2.length > 0) {
340
387
  enqueue(queue, mapFilesFromStringAnalysis2);
341
388
  }
389
+ if (research) {
390
+ accumulateTechnique(svelteResearchMap, "svelte_stringAnalysisJSFiles", jsFilesFromStringAnalysis2);
391
+ accumulateTechnique(svelteResearchMap, "svelte_stringAnalysisJSFiles", mapFilesFromStringAnalysis2);
392
+ }
342
393
  }
343
394
  yield queue.drain();
344
395
  if (hardTimeoutReached)
345
396
  return;
346
397
  queue.printSummary();
398
+ if (research) {
399
+ fs.writeFileSync(researchOutput, JSON.stringify(svelteResearchMap, null, 4));
400
+ printMsg(MSG.Run, "[✓] Research mode enabled. Technique efficiency written to " + researchOutput);
401
+ }
347
402
  yield extractSourceMaps(output, join(output, sourcemapDir));
348
403
  }
349
404
  else if (tech.name === "angular") {
350
- console.log(chalk.green("[✓] Angular detected"));
351
- console.log(chalk.yellow(`Evidence: ${tech.evidence}`));
405
+ printMsg(MSG.Run, "[✓] Angular detected");
406
+ printMsg(MSG.Warn, `Evidence: ${tech.evidence}`);
352
407
  const queue = new DownloadQueue(output, threads, { alreadyBatchTargetRoot: isBatch });
353
408
  activeQueue = queue;
409
+ const angularResearchMap = {};
354
410
  // find the files from the page source
355
411
  const jsFilesFromPageSource = shouldRunMethod("angular_getFromPageSource", includeMethods, excludeMethods)
356
412
  ? yield angular_getFromPageSource(url)
357
413
  : [];
358
414
  enqueue(queue, jsFilesFromPageSource);
415
+ if (research)
416
+ accumulateTechnique(angularResearchMap, "angular_getFromPageSource", jsFilesFromPageSource);
359
417
  // files using the main.js
360
418
  if (shouldRunMethod("angular_getFromMainJs", includeMethods, excludeMethods)) {
361
419
  let mainJsUrl;
@@ -368,10 +426,14 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
368
426
  if (mainJsUrl) {
369
427
  const jsFilesFromMainJs = yield angular_getFromMainJs(mainJsUrl);
370
428
  enqueue(queue, jsFilesFromMainJs);
429
+ if (research)
430
+ accumulateTechnique(angularResearchMap, "angular_getFromMainJs", jsFilesFromMainJs);
371
431
  // recursively follow chunk-to-chunk imports beyond the first hop
372
432
  if (shouldRunMethod("angular_recursiveChunkImports", includeMethods, excludeMethods)) {
373
433
  const transitiveChunks = yield angular_recursiveChunkImports(jsFilesFromMainJs, threads);
374
434
  enqueue(queue, transitiveChunks);
435
+ if (research)
436
+ accumulateTechnique(angularResearchMap, "angular_recursiveChunkImports", transitiveChunks);
375
437
  }
376
438
  }
377
439
  }
@@ -379,16 +441,21 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
379
441
  if (hardTimeoutReached)
380
442
  return;
381
443
  queue.printSummary();
444
+ if (research) {
445
+ fs.writeFileSync(researchOutput, JSON.stringify(angularResearchMap, null, 4));
446
+ printMsg(MSG.Run, "[✓] Research mode enabled. Technique efficiency written to " + researchOutput);
447
+ }
382
448
  }
383
449
  else if (tech.name === "react") {
384
- console.log(chalk.green("[✓] React detected"));
385
- console.log(chalk.yellow(`Evidence: ${tech.evidence}`));
450
+ printMsg(MSG.Run, "[✓] React detected");
451
+ printMsg(MSG.Warn, `Evidence: ${tech.evidence}`);
386
452
  const queue = new DownloadQueue(output, threads, {
387
453
  compactOutput: true,
388
454
  onProgress: (progress) => activeDownloadProgress === null || activeDownloadProgress === void 0 ? void 0 : activeDownloadProgress.update(progress),
389
455
  alreadyBatchTargetRoot: isBatch,
390
456
  });
391
457
  activeQueue = queue;
458
+ const reactResearchMap = {};
392
459
  // Seed: <script src> tags + <link rel="modulepreload"> (Vite vendor chunks)
393
460
  const jsFilesFromPageSource = shouldRunMethod("react_getScriptTags", includeMethods, excludeMethods)
394
461
  ? yield react_getScriptTags(url, maxJsSizeMb, output, isBatch)
@@ -396,6 +463,8 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
396
463
  if (hardTimeoutReached)
397
464
  return;
398
465
  enqueue(queue, jsFilesFromPageSource);
466
+ if (research)
467
+ accumulateTechnique(reactResearchMap, "react_getScriptTags", jsFilesFromPageSource);
399
468
  // webpack-style chunk path builders (CRA / custom webpack configs)
400
469
  const webpackChunkPaths = shouldRunMethod("react_webpackChunkPaths", includeMethods, excludeMethods)
401
470
  ? yield react_webpackChunkPaths(url, maxJsSizeMb, jsFilesFromPageSource, threads)
@@ -406,6 +475,8 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
406
475
  activeDownloadProgress.update(queue.progress);
407
476
  try {
408
477
  enqueue(queue, webpackChunkPaths);
478
+ if (research)
479
+ accumulateTechnique(reactResearchMap, "react_webpackChunkPaths", webpackChunkPaths);
409
480
  // Recursively follow ESM imports and Vite __vite_mapDeps references.
410
481
  // visited starts empty so the seed files are fetched and parsed in the first round.
411
482
  const visited = new Set();
@@ -419,6 +490,8 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
419
490
  break;
420
491
  progressLog(chalk.green(`[✓] Discovered ${newFiles.length} more JS file(s) via imports`));
421
492
  enqueue(queue, newFiles);
493
+ if (research)
494
+ accumulateTechnique(reactResearchMap, "react_followImports", newFiles);
422
495
  toFollow = newFiles;
423
496
  }
424
497
  }
@@ -427,6 +500,8 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
427
500
  shouldRunMethod("react_sourcemapUrls", includeMethods, excludeMethods)) {
428
501
  const sourcemapUrls = yield react_sourcemapUrls([...visited], threads);
429
502
  enqueue(queue, sourcemapUrls);
503
+ if (research)
504
+ accumulateTechnique(reactResearchMap, "react_sourcemapUrls", sourcemapUrls);
430
505
  }
431
506
  yield queue.drain();
432
507
  }
@@ -437,50 +512,38 @@ const lazyLoad = (url_1, output_1, strictScope_1, inputScope_1, threads_1, subse
437
512
  if (hardTimeoutReached)
438
513
  return;
439
514
  queue.printSummary();
515
+ if (research) {
516
+ fs.writeFileSync(researchOutput, JSON.stringify(reactResearchMap, null, 4));
517
+ printMsg(MSG.Run, "[✓] Research mode enabled. Technique efficiency written to " + researchOutput);
518
+ }
440
519
  yield extractSourceMaps(output, join(output, sourcemapDir));
441
520
  }
442
521
  }
443
522
  else {
444
- console.error(chalk.red("[!] Framework not detected :("));
445
- console.log(chalk.magenta(CONFIG.notFoundMessage));
446
- console.log(chalk.yellow("[i] Trying to download loaded JS files"));
447
- const js_urls = yield downloadLoadedJs(url);
523
+ printMsg(MSG.Warn, "[i] Framework not detected — falling back to generic JS extraction");
524
+ globals.setTech("generic");
525
+ // If the caller didn't customize scope (still the "*" default) and isn't
526
+ // using --strict-scope, default the generic crawl's scope to the origin
527
+ // reached after following redirects, rather than crawling the whole web.
528
+ if (!strictScope && inputScope.length === 1 && inputScope[0] === "*") {
529
+ const resolvedScope = yield resolveGenericScope(url, maxRedirects);
530
+ lazyLoadGlobals.setScope(resolvedScope);
531
+ }
532
+ // Downloads JS incrementally as pages are crawled (see generic_crawlPages.ts) —
533
+ // the returned list is only used for the final summary count.
534
+ const genericResearchMap = {};
535
+ const allUrls = yield generic_crawlPages(url, maxJsSizeMb, output, maxPageVisits, threads, research ? genericResearchMap : undefined, stringsEnabled, stringsMaxIterations, getLastInterceptedUrls(), stagnationTimeinMs, stagnationPercentage, stagnationMonitorMs);
448
536
  if (hardTimeoutReached)
449
537
  return;
450
- if (js_urls && js_urls.length > 0) {
451
- console.log(chalk.green(`[✓] Found ${js_urls.length} JS chunks`));
452
- // Second-chance tech detection: scan downloaded URL paths for
453
- // framework signatures that Puppeteer may have missed on timeout
454
- // (e.g. Next.js served at a non-root basePath).
455
- let secondChanceTech = null;
456
- let secondChanceEvidence = "";
457
- for (const u of js_urls) {
458
- if (u.includes("/_next/")) {
459
- secondChanceTech = "next";
460
- secondChanceEvidence = u;
461
- break;
462
- }
463
- if (u.includes("/_nuxt/")) {
464
- secondChanceTech = "nuxt";
465
- secondChanceEvidence = u;
466
- break;
467
- }
468
- if (u.includes("/_app/immutable/")) {
469
- secondChanceTech = "svelte";
470
- secondChanceEvidence = u;
471
- break;
472
- }
473
- }
474
- if (secondChanceTech) {
475
- console.log(chalk.green(`[✓] Detected ${secondChanceTech} from downloaded file paths (evidence: ${secondChanceEvidence})`));
476
- globals.setTech(secondChanceTech);
477
- }
478
- const queue = new DownloadQueue(output, threads, { alreadyBatchTargetRoot: isBatch });
479
- enqueue(queue, js_urls);
480
- yield queue.drain();
481
- if (hardTimeoutReached)
482
- return;
483
- queue.printSummary();
538
+ if (allUrls.length > 0) {
539
+ printMsg(MSG.Run, `[✓] Found ${allUrls.length} JS file(s)`);
540
+ }
541
+ else {
542
+ printMsg(MSG.Warn, "[i] No JS files discovered");
543
+ }
544
+ if (research) {
545
+ fs.writeFileSync(researchOutput, JSON.stringify(genericResearchMap, null, 4));
546
+ printMsg(MSG.Run, "[✓] Research mode enabled. Technique efficiency written to " + researchOutput);
484
547
  }
485
548
  }
486
549
  }