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

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 (440) hide show
  1. package/.claude-sync/sync.sh +1 -1
  2. package/.github/dependabot.yml +50 -0
  3. package/.github/workflows/build-and-prettify.yaml +49 -19
  4. package/.github/workflows/codeql.yml +33 -0
  5. package/.github/workflows/exploit-smoke-test.yaml +160 -0
  6. package/.github/workflows/framework-detection-smoke-test.yaml +135 -0
  7. package/.github/workflows/plumber.yml +20 -0
  8. package/.github/workflows/promote-js-recon.yml +5 -3
  9. package/.github/workflows/publish-js-recon.yml +31 -2
  10. package/.github/workflows/rules-smoke-test.yaml +13 -5
  11. package/.nvmrc +1 -0
  12. package/.plumber.yaml +151 -0
  13. package/CHANGELOG.md +55 -0
  14. package/CONTRIBUTING.md +32 -0
  15. package/Dockerfile +1 -0
  16. package/README.md +3 -2
  17. package/SECURITY.md +1 -1
  18. package/build/analyze/engine/astEngine.js +10 -9
  19. package/build/analyze/engine/astEngine.js.map +1 -1
  20. package/build/analyze/engine/csMastSEngine.js +6 -6
  21. package/build/analyze/engine/csMastSEngine.js.map +1 -1
  22. package/build/analyze/engine/index.js +1 -1
  23. package/build/analyze/engine/index.js.map +1 -1
  24. package/build/analyze/engine/requestEngine.js +6 -6
  25. package/build/analyze/engine/requestEngine.js.map +1 -1
  26. package/build/analyze/helpers/determineCompatibleVersion.js +70 -0
  27. package/build/analyze/helpers/determineCompatibleVersion.js.map +1 -0
  28. package/build/analyze/helpers/engineHelpers/findMemberExpressionAssignment.js +9 -3
  29. package/build/analyze/helpers/engineHelpers/findMemberExpressionAssignment.js.map +1 -1
  30. package/build/analyze/helpers/initRules.js +9 -9
  31. package/build/analyze/helpers/initRules.js.map +1 -1
  32. package/build/analyze/helpers/outputHelper.js +3 -3
  33. package/build/analyze/helpers/outputHelper.js.map +1 -1
  34. package/build/analyze/helpers/schemas.js +1 -0
  35. package/build/analyze/helpers/schemas.js.map +1 -1
  36. package/build/analyze/helpers/validate.js +9 -5
  37. package/build/analyze/helpers/validate.js.map +1 -1
  38. package/build/analyze/index.js +26 -16
  39. package/build/analyze/index.js.map +1 -1
  40. package/build/cliProgram.js +733 -0
  41. package/build/cliProgram.js.map +1 -0
  42. package/build/completion/index.js +247 -382
  43. package/build/completion/index.js.map +1 -1
  44. package/build/completion/introspect.js +17 -0
  45. package/build/completion/introspect.js.map +1 -0
  46. package/build/config/applicationConfig.js +3 -2
  47. package/build/config/applicationConfig.js.map +1 -1
  48. package/build/cs_mast/index.js +18 -17
  49. package/build/cs_mast/index.js.map +1 -1
  50. package/build/endpoints/gen_report/gen_json.js +2 -2
  51. package/build/endpoints/gen_report/gen_json.js.map +1 -1
  52. package/build/endpoints/gen_report/utility/iterate_n_store.js +1 -1
  53. package/build/endpoints/gen_report/utility/iterate_n_store.js.map +1 -1
  54. package/build/endpoints/index.js +12 -12
  55. package/build/endpoints/index.js.map +1 -1
  56. package/build/endpoints/next_js/client_jsFilesHref.js +3 -3
  57. package/build/endpoints/next_js/client_jsFilesHref.js.map +1 -1
  58. package/build/endpoints/next_js/client_jsonParse.js +4 -4
  59. package/build/endpoints/next_js/client_jsonParse.js.map +1 -1
  60. package/build/endpoints/next_js/client_mappedJsonFile.js +6 -6
  61. package/build/endpoints/next_js/client_mappedJsonFile.js.map +1 -1
  62. package/build/endpoints/next_js/client_subsequentRequests.js +5 -5
  63. package/build/endpoints/next_js/client_subsequentRequests.js.map +1 -1
  64. package/build/exploit/angular/cve-2026-68945.js +61 -0
  65. package/build/exploit/angular/cve-2026-68945.js.map +1 -0
  66. package/build/exploit/index.js +60 -0
  67. package/build/exploit/index.js.map +1 -0
  68. package/build/exploit/next/cve-2025-29927.js +65 -0
  69. package/build/exploit/next/cve-2025-29927.js.map +1 -0
  70. package/build/exploit/next/cve-2026-64645.js +51 -0
  71. package/build/exploit/next/cve-2026-64645.js.map +1 -0
  72. package/build/exploit/nuxt/cve-2026-71315.js +47 -0
  73. package/build/exploit/nuxt/cve-2026-71315.js.map +1 -0
  74. package/build/exploit/nuxt/cve-2026-71320.js +114 -0
  75. package/build/exploit/nuxt/cve-2026-71320.js.map +1 -0
  76. package/build/exploit/react/cve-2025-55182.js +116 -0
  77. package/build/exploit/react/cve-2025-55182.js.map +1 -0
  78. package/build/exploit/registry/cveRegistry.js +115 -0
  79. package/build/exploit/registry/cveRegistry.js.map +1 -0
  80. package/build/exploit/types.js +2 -0
  81. package/build/exploit/types.js.map +1 -0
  82. package/build/exploit/utility/compareResponses.js +29 -0
  83. package/build/exploit/utility/compareResponses.js.map +1 -0
  84. package/build/exploit/utility/outputHelper.js +22 -0
  85. package/build/exploit/utility/outputHelper.js.map +1 -0
  86. package/build/exploit/utility/rawRequest.js +56 -0
  87. package/build/exploit/utility/rawRequest.js.map +1 -0
  88. package/build/exploit/utility/sandboxRce.js +49 -0
  89. package/build/exploit/utility/sandboxRce.js.map +1 -0
  90. package/build/exploit/utility/toEngineOutput.js +28 -0
  91. package/build/exploit/utility/toEngineOutput.js.map +1 -0
  92. package/build/exploit/utility/wsClient.js +78 -0
  93. package/build/exploit/utility/wsClient.js.map +1 -0
  94. package/build/exploit/vite/cve-2025-30208.js +44 -0
  95. package/build/exploit/vite/cve-2025-30208.js.map +1 -0
  96. package/build/exploit/vite/cve-2026-39363.js +60 -0
  97. package/build/exploit/vite/cve-2026-39363.js.map +1 -0
  98. package/build/fingerprint/index.js +3 -2
  99. package/build/fingerprint/index.js.map +1 -1
  100. package/build/globalConfig.js +2 -2
  101. package/build/globalConfig.js.map +1 -1
  102. package/build/index.js +5 -596
  103. package/build/index.js.map +1 -1
  104. package/build/lazyLoad/angular/angular_getFromPageSource.js +3 -3
  105. package/build/lazyLoad/angular/angular_getFromPageSource.js.map +1 -1
  106. package/build/lazyLoad/downloadFilesUtil.js +14 -11
  107. package/build/lazyLoad/downloadFilesUtil.js.map +1 -1
  108. package/build/lazyLoad/downloadQueue.js +9 -1
  109. package/build/lazyLoad/downloadQueue.js.map +1 -1
  110. package/build/lazyLoad/downloadResponse.js +1 -0
  111. package/build/lazyLoad/downloadResponse.js.map +1 -1
  112. package/build/lazyLoad/generic/generic_crawlPages.js +186 -0
  113. package/build/lazyLoad/generic/generic_crawlPages.js.map +1 -0
  114. package/build/lazyLoad/generic/generic_downloadFiles.js +81 -0
  115. package/build/lazyLoad/generic/generic_downloadFiles.js.map +1 -0
  116. package/build/lazyLoad/generic/generic_extractLinks.js +79 -0
  117. package/build/lazyLoad/generic/generic_extractLinks.js.map +1 -0
  118. package/build/lazyLoad/generic/generic_getScriptTags.js +152 -0
  119. package/build/lazyLoad/generic/generic_getScriptTags.js.map +1 -0
  120. package/build/lazyLoad/generic/generic_importMapDiscovery.js +87 -0
  121. package/build/lazyLoad/generic/generic_importMapDiscovery.js.map +1 -0
  122. package/build/lazyLoad/generic/generic_resolveScope.js +66 -0
  123. package/build/lazyLoad/generic/generic_resolveScope.js.map +1 -0
  124. package/build/lazyLoad/generic/generic_scanAttributesForJs.js +122 -0
  125. package/build/lazyLoad/generic/generic_scanAttributesForJs.js.map +1 -0
  126. package/build/lazyLoad/generic/generic_stringsDiscovery.js +103 -0
  127. package/build/lazyLoad/generic/generic_stringsDiscovery.js.map +1 -0
  128. package/build/lazyLoad/generic/generic_webpackChunkPaths.js +56 -0
  129. package/build/lazyLoad/generic/generic_webpackChunkPaths.js.map +1 -0
  130. package/build/lazyLoad/globals.js +31 -0
  131. package/build/lazyLoad/globals.js.map +1 -1
  132. package/build/lazyLoad/index.js +172 -75
  133. package/build/lazyLoad/index.js.map +1 -1
  134. package/build/lazyLoad/methodFilter.js +9 -1
  135. package/build/lazyLoad/methodFilter.js.map +1 -1
  136. package/build/lazyLoad/next_js/NextJsCrawler.js +98 -14
  137. package/build/lazyLoad/next_js/NextJsCrawler.js.map +1 -1
  138. package/build/lazyLoad/next_js/next_GetJSScript.js +3 -3
  139. package/build/lazyLoad/next_js/next_GetJSScript.js.map +1 -1
  140. package/build/lazyLoad/next_js/next_GetLazyResourcesBuildManifestJs.js +4 -4
  141. package/build/lazyLoad/next_js/next_GetLazyResourcesBuildManifestJs.js.map +1 -1
  142. package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js +17 -11
  143. package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js.map +1 -1
  144. package/build/lazyLoad/next_js/next_SubsequentRequests.js +7 -6
  145. package/build/lazyLoad/next_js/next_SubsequentRequests.js.map +1 -1
  146. package/build/lazyLoad/next_js/next_bruteForceJsFiles.js +1 -1
  147. package/build/lazyLoad/next_js/next_bruteForceJsFiles.js.map +1 -1
  148. package/build/lazyLoad/next_js/next_buildId.js +2 -2
  149. package/build/lazyLoad/next_js/next_buildId.js.map +1 -1
  150. package/build/lazyLoad/next_js/next_getClientSidePaths.js +2 -2
  151. package/build/lazyLoad/next_js/next_getClientSidePaths.js.map +1 -1
  152. package/build/lazyLoad/next_js/next_parseLayoutJs.js +6 -6
  153. package/build/lazyLoad/next_js/next_parseLayoutJs.js.map +1 -1
  154. package/build/lazyLoad/next_js/next_promiseResolve.js +1 -1
  155. package/build/lazyLoad/next_js/next_promiseResolve.js.map +1 -1
  156. package/build/lazyLoad/next_js/next_routerStateForge.js +407 -0
  157. package/build/lazyLoad/next_js/next_routerStateForge.js.map +1 -0
  158. package/build/lazyLoad/next_js/next_scriptTagsSubsequentRequests.js +1 -1
  159. package/build/lazyLoad/next_js/next_scriptTagsSubsequentRequests.js.map +1 -1
  160. package/build/lazyLoad/next_js/next_serverActionIdScan.js +77 -0
  161. package/build/lazyLoad/next_js/next_serverActionIdScan.js.map +1 -0
  162. package/build/lazyLoad/nuxt_js/nuxt_astParse.js +15 -13
  163. package/build/lazyLoad/nuxt_js/nuxt_astParse.js.map +1 -1
  164. package/build/lazyLoad/nuxt_js/nuxt_getBuildsManifest.js +2 -2
  165. package/build/lazyLoad/nuxt_js/nuxt_getBuildsManifest.js.map +1 -1
  166. package/build/lazyLoad/nuxt_js/nuxt_getFromPageSource.js +3 -3
  167. package/build/lazyLoad/nuxt_js/nuxt_getFromPageSource.js.map +1 -1
  168. package/build/lazyLoad/nuxt_js/nuxt_stringAnalysisJSFiles.js +29 -5
  169. package/build/lazyLoad/nuxt_js/nuxt_stringAnalysisJSFiles.js.map +1 -1
  170. package/build/lazyLoad/react/react_sourcemapUrls.js +7 -28
  171. package/build/lazyLoad/react/react_sourcemapUrls.js.map +1 -1
  172. package/build/lazyLoad/react/react_webpackChunkPaths.js +10 -202
  173. package/build/lazyLoad/react/react_webpackChunkPaths.js.map +1 -1
  174. package/build/lazyLoad/researchUtils.js +15 -0
  175. package/build/lazyLoad/researchUtils.js.map +1 -0
  176. package/build/lazyLoad/shared/webpackChunkParsers.js +218 -0
  177. package/build/lazyLoad/shared/webpackChunkParsers.js.map +1 -0
  178. package/build/lazyLoad/sourcemap.js +120 -0
  179. package/build/lazyLoad/sourcemap.js.map +1 -1
  180. package/build/lazyLoad/stagnation/stagnationMonitor.js +63 -0
  181. package/build/lazyLoad/stagnation/stagnationMonitor.js.map +1 -0
  182. package/build/lazyLoad/svelte/svelte_discoverPagesFromJs.js +1 -0
  183. package/build/lazyLoad/svelte/svelte_discoverPagesFromJs.js.map +1 -1
  184. package/build/lazyLoad/svelte/svelte_getFromPageSource.js +5 -5
  185. package/build/lazyLoad/svelte/svelte_getFromPageSource.js.map +1 -1
  186. package/build/lazyLoad/svelte/svelte_getVersionJson.js +2 -2
  187. package/build/lazyLoad/svelte/svelte_getVersionJson.js.map +1 -1
  188. package/build/lazyLoad/svelte/svelte_recursivePageCrawl.js +6 -6
  189. package/build/lazyLoad/svelte/svelte_recursivePageCrawl.js.map +1 -1
  190. package/build/lazyLoad/svelte/svelte_stringAnalysisJSFiles.js +15 -6
  191. package/build/lazyLoad/svelte/svelte_stringAnalysisJSFiles.js.map +1 -1
  192. package/build/lazyLoad/techDetect/checkAngularJS.js +1 -1
  193. package/build/lazyLoad/techDetect/checkAngularJS.js.map +1 -1
  194. package/build/lazyLoad/techDetect/checkNuxtJS.js +3 -3
  195. package/build/lazyLoad/techDetect/checkNuxtJS.js.map +1 -1
  196. package/build/lazyLoad/techDetect/checkSvelte.js +0 -1
  197. package/build/lazyLoad/techDetect/checkSvelte.js.map +1 -1
  198. package/build/lazyLoad/techDetect/checkVueJS.js +6 -6
  199. package/build/lazyLoad/techDetect/checkVueJS.js.map +1 -1
  200. package/build/lazyLoad/techDetect/index.js +17 -1
  201. package/build/lazyLoad/techDetect/index.js.map +1 -1
  202. package/build/lazyLoad/vue/vue_SingleJsFileOnHome.js +2 -2
  203. package/build/lazyLoad/vue/vue_SingleJsFileOnHome.js.map +1 -1
  204. package/build/lazyLoad/vue/vue_discoverJsFiles.js +13 -11
  205. package/build/lazyLoad/vue/vue_discoverJsFiles.js.map +1 -1
  206. package/build/lazyLoad/vue/vue_getClientSidePaths.js +1 -1
  207. package/build/lazyLoad/vue/vue_getClientSidePaths.js.map +1 -1
  208. package/build/lazyLoad/vue/vue_pageSrc.js +1 -1
  209. package/build/lazyLoad/vue/vue_pageSrc.js.map +1 -1
  210. package/build/lazyLoad/vue/vue_reconstructSourceMaps.js +12 -3
  211. package/build/lazyLoad/vue/vue_reconstructSourceMaps.js.map +1 -1
  212. package/build/lazyLoad/vue/vue_recursiveClientSidePathDownload.js +2 -2
  213. package/build/lazyLoad/vue/vue_recursiveClientSidePathDownload.js.map +1 -1
  214. package/build/lazyLoad/vue/vue_severalJsFilesHome.js +3 -3
  215. package/build/lazyLoad/vue/vue_severalJsFilesHome.js.map +1 -1
  216. package/build/load/index.js +28 -38
  217. package/build/load/index.js.map +1 -1
  218. package/build/map/angular_js/getAngularConnections.js +6 -6
  219. package/build/map/angular_js/getAngularConnections.js.map +1 -1
  220. package/build/map/graphql/resolveGraphql.js +6 -6
  221. package/build/map/graphql/resolveGraphql.js.map +1 -1
  222. package/build/map/index.js +17 -17
  223. package/build/map/index.js.map +1 -1
  224. package/build/map/interactive-mode/commandHandler.js +278 -0
  225. package/build/map/interactive-mode/commandHandler.js.map +1 -0
  226. package/build/map/interactive-mode/commandHelpers.js +189 -0
  227. package/build/map/interactive-mode/commandHelpers.js.map +1 -0
  228. package/build/map/interactive-mode/esqueryGen.js.map +1 -0
  229. package/build/map/interactive-mode/helpMenu.js +11 -0
  230. package/build/map/interactive-mode/helpMenu.js.map +1 -0
  231. package/build/map/interactive-mode/inputPatch.js.map +1 -0
  232. package/build/map/interactive-mode/interactive.js +71 -0
  233. package/build/map/interactive-mode/interactive.js.map +1 -0
  234. package/build/map/interactive-mode/keybindings.js.map +1 -0
  235. package/build/map/interactive-mode/printer.js.map +1 -0
  236. package/build/map/interactive-mode/ui.js.map +1 -0
  237. package/build/map/next_js/getAxiosInstances.js +5 -5
  238. package/build/map/next_js/getAxiosInstances.js.map +1 -1
  239. package/build/map/next_js/getExports.js +4 -4
  240. package/build/map/next_js/getExports.js.map +1 -1
  241. package/build/map/next_js/getFetchInstances.js +10 -10
  242. package/build/map/next_js/getFetchInstances.js.map +1 -1
  243. package/build/map/next_js/getTurbopackConnections.js +8 -8
  244. package/build/map/next_js/getTurbopackConnections.js.map +1 -1
  245. package/build/map/next_js/getWebpackConnections.js +27 -16
  246. package/build/map/next_js/getWebpackConnections.js.map +1 -1
  247. package/build/map/next_js/interactive.js +3 -65
  248. package/build/map/next_js/interactive.js.map +1 -1
  249. package/build/map/next_js/interactive_helpers/commandHandler.js +38 -290
  250. package/build/map/next_js/interactive_helpers/commandHandler.js.map +1 -1
  251. package/build/map/next_js/interactive_helpers/commandHelpers.js +0 -184
  252. package/build/map/next_js/interactive_helpers/commandHelpers.js.map +1 -1
  253. package/build/map/next_js/interactive_helpers/helpMenu.js +2 -10
  254. package/build/map/next_js/interactive_helpers/helpMenu.js.map +1 -1
  255. package/build/map/next_js/resolveAxios.js +6 -6
  256. package/build/map/next_js/resolveAxios.js.map +1 -1
  257. package/build/map/next_js/resolveAxiosHelpers/findAxiosClients.js +4 -4
  258. package/build/map/next_js/resolveAxiosHelpers/findAxiosClients.js.map +1 -1
  259. package/build/map/next_js/resolveAxiosHelpers/findAxiosInstance.js +2 -2
  260. package/build/map/next_js/resolveAxiosHelpers/findAxiosInstance.js.map +1 -1
  261. package/build/map/next_js/resolveAxiosHelpers/findCrossChunkParams.js +5 -5
  262. package/build/map/next_js/resolveAxiosHelpers/findCrossChunkParams.js.map +1 -1
  263. package/build/map/next_js/resolveAxiosHelpers/handleAxiosCreate.js +10 -10
  264. package/build/map/next_js/resolveAxiosHelpers/handleAxiosCreate.js.map +1 -1
  265. package/build/map/next_js/resolveAxiosHelpers/handleZDotCreate.js +13 -9
  266. package/build/map/next_js/resolveAxiosHelpers/handleZDotCreate.js.map +1 -1
  267. package/build/map/next_js/resolveAxiosHelpers/processAxiosCall.js +12 -8
  268. package/build/map/next_js/resolveAxiosHelpers/processAxiosCall.js.map +1 -1
  269. package/build/map/next_js/resolveAxiosHelpers/processDirectAxiosCall.js +12 -8
  270. package/build/map/next_js/resolveAxiosHelpers/processDirectAxiosCall.js.map +1 -1
  271. package/build/map/next_js/resolveAxiosHelpers/processExportedEndpoints.js +11 -11
  272. package/build/map/next_js/resolveAxiosHelpers/processExportedEndpoints.js.map +1 -1
  273. package/build/map/next_js/resolveAxiosHelpers/traceAxiosInstanceExports.js +16 -16
  274. package/build/map/next_js/resolveAxiosHelpers/traceAxiosInstanceExports.js.map +1 -1
  275. package/build/map/next_js/resolveFetch.js +23 -23
  276. package/build/map/next_js/resolveFetch.js.map +1 -1
  277. package/build/map/next_js/resolveNewRequest.js +10 -10
  278. package/build/map/next_js/resolveNewRequest.js.map +1 -1
  279. package/build/map/next_js/resolveServerActions.js +4 -4
  280. package/build/map/next_js/resolveServerActions.js.map +1 -1
  281. package/build/map/next_js/utils.js +8 -2
  282. package/build/map/next_js/utils.js.map +1 -1
  283. package/build/map/react_js/getReactConnections.js +21 -14
  284. package/build/map/react_js/getReactConnections.js.map +1 -1
  285. package/build/map/svelte_js/interactive.js +3 -54
  286. package/build/map/svelte_js/interactive.js.map +1 -1
  287. package/build/map/vue_js/getViteConnections.js +23 -16
  288. package/build/map/vue_js/getViteConnections.js.map +1 -1
  289. package/build/map/vue_js/interactive.js +3 -63
  290. package/build/map/vue_js/interactive.js.map +1 -1
  291. package/build/map/vue_js/interactive_helpers/commandHandler.js +34 -283
  292. package/build/map/vue_js/interactive_helpers/commandHandler.js.map +1 -1
  293. package/build/map/vue_js/interactive_helpers/helpMenu.js +2 -10
  294. package/build/map/vue_js/interactive_helpers/helpMenu.js.map +1 -1
  295. package/build/map/vue_js/taint_utils.js +1 -1
  296. package/build/map/vue_js/taint_utils.js.map +1 -1
  297. package/build/map/vue_js/vue_resolveFetch.js +12 -12
  298. package/build/map/vue_js/vue_resolveFetch.js.map +1 -1
  299. package/build/map/vue_js/vue_resolveHttpClient.js +18 -18
  300. package/build/map/vue_js/vue_resolveHttpClient.js.map +1 -1
  301. package/build/map/vue_js/vue_resolveXhr.js +11 -11
  302. package/build/map/vue_js/vue_resolveXhr.js.map +1 -1
  303. package/build/mcp/chatOneShot.js +7 -7
  304. package/build/mcp/chatOneShot.js.map +1 -1
  305. package/build/mcp/claudeCodeCreds.js +5 -5
  306. package/build/mcp/claudeCodeCreds.js.map +1 -1
  307. package/build/mcp/cli.js +36 -35
  308. package/build/mcp/cli.js.map +1 -1
  309. package/build/mcp/config.js +4 -4
  310. package/build/mcp/config.js.map +1 -1
  311. package/build/mcp/index.js +7 -7
  312. package/build/mcp/index.js.map +1 -1
  313. package/build/mcp/mcpServer.js +4 -3
  314. package/build/mcp/mcpServer.js.map +1 -1
  315. package/build/mcp/skills.js +1 -0
  316. package/build/mcp/skills.js.map +1 -1
  317. package/build/mcp/tools.js +6 -5
  318. package/build/mcp/tools.js.map +1 -1
  319. package/build/proxy/detectBlockedResponse.js +2 -0
  320. package/build/proxy/detectBlockedResponse.js.map +1 -1
  321. package/build/proxy/index.js +3 -3
  322. package/build/proxy/index.js.map +1 -1
  323. package/build/refactor/index.js +83 -79
  324. package/build/refactor/index.js.map +1 -1
  325. package/build/refactor/next/index.js +69 -26
  326. package/build/refactor/next/index.js.map +1 -1
  327. package/build/refactor/next/transform.js +11 -4
  328. package/build/refactor/next/transform.js.map +1 -1
  329. package/build/refactor/next/validator.js +7 -7
  330. package/build/refactor/next/validator.js.map +1 -1
  331. package/build/refactor/react/index.js +13 -13
  332. package/build/refactor/react/index.js.map +1 -1
  333. package/build/refactor/react/validator.js +7 -7
  334. package/build/refactor/react/validator.js.map +1 -1
  335. package/build/refactor/react-vite/index.js +3 -3
  336. package/build/refactor/react-vite/index.js.map +1 -1
  337. package/build/refactor/remote/hf-client.js +1 -0
  338. package/build/refactor/remote/hf-client.js.map +1 -1
  339. package/build/refactor/remote/version-detect.js +12 -12
  340. package/build/refactor/remote/version-detect.js.map +1 -1
  341. package/build/refactor/vue/index.js +6 -6
  342. package/build/refactor/vue/index.js.map +1 -1
  343. package/build/refactor/vue/vite.js +6 -6
  344. package/build/refactor/vue/vite.js.map +1 -1
  345. package/build/report/index.js +30 -8
  346. package/build/report/index.js.map +1 -1
  347. package/build/report/swaggerJacker.js +63 -0
  348. package/build/report/swaggerJacker.js.map +1 -0
  349. package/build/report/utility/dataTables/genDataTablesPage.js +2 -1
  350. package/build/report/utility/dataTables/genDataTablesPage.js.map +1 -1
  351. package/build/report/utility/genHtml.js +316 -25
  352. package/build/report/utility/genHtml.js.map +1 -1
  353. package/build/report/utility/markdownGen/addAnalyze.js +2 -1
  354. package/build/report/utility/markdownGen/addAnalyze.js.map +1 -1
  355. package/build/report/utility/populateDb/populateAnalysisFindings.js +2 -2
  356. package/build/report/utility/populateDb/populateAnalysisFindings.js.map +1 -1
  357. package/build/report/utility/populateDb/populateEndpoints.js +3 -3
  358. package/build/report/utility/populateDb/populateEndpoints.js.map +1 -1
  359. package/build/report/utility/populateDb/populateMappedJson.js +2 -2
  360. package/build/report/utility/populateDb/populateMappedJson.js.map +1 -1
  361. package/build/report/utility/populateDb/populateMappedOpenapi.js +3 -3
  362. package/build/report/utility/populateDb/populateMappedOpenapi.js.map +1 -1
  363. package/build/report/utility/severityColors.js +35 -0
  364. package/build/report/utility/severityColors.js.map +1 -0
  365. package/build/run/bundler-detect.js +45 -9
  366. package/build/run/bundler-detect.js.map +1 -1
  367. package/build/run/dashboard/dashboardHtml.js +150 -0
  368. package/build/run/dashboard/dashboardHtml.js.map +1 -0
  369. package/build/run/dashboard/fsBrowser.js +43 -0
  370. package/build/run/dashboard/fsBrowser.js.map +1 -0
  371. package/build/run/dashboard/server.js +123 -0
  372. package/build/run/dashboard/server.js.map +1 -0
  373. package/build/run/dashboard/state.js +97 -0
  374. package/build/run/dashboard/state.js.map +1 -0
  375. package/build/run/index.js +177 -110
  376. package/build/run/index.js.map +1 -1
  377. package/build/run/interruptHandler.js +18 -0
  378. package/build/run/interruptHandler.js.map +1 -1
  379. package/build/sourcemaps/index.js +7 -6
  380. package/build/sourcemaps/index.js.map +1 -1
  381. package/build/strings/index.js +27 -24
  382. package/build/strings/index.js.map +1 -1
  383. package/build/strings/openapi.js +4 -4
  384. package/build/strings/openapi.js.map +1 -1
  385. package/build/strings/permutate.js +4 -4
  386. package/build/strings/permutate.js.map +1 -1
  387. package/build/strings/secrets.js +1 -0
  388. package/build/strings/secrets.js.map +1 -1
  389. package/build/strings/trufflehog.js +66 -19
  390. package/build/strings/trufflehog.js.map +1 -1
  391. package/build/strings/trufflehogConfig.js +36 -0
  392. package/build/strings/trufflehogConfig.js.map +1 -0
  393. package/build/strings/trufflehogDownload.js +115 -0
  394. package/build/strings/trufflehogDownload.js.map +1 -0
  395. package/build/utility/ai.js +33 -4
  396. package/build/utility/ai.js.map +1 -1
  397. package/build/utility/banner.js +4 -3
  398. package/build/utility/banner.js.map +1 -1
  399. package/build/utility/cacheDb.js +78 -0
  400. package/build/utility/cacheDb.js.map +1 -0
  401. package/build/utility/configureSandbox.js +2 -2
  402. package/build/utility/configureSandbox.js.map +1 -1
  403. package/build/utility/customHeaders.js +30 -0
  404. package/build/utility/customHeaders.js.map +1 -0
  405. package/build/utility/globals.js +37 -12
  406. package/build/utility/globals.js.map +1 -1
  407. package/build/utility/heap.js +2 -1
  408. package/build/utility/heap.js.map +1 -1
  409. package/build/utility/makeReq.js +38 -87
  410. package/build/utility/makeReq.js.map +1 -1
  411. package/build/utility/openapiGenerator.js +2 -2
  412. package/build/utility/openapiGenerator.js.map +1 -1
  413. package/build/utility/printMsg.js +53 -0
  414. package/build/utility/printMsg.js.map +1 -0
  415. package/build/utility/progressLog.js +4 -3
  416. package/build/utility/progressLog.js.map +1 -1
  417. package/build/utility/resolvePath.js +2 -1
  418. package/build/utility/resolvePath.js.map +1 -1
  419. package/build/utility/ruleVersionMap.js +73 -0
  420. package/build/utility/ruleVersionMap.js.map +1 -0
  421. package/config.dist.yaml +3 -3
  422. package/contributing/testing.md +106 -0
  423. package/eslint.config.js +24 -0
  424. package/package.json +22 -6
  425. package/scripts/exploit-smoke-test.js +82 -0
  426. package/scripts/framework-detect-smoke-test.js +64 -0
  427. package/scripts/postinstall-completion.mjs +40 -0
  428. package/scripts/smoke-test.js +12 -0
  429. package/build/lazyLoad/downloadLoadedJsUtil.js +0 -98
  430. package/build/lazyLoad/downloadLoadedJsUtil.js.map +0 -1
  431. package/build/map/next_js/interactive_helpers/esqueryGen.js.map +0 -1
  432. package/build/map/next_js/interactive_helpers/inputPatch.js.map +0 -1
  433. package/build/map/next_js/interactive_helpers/keybindings.js.map +0 -1
  434. package/build/map/next_js/interactive_helpers/printer.js.map +0 -1
  435. package/build/map/next_js/interactive_helpers/ui.js.map +0 -1
  436. /package/build/map/{next_js/interactive_helpers → interactive-mode}/esqueryGen.js +0 -0
  437. /package/build/map/{next_js/interactive_helpers → interactive-mode}/inputPatch.js +0 -0
  438. /package/build/map/{next_js/interactive_helpers → interactive-mode}/keybindings.js +0 -0
  439. /package/build/map/{next_js/interactive_helpers → interactive-mode}/printer.js +0 -0
  440. /package/build/map/{next_js/interactive_helpers → interactive-mode}/ui.js +0 -0
@@ -7,6 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
+ import { printMsg, MSG } from "./printMsg.js";
10
11
  /**
11
12
  * Computes a progress bar width that fits within the current terminal.
12
13
  * @param formatOverhead Total visible characters in the format string excluding the bar itself
@@ -86,7 +87,7 @@ export const progressLog = (message) => {
86
87
  activeBarLogger.log(message + "\n");
87
88
  }
88
89
  else {
89
- console.log(message);
90
+ printMsg(MSG.Plain, message);
90
91
  }
91
92
  };
92
93
  export const progressError = (message) => {
@@ -95,7 +96,7 @@ export const progressError = (message) => {
95
96
  activeBarLogger.log(message + "\n");
96
97
  }
97
98
  else {
98
- console.error(message);
99
+ printMsg(MSG.Err, message);
99
100
  }
100
101
  };
101
102
  export const progressWarn = (message) => {
@@ -104,7 +105,7 @@ export const progressWarn = (message) => {
104
105
  activeBarLogger.log(message + "\n");
105
106
  }
106
107
  else {
107
- console.warn(message);
108
+ printMsg(MSG.Warn, message);
108
109
  }
109
110
  };
110
111
  //# sourceMappingURL=progressLog.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"progressLog.js","sourceRoot":"","sources":["../../src/utility/progressLog.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"progressLog.js","sourceRoot":"","sources":["../../src/utility/progressLog.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { printMsg, MSG } from "./printMsg.js";
1
2
  /**
2
3
  * Resolves a relative path with a given base URL.
3
4
  *
@@ -34,7 +35,7 @@ const resolvePath = (url, path) => {
34
35
  return resolvedUrl.href;
35
36
  }
36
37
  catch (e) {
37
- console.error(`Error resolving path "${path}" with base URL "${url}": ${e.message}`);
38
+ printMsg(MSG.Err, `Error resolving path "${path}" with base URL "${url}": ${e.message}`);
38
39
  // Rethrowing the error to signal failure to the caller.
39
40
  // Alternative error handling (e.g., returning null) can be implemented if required.
40
41
  throw e;
@@ -1 +1 @@
1
- {"version":3,"file":"resolvePath.js","sourceRoot":"","sources":["../../src/utility/resolvePath.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,GAAG,CAAC,GAAW,EAAE,IAAY,EAAE,EAAE;IAC9C,IAAI,CAAC;QACD,gEAAgE;QAChE,yEAAyE;QACzE,oEAAoE;QACpE,+CAA+C;QAC/C,mDAAmD;QACnD,qFAAqF;QACrF,sDAAsD;QACtD,gGAAgG;QAChG,2DAA2D;QAC3D,4FAA4F;QAC5F,yFAAyF;QACzF,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACvC,OAAO,WAAW,CAAC,IAAI,CAAC;IAC5B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,yBAAyB,IAAI,oBAAoB,GAAG,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACrF,wDAAwD;QACxD,oFAAoF;QACpF,MAAM,CAAC,CAAC;IACZ,CAAC;AACL,CAAC,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"resolvePath.js","sourceRoot":"","sources":["../../src/utility/resolvePath.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAE9C;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,GAAG,CAAC,GAAW,EAAE,IAAY,EAAE,EAAE;IAC9C,IAAI,CAAC;QACD,gEAAgE;QAChE,yEAAyE;QACzE,oEAAoE;QACpE,+CAA+C;QAC/C,mDAAmD;QACnD,qFAAqF;QACrF,sDAAsD;QACtD,gGAAgG;QAChG,2DAA2D;QAC3D,4FAA4F;QAC5F,yFAAyF;QACzF,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACvC,OAAO,WAAW,CAAC,IAAI,CAAC;IAC5B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,yBAAyB,IAAI,oBAAoB,GAAG,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACzF,wDAAwD;QACxD,oFAAoF;QACpF,MAAM,CAAC,CAAC;IACZ,CAAC;AACL,CAAC,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Maps a rule attribute (tech value, rule type, or step sub-feature) to the js-recon
3
+ * version that introduced it, and, if it has since been retired, the version it was
4
+ * removed in. Only attributes added after `js_recon_version` itself became mandatory
5
+ * (1.3.1-alpha.3) need an entry here — anything from the original schema is implicitly
6
+ * satisfied by any declared version.
7
+ *
8
+ * When `schemas.ts` or an engine gains/retires a capability, add/update the matching
9
+ * entry here (see `src/analyze/CLAUDE.md`).
10
+ */
11
+ export const RULE_VERSION_MAP = {
12
+ "tech.vue": { min: "1.3.1-alpha.3" },
13
+ "tech.all": { min: "1.3.1-alpha.3" },
14
+ "tech.react": { min: "1.3.1-alpha.4" },
15
+ "tech.svelte": { min: "1.3.1-alpha.4" },
16
+ "tech.angular": { min: "1.4.1-alpha.4" },
17
+ "type.cs-mast-s": { min: "1.4.1-alpha.5" },
18
+ "step.esquery.inScopeOf": { min: "1.3.1-alpha.1" },
19
+ "step.esquery.taintFrom": { min: "1.3.1-alpha.2" },
20
+ "step.regexMatch": { min: "1.3.1-alpha.4" },
21
+ "step.csMastS": { min: "1.4.1-alpha.5" },
22
+ };
23
+ const parseVersion = (version) => {
24
+ const clean = version.split("-")[0];
25
+ const parts = clean.split(".").map(Number);
26
+ return [parts[0] || 0, parts[1] || 0, parts[2] || 0];
27
+ };
28
+ const compareVersions = (a, b) => {
29
+ for (let i = 0; i < 3; i++) {
30
+ if (a[i] !== b[i])
31
+ return a[i] - b[i];
32
+ }
33
+ return 0;
34
+ };
35
+ const isHigherMin = (a, b) => compareVersions(parseVersion(a), parseVersion(b)) > 0;
36
+ const isLowerMax = (a, b) => compareVersions(parseVersion(a), parseVersion(b)) < 0;
37
+ /**
38
+ * Walks a parsed rule's tech list, type, and steps, looks up every attribute present
39
+ * in RULE_VERSION_MAP, and folds the results into the strictest overall requirement:
40
+ * the highest min version and (if any apply) the lowest max version.
41
+ */
42
+ export const computeRequiredVersion = (rule) => {
43
+ var _a, _b;
44
+ const keys = [];
45
+ for (const tech of rule.tech || []) {
46
+ keys.push(`tech.${tech}`);
47
+ }
48
+ keys.push(`type.${rule.type}`);
49
+ for (const step of rule.steps || []) {
50
+ if (((_a = step.esquery) === null || _a === void 0 ? void 0 : _a.inScopeOf) !== undefined)
51
+ keys.push("step.esquery.inScopeOf");
52
+ if (((_b = step.esquery) === null || _b === void 0 ? void 0 : _b.taintFrom) !== undefined)
53
+ keys.push("step.esquery.taintFrom");
54
+ if (step.regexMatch)
55
+ keys.push("step.regexMatch");
56
+ if (step.csMastS)
57
+ keys.push("step.csMastS");
58
+ }
59
+ let result = { min: "0.0.0" };
60
+ for (const key of keys) {
61
+ const requirement = RULE_VERSION_MAP[key];
62
+ if (!requirement)
63
+ continue;
64
+ if (isHigherMin(requirement.min, result.min)) {
65
+ result = Object.assign(Object.assign({}, result), { min: requirement.min });
66
+ }
67
+ if (requirement.max && (!result.max || isLowerMax(requirement.max, result.max))) {
68
+ result = Object.assign(Object.assign({}, result), { max: requirement.max });
69
+ }
70
+ }
71
+ return result;
72
+ };
73
+ //# sourceMappingURL=ruleVersionMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ruleVersionMap.js","sourceRoot":"","sources":["../../src/utility/ruleVersionMap.ts"],"names":[],"mappings":"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"}
package/config.dist.yaml CHANGED
@@ -36,7 +36,7 @@ commands:
36
36
  oxylabsFallbackMaxRequests: "10"
37
37
  oxylabsFallbackMaxTotal: "100"
38
38
  oxylabsFallbackMaxOrigins: "25"
39
- cacheFile: .resp_cache.json
39
+ cacheFile: .resp_cache.db
40
40
  disableCache: false
41
41
  cacheOnly: false
42
42
  yes: false
@@ -173,7 +173,7 @@ commands:
173
173
  oxylabsFallbackMaxRequests: "10"
174
174
  oxylabsFallbackMaxTotal: "100"
175
175
  oxylabsFallbackMaxOrigins: "25"
176
- cacheFile: .resp_cache.json
176
+ cacheFile: .resp_cache.db
177
177
  disableCache: false
178
178
  cacheOnly: false
179
179
  yes: false
@@ -209,7 +209,7 @@ commands:
209
209
  load:
210
210
  caido: null
211
211
  url: null
212
- cacheFile: .resp_cache.json
212
+ cacheFile: .resp_cache.db
213
213
 
214
214
  fingerprint:
215
215
  # May also be a YAML list of HTTP(S) URLs.
@@ -0,0 +1,106 @@
1
+ # Writing tests for js-recon
2
+
3
+ New functionality must ship with tests. Which kind depends on what you're adding — see below.
4
+
5
+ ## Unit tests (Vitest)
6
+
7
+ Test framework is [Vitest](https://vitest.dev/) — ESM-native, TypeScript-native, no build step.
8
+
9
+ ```bash
10
+ npm test # run all unit tests once
11
+ npm run test:watch # watch mode
12
+ npm run test:coverage # run with coverage report
13
+ ```
14
+
15
+ **What to test.** Pure functions: anything that takes plain inputs and returns a value without I/O.
16
+ Puppeteer, network calls (`makeRequest`), and file writes are intentionally left untested at the
17
+ unit level — they're validated end-to-end via the `run` subcommand instead (see below). When a
18
+ function mixes I/O with logic, extract the parse/transform step into an exported pure function and
19
+ test that:
20
+
21
+ ```typescript
22
+ // Exported pure function — testable
23
+ export const parseThings = (content: string, baseUrl: string): string[] => {
24
+ /* ... */
25
+ };
26
+
27
+ // Orchestrator — not unit-tested
28
+ const myModule = async (url: string): Promise<string[]> => {
29
+ const resp = await makeRequest(url);
30
+ const content = await resp.text();
31
+ return parseThings(content, url);
32
+ };
33
+ ```
34
+
35
+ **File layout.** Tests live in `src/__tests__/<component>/<name>.test.ts`, mirroring the source
36
+ path. Use `describe`/`it` blocks grouped by function name; cover the happy path, edge cases (empty
37
+ input, malformed input), and threshold boundaries.
38
+
39
+ **Local imports use the `.js` extension** (this is an ESM project with `"module": "node16"`):
40
+
41
+ ```typescript
42
+ import { fn } from "../../lazyLoad/next_js/myModule.js";
43
+ ```
44
+
45
+ **Constructing Babel AST nodes for tests.** If a function under test requires a real Babel AST node
46
+ (with `scope`, `path`, correct `start`/`end` offsets), parse a snippet and capture the node via a
47
+ `traverse` visitor rather than building it by hand:
48
+
49
+ ```typescript
50
+ import parser from "@babel/parser";
51
+ import _traverse from "@babel/traverse";
52
+ const traverse = (_traverse.default ?? _traverse) as typeof _traverse.default;
53
+
54
+ function parseExpr(code: string) {
55
+ const src = `const _x = ${code};`;
56
+ const ast = parser.parse(src, { sourceType: "unambiguous", plugins: ["jsx", "typescript"] });
57
+ let node: any;
58
+ traverse(ast, {
59
+ VariableDeclarator(p) {
60
+ node = p.node.init;
61
+ p.stop();
62
+ },
63
+ });
64
+ return { node, src };
65
+ }
66
+ ```
67
+
68
+ **Avoid GitHub's secret scanner false-positives.** Strings that look like real secrets (webhook
69
+ URLs, API keys) get blocked by push protection even inside test files. Assemble them at runtime:
70
+
71
+ ```typescript
72
+ // BAD — blocked by secret scanner
73
+ const url = "https://hooks.slack.com/services/TABCDEF/BABCDEF/xxxxxxxxxxxx";
74
+
75
+ // GOOD — assembled at runtime
76
+ const parts = ["https://hooks.slack.com/services/T", "ABCDEF/B", "ABCDEF/xxxx"];
77
+ const url = parts.join("");
78
+ ```
79
+
80
+ ## Fuzz tests (fast-check)
81
+
82
+ js-recon's job is parsing and analyzing JS bundles pulled from third-party targets — that input is
83
+ fully untrusted. Functions on that boundary (parsing raw bundle text, resolving URLs/strings out of
84
+ it) should get a property-based fuzz test in addition to example-based unit tests, using
85
+ [fast-check](https://fast-check.dev/).
86
+
87
+ ```bash
88
+ npm run test:fuzz # runs src/**/*.fuzz.test.ts via vitest.fuzz.config.ts
89
+ ```
90
+
91
+ Fuzz tests live alongside the function's regular unit test, named `<name>.fuzz.test.ts`, and are
92
+ excluded from the default `npm test` run (they're slower — property-based, hundreds of generated
93
+ cases per run). See `src/__tests__/strings/extractStrings.fuzz.test.ts` for the reference shape:
94
+ generate arbitrary/adversarial strings, feed them through the same parse config the real call site
95
+ uses, and assert the function under test never throws uncaught or hangs. If a parse step can
96
+ legitimately throw on malformed input (Babel's `errorRecovery: true` does not guarantee it won't),
97
+ wrap it in try/catch inside the test exactly as the real call site does — a caught, expected error
98
+ is not a fuzz failure; an uncaught throw or a hang is.
99
+
100
+ ## Smoke tests (CI)
101
+
102
+ The `rules-smoke-test` GitHub Actions workflow runs js-recon end-to-end against a seeded lab app and
103
+ asserts every expected rule fires. If you're adding a new AST/request rule to `js-recon-rules`, seed
104
+ the corresponding vulnerability in `js-recon-labs`'s `next_js/vuln-all-rules` app and add the rule ID
105
+ to `EXPECTED_RULES` in `scripts/smoke-test.js`. See the root `CLAUDE.md`'s "Rules smoke test (CI)"
106
+ section for details.
@@ -0,0 +1,24 @@
1
+ import tseslint from "typescript-eslint";
2
+ import security from "eslint-plugin-security";
3
+
4
+ export default tseslint.config(
5
+ {
6
+ ignores: ["build/**", "output/**", "output_refactored/**", "node_modules/**"],
7
+ },
8
+ {
9
+ files: ["src/**/*.ts"],
10
+ extends: [...tseslint.configs.recommended],
11
+ plugins: {
12
+ security,
13
+ },
14
+ rules: {
15
+ ...security.configs.recommended.rules,
16
+ // These fire on legitimate dynamic-code patterns intrinsic to a bundle-analysis tool
17
+ // (parsing/instrumenting untrusted third-party JS is the entire point of js-recon).
18
+ "security/detect-non-literal-fs-filename": "off",
19
+ "security/detect-object-injection": "off",
20
+ "@typescript-eslint/no-explicit-any": "off",
21
+ "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
22
+ },
23
+ }
24
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@js-recon/js-recon",
3
- "version": "1.4.4",
3
+ "version": "2.0.1-alpha.2",
4
4
  "description": "JS Recon Tool",
5
5
  "main": "build/index.js",
6
6
  "type": "module",
@@ -13,9 +13,12 @@
13
13
  "start": "node --max-old-space-size=8192 build/index.js",
14
14
  "test": "vitest run",
15
15
  "test:watch": "vitest",
16
+ "test:coverage": "vitest run --coverage",
17
+ "test:fuzz": "vitest run --config vitest.fuzz.config.ts",
16
18
  "test:build": "node build/index.js -h",
17
- "postinstall": "patch-package",
18
- "cleanup": "rm -rf build output output_refactored .resp_cache.json .resp_cache.json.entries endpoints.json extracted_urls{.txt,.json,-openapi.json} strings.json mapped{-openapi.json,.json,-openapi.postman_collection.json} analyze.json test{.yaml,.js} js-recon-js-recon-*.tgz js-recon.db report.{html,md} js_recon_run_output *_test.js extracted/ research.json results* out.* && tsc"
19
+ "lint": "eslint src",
20
+ "postinstall": "patch-package || true; node scripts/postinstall-completion.mjs",
21
+ "cleanup": "rm -rf build output output_refactored .resp_cache.json .resp_cache.json.entries .resp_cache.db endpoints.json extracted_urls{.txt,.json,-openapi.json} strings.json mapped{-openapi.json,.json,-openapi.postman_collection.json} analyze.json test{.yaml,.js} js-recon-js-recon-*.tgz js-recon.db report.{html,md} js_recon_run_output *_test.js extracted/ research.json results* out.* swagger-jacker-results.json && tsc"
19
22
  },
20
23
  "keywords": [],
21
24
  "author": "Shriyans Sudhi",
@@ -27,7 +30,7 @@
27
30
  "@babel/traverse": "^7.28.5",
28
31
  "@babel/types": "^7.27.6",
29
32
  "@modelcontextprotocol/sdk": "^1.29.0",
30
- "@shriyanss/cli-print-img": "^1.1.0",
33
+ "@shriyanss/cli-print-img": "^1.1.1",
31
34
  "@shriyanss/cs-mast": "0.1.8",
32
35
  "@types/chalk": "^0.4.31",
33
36
  "@types/cli-progress": "^3.11.6",
@@ -41,13 +44,14 @@
41
44
  "datatables.net": "^2.3.6",
42
45
  "datatables.net-dt": "^2.3.6",
43
46
  "esquery": "^1.6.0",
47
+ "express": "^5.2.1",
44
48
  "extract-zip": "^2.0.1",
45
- "fs": "^0.0.2",
46
49
  "graphql": "^16.14.1",
47
50
  "highlight.js": "^11.11.1",
48
51
  "inquirer": "^12.6.3",
49
52
  "marked": "^16.1.2",
50
53
  "md5": "^2.3.0",
54
+ "ohash": "^2.0.11",
51
55
  "ollama": "^0.6.3",
52
56
  "openai": "^5.8.2",
53
57
  "patch-package": "^8.0.1",
@@ -58,7 +62,10 @@
58
62
  "puppeteer-extra-plugin-stealth": "^2.11.2",
59
63
  "readline": "^1.3.0",
60
64
  "ses": "^1.13.0",
61
- "undici": "^7.28.0",
65
+ "shell-quote": "^1.10.0",
66
+ "tar": "^7.5.22",
67
+ "undici": "^7.29.0",
68
+ "ws": "^8.21.2",
62
69
  "yaml": "^2.8.0",
63
70
  "zod": "^3.23.8"
64
71
  },
@@ -78,11 +85,20 @@
78
85
  "@types/babel__traverse": "^7.28.0",
79
86
  "@types/better-sqlite3": "^7.6.13",
80
87
  "@types/blessed": "^0.1.25",
88
+ "@types/express": "^5.0.6",
81
89
  "@types/graphql": "^14.2.3",
82
90
  "@types/node": "^24.12.4",
91
+ "@types/shell-quote": "^1.7.5",
92
+ "@types/ws": "^8.18.1",
93
+ "@vitest/coverage-v8": "^4.1.10",
94
+ "eslint": "^10.8.0",
95
+ "eslint-plugin-security": "^4.0.1",
96
+ "fast-check": "^4.9.0",
97
+ "patch-package": "^8.0.1",
83
98
  "ts-node": "^10.9.2",
84
99
  "tsconfig-paths": "^4.2.0",
85
100
  "typescript": "^5.9.2",
101
+ "typescript-eslint": "^8.66.0",
86
102
  "vitest": "^4.1.10"
87
103
  }
88
104
  }
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Smoke test: verifies that the `exploit` module reported `vulnerable: true` for every CVE
4
+ * fixture in js-recon-labs.
5
+ *
6
+ * Usage:
7
+ * node scripts/exploit-smoke-test.js [results-dir]
8
+ *
9
+ * Expects one `<CVE-ID>.json` (rich exploit.json output shape) per CVE in results-dir, as
10
+ * produced by the `exploit-smoke-test.yaml` workflow's `-o` flag.
11
+ */
12
+
13
+ import { readFileSync, existsSync } from "fs";
14
+ import { resolve } from "path";
15
+
16
+ const resultsDir = process.argv[2] || "/tmp/exploit-results";
17
+
18
+ const EXPECTED_CVES = [
19
+ "CVE-2025-29927",
20
+ "CVE-2026-64645",
21
+ "CVE-2025-30208",
22
+ "CVE-2026-39363",
23
+ "CVE-2026-71320",
24
+ "CVE-2026-71315",
25
+ "CVE-2026-68945",
26
+ "CVE-2025-55182",
27
+ ];
28
+
29
+ // RCE-class CVEs must additionally prove their `id` proof output looks like real `id` command
30
+ // output, not just any non-empty string — otherwise a broken payload that returns garbage would
31
+ // still satisfy a loose `vulnerable: true` check.
32
+ const RCE_OUTPUT_PATTERN = /uid=\d+.*gid=\d+/;
33
+ const RCE_CVES = new Set(["CVE-2026-71320", "CVE-2025-55182"]);
34
+
35
+ let failures = [];
36
+
37
+ for (const cveId of EXPECTED_CVES) {
38
+ const filePath = resolve(resultsDir, `${cveId}.json`);
39
+ if (!existsSync(filePath)) {
40
+ failures.push(`${cveId}: no result file at ${filePath}`);
41
+ continue;
42
+ }
43
+
44
+ let findings;
45
+ try {
46
+ findings = JSON.parse(readFileSync(filePath, "utf-8"));
47
+ } catch (err) {
48
+ failures.push(`${cveId}: could not parse ${filePath}: ${err.message}`);
49
+ continue;
50
+ }
51
+
52
+ const finding = findings[0];
53
+ if (!finding || finding.vulnerable !== true) {
54
+ failures.push(`${cveId}: not reported vulnerable (evidence: ${finding?.evidence ?? "none"})`);
55
+ continue;
56
+ }
57
+
58
+ if (RCE_CVES.has(cveId)) {
59
+ const execOutput = finding.execOutput ?? "";
60
+ if (!RCE_OUTPUT_PATTERN.test(execOutput)) {
61
+ failures.push(
62
+ `${cveId}: vulnerable=true but execOutput doesn't look like real 'id' output: "${execOutput}"`
63
+ );
64
+ }
65
+ }
66
+
67
+ console.log(`[✓] ${cveId}: vulnerable (${finding.evidence.slice(0, 120)})`);
68
+ }
69
+
70
+ console.log();
71
+ console.log(`[i] ${EXPECTED_CVES.length - failures.length} / ${EXPECTED_CVES.length} CVEs confirmed vulnerable.`);
72
+
73
+ if (failures.length > 0) {
74
+ console.error();
75
+ console.error("[!] Exploit smoke test FAILED:");
76
+ for (const f of failures) {
77
+ console.error(` - ${f}`);
78
+ }
79
+ process.exit(1);
80
+ }
81
+
82
+ console.log("[✓] Exploit smoke test PASSED.");
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Smoke test: verifies that js-recon's `fingerprint` command detects the
4
+ * correct front-end framework for every lab app in the framework-detection
5
+ * matrix (js-recon-labs/detection/*).
6
+ *
7
+ * Usage:
8
+ * node scripts/framework-detect-smoke-test.js [path-to-fingerprint-result.json]
9
+ *
10
+ * Default path: /tmp/fingerprint-result.json
11
+ */
12
+
13
+ import { readFileSync } from "fs";
14
+ import { resolve } from "path";
15
+
16
+ const resultPath = process.argv[2] || "/tmp/fingerprint-result.json";
17
+ const absolutePath = resolve(resultPath);
18
+
19
+ let results;
20
+ try {
21
+ results = JSON.parse(readFileSync(absolutePath, "utf-8"));
22
+ } catch (err) {
23
+ console.error(`[!] Could not read ${absolutePath}: ${err.message}`);
24
+ console.error(" Make sure `js-recon fingerprint -f json` completed successfully before running this script.");
25
+ process.exit(1);
26
+ }
27
+
28
+ // URL -> expected framework name, matching js-recon-labs/detection/* app ports.
29
+ const EXPECTED = {
30
+ "http://localhost:3010": "next",
31
+ "http://localhost:3011": "vue",
32
+ "http://localhost:3012": "nuxt",
33
+ "http://localhost:3013": "svelte",
34
+ "http://localhost:3014": "angular",
35
+ "http://localhost:3015": "react",
36
+ "http://localhost:3016": "react",
37
+ };
38
+
39
+ const detected = new Map(results.map((r) => [r.url, r.framework]));
40
+ const rows = [];
41
+ let failed = false;
42
+
43
+ for (const [url, expected] of Object.entries(EXPECTED)) {
44
+ const actual = detected.get(url) ?? "unknown";
45
+ const ok = actual === expected;
46
+ if (!ok) failed = true;
47
+ rows.push({ url, expected, actual, ok });
48
+ }
49
+
50
+ console.log(`[i] Checked ${rows.length} lab apps.`);
51
+ console.log();
52
+ console.log("URL".padEnd(28), "Expected".padEnd(10), "Detected".padEnd(10), "Result");
53
+ for (const { url, expected, actual, ok } of rows) {
54
+ console.log(url.padEnd(28), expected.padEnd(10), actual.padEnd(10), ok ? "OK" : "MISMATCH");
55
+ }
56
+ console.log();
57
+
58
+ if (failed) {
59
+ const mismatches = rows.filter((r) => !r.ok).length;
60
+ console.error(`[!] ${mismatches} / ${rows.length} apps failed framework detection. Smoke test FAILED.`);
61
+ process.exit(1);
62
+ }
63
+
64
+ console.log(`[✓] All ${rows.length} apps detected correctly. Smoke test PASSED.`);
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env node
2
+ // Auto-installs shell completion on real global installs/upgrades (npm install -g,
3
+ // Homebrew, the Docker release image). Never runs for contributor `npm install`/`npm ci`
4
+ // inside this repo (npm_config_global is unset/false there). Must never fail the parent
5
+ // `npm install` regardless of outcome — all errors are caught and logged, not thrown.
6
+
7
+ import path from "path";
8
+ import { fileURLToPath, pathToFileURL } from "url";
9
+
10
+ const SUPPORTED_SHELLS = new Set(["bash", "zsh", "fish"]);
11
+
12
+ async function main() {
13
+ if (process.env.npm_config_global !== "true") {
14
+ return;
15
+ }
16
+
17
+ const shellPath = process.env.SHELL;
18
+ if (!shellPath) {
19
+ console.log("[i] js-recon: SHELL environment variable not set; skipping automatic completion install.");
20
+ console.log("[i] Run `js-recon completion <bash|zsh|fish>` manually to enable it.");
21
+ return;
22
+ }
23
+
24
+ const shell = path.basename(shellPath);
25
+ if (!SUPPORTED_SHELLS.has(shell)) {
26
+ console.log(`[i] js-recon: unsupported shell "${shell}"; skipping automatic completion install.`);
27
+ console.log("[i] Supported shells: bash, zsh, fish. Run `js-recon completion <shell>` manually if applicable.");
28
+ return;
29
+ }
30
+
31
+ const here = path.dirname(fileURLToPath(import.meta.url));
32
+ const completionModuleUrl = pathToFileURL(path.join(here, "..", "build", "completion", "index.js"));
33
+ const { default: completion } = await import(completionModuleUrl);
34
+ completion(shell);
35
+ }
36
+
37
+ main().catch((err) => {
38
+ console.error(`[!] js-recon: automatic completion install failed: ${err?.message ?? err}`);
39
+ console.error("[!] Run `js-recon completion <bash|zsh|fish>` manually to enable it.");
40
+ });
@@ -40,13 +40,25 @@ const EXPECTED_RULES = [
40
40
  "detect_js_injection_eval",
41
41
  "detect_redos_url_param",
42
42
  "detect_cspt_fetch_url_param",
43
+ "detect_cspt_xhr_url_param",
43
44
  "detect_ajax_header_manipulation",
44
45
  "detect_postMessage",
45
46
  "detect_postMessage_innerHtml_sink",
46
47
  "detect_postMessage_function_href",
47
48
  "detect_postMessage_wildcard_origin",
48
49
  "detect_postmessage_eval",
50
+ "detect_postmessage_weak_origin_check",
49
51
  "detect_hardcoded_secrets",
52
+ "detect_css_injection_style_sink",
53
+ "detect_react_createelement_dynamic_type",
54
+ "detect_jquery_html_injection_url_param",
55
+ "detect_dompurify_forcekeepattr_hook",
56
+ "detect_client_side_authz_gate",
57
+ "detect_insecure_random_token_storage",
58
+ "detect_cloud_credentials_in_bundle",
59
+ "detect_hardcoded_hmac_signing_key",
60
+ "detect_non_global_regex_sanitizer",
61
+ "detect_prototype_pollution_merge_gadget",
50
62
  // Request rules
51
63
  "api_path",
52
64
  "admin_api",