@js-recon/js-recon 1.4.3 → 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.
- package/.claude-sync/sync.sh +1 -1
- package/.github/workflows/build-and-prettify.yaml +55 -25
- package/.github/workflows/codeql.yml +33 -0
- package/.github/workflows/exploit-smoke-test.yaml +160 -0
- package/.github/workflows/framework-detection-smoke-test.yaml +135 -0
- package/.github/workflows/plumber.yml +20 -0
- package/.github/workflows/promote-js-recon.yml +5 -3
- package/.github/workflows/publish-js-recon.yml +6 -1
- package/.github/workflows/rules-smoke-test.yaml +15 -7
- package/.nvmrc +1 -0
- package/.plumber.yaml +151 -0
- package/CHANGELOG.md +54 -0
- package/CONTRIBUTING.md +32 -0
- package/Dockerfile +1 -0
- package/README.md +55 -2
- package/SECURITY.md +1 -1
- package/build/analyze/engine/astEngine.js +10 -9
- package/build/analyze/engine/astEngine.js.map +1 -1
- package/build/analyze/engine/csMastSEngine.js +6 -6
- package/build/analyze/engine/csMastSEngine.js.map +1 -1
- package/build/analyze/engine/index.js +1 -1
- package/build/analyze/engine/index.js.map +1 -1
- package/build/analyze/engine/requestEngine.js +6 -6
- package/build/analyze/engine/requestEngine.js.map +1 -1
- package/build/analyze/helpers/determineCompatibleVersion.js +70 -0
- package/build/analyze/helpers/determineCompatibleVersion.js.map +1 -0
- package/build/analyze/helpers/engineHelpers/findMemberExpressionAssignment.js +9 -3
- package/build/analyze/helpers/engineHelpers/findMemberExpressionAssignment.js.map +1 -1
- package/build/analyze/helpers/initRules.js +42 -24
- package/build/analyze/helpers/initRules.js.map +1 -1
- package/build/analyze/helpers/outputHelper.js +3 -3
- package/build/analyze/helpers/outputHelper.js.map +1 -1
- package/build/analyze/helpers/schemas.js +1 -0
- package/build/analyze/helpers/schemas.js.map +1 -1
- package/build/analyze/helpers/validate.js +9 -5
- package/build/analyze/helpers/validate.js.map +1 -1
- package/build/analyze/index.js +26 -16
- package/build/analyze/index.js.map +1 -1
- package/build/cliProgram.js +710 -0
- package/build/cliProgram.js.map +1 -0
- package/build/completion/index.js +245 -339
- package/build/completion/index.js.map +1 -1
- package/build/completion/introspect.js +17 -0
- package/build/completion/introspect.js.map +1 -0
- package/build/config/applicationConfig.js +494 -0
- package/build/config/applicationConfig.js.map +1 -0
- package/build/cs_mast/index.js +18 -17
- package/build/cs_mast/index.js.map +1 -1
- package/build/endpoints/gen_report/gen_json.js +2 -2
- package/build/endpoints/gen_report/gen_json.js.map +1 -1
- package/build/endpoints/gen_report/utility/iterate_n_store.js +1 -1
- package/build/endpoints/gen_report/utility/iterate_n_store.js.map +1 -1
- package/build/endpoints/index.js +12 -12
- package/build/endpoints/index.js.map +1 -1
- package/build/endpoints/next_js/client_jsFilesHref.js +3 -3
- package/build/endpoints/next_js/client_jsFilesHref.js.map +1 -1
- package/build/endpoints/next_js/client_jsonParse.js +4 -4
- package/build/endpoints/next_js/client_jsonParse.js.map +1 -1
- package/build/endpoints/next_js/client_mappedJsonFile.js +6 -6
- package/build/endpoints/next_js/client_mappedJsonFile.js.map +1 -1
- package/build/endpoints/next_js/client_subsequentRequests.js +5 -5
- package/build/endpoints/next_js/client_subsequentRequests.js.map +1 -1
- package/build/exploit/angular/cve-2026-68945.js +61 -0
- package/build/exploit/angular/cve-2026-68945.js.map +1 -0
- package/build/exploit/index.js +60 -0
- package/build/exploit/index.js.map +1 -0
- package/build/exploit/next/cve-2025-29927.js +65 -0
- package/build/exploit/next/cve-2025-29927.js.map +1 -0
- package/build/exploit/next/cve-2026-64645.js +51 -0
- package/build/exploit/next/cve-2026-64645.js.map +1 -0
- package/build/exploit/nuxt/cve-2026-71315.js +47 -0
- package/build/exploit/nuxt/cve-2026-71315.js.map +1 -0
- package/build/exploit/nuxt/cve-2026-71320.js +114 -0
- package/build/exploit/nuxt/cve-2026-71320.js.map +1 -0
- package/build/exploit/react/cve-2025-55182.js +116 -0
- package/build/exploit/react/cve-2025-55182.js.map +1 -0
- package/build/exploit/registry/cveRegistry.js +115 -0
- package/build/exploit/registry/cveRegistry.js.map +1 -0
- package/build/exploit/types.js +2 -0
- package/build/exploit/types.js.map +1 -0
- package/build/exploit/utility/compareResponses.js +29 -0
- package/build/exploit/utility/compareResponses.js.map +1 -0
- package/build/exploit/utility/outputHelper.js +22 -0
- package/build/exploit/utility/outputHelper.js.map +1 -0
- package/build/exploit/utility/rawRequest.js +54 -0
- package/build/exploit/utility/rawRequest.js.map +1 -0
- package/build/exploit/utility/sandboxRce.js +49 -0
- package/build/exploit/utility/sandboxRce.js.map +1 -0
- package/build/exploit/utility/toEngineOutput.js +28 -0
- package/build/exploit/utility/toEngineOutput.js.map +1 -0
- package/build/exploit/utility/wsClient.js +78 -0
- package/build/exploit/utility/wsClient.js.map +1 -0
- package/build/exploit/vite/cve-2025-30208.js +44 -0
- package/build/exploit/vite/cve-2025-30208.js.map +1 -0
- package/build/exploit/vite/cve-2026-39363.js +60 -0
- package/build/exploit/vite/cve-2026-39363.js.map +1 -0
- package/build/fingerprint/index.js +11 -21
- package/build/fingerprint/index.js.map +1 -1
- package/build/globalConfig.js +2 -2
- package/build/globalConfig.js.map +1 -1
- package/build/index.js +16 -555
- package/build/index.js.map +1 -1
- package/build/lazyLoad/angular/angular_getFromPageSource.js +3 -3
- package/build/lazyLoad/angular/angular_getFromPageSource.js.map +1 -1
- package/build/lazyLoad/downloadFilesUtil.js +51 -40
- package/build/lazyLoad/downloadFilesUtil.js.map +1 -1
- package/build/lazyLoad/downloadQueue.js +154 -50
- package/build/lazyLoad/downloadQueue.js.map +1 -1
- package/build/lazyLoad/downloadResponse.js +113 -0
- package/build/lazyLoad/downloadResponse.js.map +1 -0
- package/build/lazyLoad/generic/generic_crawlPages.js +186 -0
- package/build/lazyLoad/generic/generic_crawlPages.js.map +1 -0
- package/build/lazyLoad/generic/generic_downloadFiles.js +81 -0
- package/build/lazyLoad/generic/generic_downloadFiles.js.map +1 -0
- package/build/lazyLoad/generic/generic_extractLinks.js +79 -0
- package/build/lazyLoad/generic/generic_extractLinks.js.map +1 -0
- package/build/lazyLoad/generic/generic_getScriptTags.js +152 -0
- package/build/lazyLoad/generic/generic_getScriptTags.js.map +1 -0
- package/build/lazyLoad/generic/generic_importMapDiscovery.js +87 -0
- package/build/lazyLoad/generic/generic_importMapDiscovery.js.map +1 -0
- package/build/lazyLoad/generic/generic_resolveScope.js +61 -0
- package/build/lazyLoad/generic/generic_resolveScope.js.map +1 -0
- package/build/lazyLoad/generic/generic_scanAttributesForJs.js +122 -0
- package/build/lazyLoad/generic/generic_scanAttributesForJs.js.map +1 -0
- package/build/lazyLoad/generic/generic_stringsDiscovery.js +103 -0
- package/build/lazyLoad/generic/generic_stringsDiscovery.js.map +1 -0
- package/build/lazyLoad/generic/generic_webpackChunkPaths.js +56 -0
- package/build/lazyLoad/generic/generic_webpackChunkPaths.js.map +1 -0
- package/build/lazyLoad/globals.js +35 -0
- package/build/lazyLoad/globals.js.map +1 -1
- package/build/lazyLoad/index.js +311 -175
- package/build/lazyLoad/index.js.map +1 -1
- package/build/lazyLoad/methodFilter.js +2 -0
- package/build/lazyLoad/methodFilter.js.map +1 -1
- package/build/lazyLoad/next_js/NextJsCrawler.js +39 -14
- package/build/lazyLoad/next_js/NextJsCrawler.js.map +1 -1
- package/build/lazyLoad/next_js/next_GetJSScript.js +3 -3
- package/build/lazyLoad/next_js/next_GetJSScript.js.map +1 -1
- package/build/lazyLoad/next_js/next_GetLazyResourcesBuildManifestJs.js +4 -4
- package/build/lazyLoad/next_js/next_GetLazyResourcesBuildManifestJs.js.map +1 -1
- package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js +21 -20
- package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js.map +1 -1
- package/build/lazyLoad/next_js/next_SubsequentRequests.js +100 -99
- package/build/lazyLoad/next_js/next_SubsequentRequests.js.map +1 -1
- package/build/lazyLoad/next_js/next_bruteForceJsFiles.js +1 -1
- package/build/lazyLoad/next_js/next_bruteForceJsFiles.js.map +1 -1
- package/build/lazyLoad/next_js/next_buildId.js +2 -2
- package/build/lazyLoad/next_js/next_buildId.js.map +1 -1
- package/build/lazyLoad/next_js/next_getClientSidePaths.js +2 -2
- package/build/lazyLoad/next_js/next_getClientSidePaths.js.map +1 -1
- package/build/lazyLoad/next_js/next_parseLayoutJs.js +6 -6
- package/build/lazyLoad/next_js/next_parseLayoutJs.js.map +1 -1
- package/build/lazyLoad/next_js/next_promiseResolve.js +1 -1
- package/build/lazyLoad/next_js/next_promiseResolve.js.map +1 -1
- package/build/lazyLoad/next_js/next_routerStateForge.js +341 -0
- package/build/lazyLoad/next_js/next_routerStateForge.js.map +1 -0
- package/build/lazyLoad/next_js/next_scriptTagsSubsequentRequests.js +1 -1
- package/build/lazyLoad/next_js/next_scriptTagsSubsequentRequests.js.map +1 -1
- package/build/lazyLoad/next_js/next_serverActionIdScan.js +77 -0
- package/build/lazyLoad/next_js/next_serverActionIdScan.js.map +1 -0
- package/build/lazyLoad/nuxt_js/nuxt_astParse.js +15 -13
- package/build/lazyLoad/nuxt_js/nuxt_astParse.js.map +1 -1
- package/build/lazyLoad/nuxt_js/nuxt_getBuildsManifest.js +2 -2
- package/build/lazyLoad/nuxt_js/nuxt_getBuildsManifest.js.map +1 -1
- package/build/lazyLoad/nuxt_js/nuxt_getFromPageSource.js +3 -3
- package/build/lazyLoad/nuxt_js/nuxt_getFromPageSource.js.map +1 -1
- package/build/lazyLoad/nuxt_js/nuxt_stringAnalysisJSFiles.js +2 -2
- package/build/lazyLoad/nuxt_js/nuxt_stringAnalysisJSFiles.js.map +1 -1
- package/build/lazyLoad/outputPath.js +92 -0
- package/build/lazyLoad/outputPath.js.map +1 -0
- package/build/lazyLoad/react/react_followImports.js +15 -5
- package/build/lazyLoad/react/react_followImports.js.map +1 -1
- package/build/lazyLoad/react/react_getScriptTags.js +11 -6
- package/build/lazyLoad/react/react_getScriptTags.js.map +1 -1
- package/build/lazyLoad/react/react_sourcemapUrls.js +3 -2
- package/build/lazyLoad/react/react_sourcemapUrls.js.map +1 -1
- package/build/lazyLoad/react/react_webpackChunkPaths.js +12 -203
- package/build/lazyLoad/react/react_webpackChunkPaths.js.map +1 -1
- package/build/lazyLoad/researchUtils.js +15 -0
- package/build/lazyLoad/researchUtils.js.map +1 -0
- package/build/lazyLoad/shared/webpackChunkParsers.js +218 -0
- package/build/lazyLoad/shared/webpackChunkParsers.js.map +1 -0
- package/build/lazyLoad/stagnation/stagnationMonitor.js +63 -0
- package/build/lazyLoad/stagnation/stagnationMonitor.js.map +1 -0
- package/build/lazyLoad/svelte/svelte_discoverPagesFromJs.js +1 -0
- package/build/lazyLoad/svelte/svelte_discoverPagesFromJs.js.map +1 -1
- package/build/lazyLoad/svelte/svelte_getFromPageSource.js +5 -5
- package/build/lazyLoad/svelte/svelte_getFromPageSource.js.map +1 -1
- package/build/lazyLoad/svelte/svelte_getVersionJson.js +2 -2
- package/build/lazyLoad/svelte/svelte_getVersionJson.js.map +1 -1
- package/build/lazyLoad/svelte/svelte_recursivePageCrawl.js +6 -6
- package/build/lazyLoad/svelte/svelte_recursivePageCrawl.js.map +1 -1
- package/build/lazyLoad/svelte/svelte_stringAnalysisJSFiles.js +2 -2
- package/build/lazyLoad/svelte/svelte_stringAnalysisJSFiles.js.map +1 -1
- package/build/lazyLoad/techDetect/checkAngularJS.js +1 -1
- package/build/lazyLoad/techDetect/checkAngularJS.js.map +1 -1
- package/build/lazyLoad/techDetect/checkNuxtJS.js +3 -3
- package/build/lazyLoad/techDetect/checkNuxtJS.js.map +1 -1
- package/build/lazyLoad/techDetect/checkSvelte.js +0 -1
- package/build/lazyLoad/techDetect/checkSvelte.js.map +1 -1
- package/build/lazyLoad/techDetect/checkVueJS.js +6 -6
- package/build/lazyLoad/techDetect/checkVueJS.js.map +1 -1
- package/build/lazyLoad/techDetect/index.js +106 -60
- package/build/lazyLoad/techDetect/index.js.map +1 -1
- package/build/lazyLoad/vue/vue_RuntimeJs.js +20 -15
- package/build/lazyLoad/vue/vue_RuntimeJs.js.map +1 -1
- package/build/lazyLoad/vue/vue_SingleJsFileOnHome.js +10 -5
- package/build/lazyLoad/vue/vue_SingleJsFileOnHome.js.map +1 -1
- package/build/lazyLoad/vue/vue_discoverJsFiles.js +20 -17
- package/build/lazyLoad/vue/vue_discoverJsFiles.js.map +1 -1
- package/build/lazyLoad/vue/vue_getClientSidePaths.js +70 -46
- package/build/lazyLoad/vue/vue_getClientSidePaths.js.map +1 -1
- package/build/lazyLoad/vue/vue_jsImports.js +3 -2
- package/build/lazyLoad/vue/vue_jsImports.js.map +1 -1
- package/build/lazyLoad/vue/vue_pageSrc.js +3 -2
- package/build/lazyLoad/vue/vue_pageSrc.js.map +1 -1
- package/build/lazyLoad/vue/vue_reconstructSourceMaps.js +6 -5
- package/build/lazyLoad/vue/vue_reconstructSourceMaps.js.map +1 -1
- package/build/lazyLoad/vue/vue_recursiveClientSidePathDownload.js +10 -21
- package/build/lazyLoad/vue/vue_recursiveClientSidePathDownload.js.map +1 -1
- package/build/lazyLoad/vue/vue_severalJsFilesHome.js +5 -4
- package/build/lazyLoad/vue/vue_severalJsFilesHome.js.map +1 -1
- package/build/lazyLoad/vue/vue_stringJsFiles.js +28 -25
- package/build/lazyLoad/vue/vue_stringJsFiles.js.map +1 -1
- package/build/lazyLoad/vue/vue_viteMapDeps.js +8 -2
- package/build/lazyLoad/vue/vue_viteMapDeps.js.map +1 -1
- package/build/load/index.js +8 -7
- package/build/load/index.js.map +1 -1
- package/build/map/angular_js/getAngularConnections.js +6 -6
- package/build/map/angular_js/getAngularConnections.js.map +1 -1
- package/build/map/graphql/resolveGraphql.js +6 -6
- package/build/map/graphql/resolveGraphql.js.map +1 -1
- package/build/map/index.js +17 -17
- package/build/map/index.js.map +1 -1
- package/build/map/interactive-mode/commandHandler.js +278 -0
- package/build/map/interactive-mode/commandHandler.js.map +1 -0
- package/build/map/interactive-mode/commandHelpers.js +189 -0
- package/build/map/interactive-mode/commandHelpers.js.map +1 -0
- package/build/map/interactive-mode/esqueryGen.js.map +1 -0
- package/build/map/interactive-mode/helpMenu.js +11 -0
- package/build/map/interactive-mode/helpMenu.js.map +1 -0
- package/build/map/interactive-mode/inputPatch.js.map +1 -0
- package/build/map/interactive-mode/interactive.js +71 -0
- package/build/map/interactive-mode/interactive.js.map +1 -0
- package/build/map/interactive-mode/keybindings.js.map +1 -0
- package/build/map/interactive-mode/printer.js.map +1 -0
- package/build/map/interactive-mode/ui.js.map +1 -0
- package/build/map/next_js/getAxiosInstances.js +5 -5
- package/build/map/next_js/getAxiosInstances.js.map +1 -1
- package/build/map/next_js/getExports.js +4 -4
- package/build/map/next_js/getExports.js.map +1 -1
- package/build/map/next_js/getFetchInstances.js +10 -10
- package/build/map/next_js/getFetchInstances.js.map +1 -1
- package/build/map/next_js/getTurbopackConnections.js +8 -8
- package/build/map/next_js/getTurbopackConnections.js.map +1 -1
- package/build/map/next_js/getWebpackConnections.js +27 -16
- package/build/map/next_js/getWebpackConnections.js.map +1 -1
- package/build/map/next_js/interactive.js +3 -65
- package/build/map/next_js/interactive.js.map +1 -1
- package/build/map/next_js/interactive_helpers/commandHandler.js +38 -290
- package/build/map/next_js/interactive_helpers/commandHandler.js.map +1 -1
- package/build/map/next_js/interactive_helpers/commandHelpers.js +0 -184
- package/build/map/next_js/interactive_helpers/commandHelpers.js.map +1 -1
- package/build/map/next_js/interactive_helpers/helpMenu.js +2 -10
- package/build/map/next_js/interactive_helpers/helpMenu.js.map +1 -1
- package/build/map/next_js/resolveAxios.js +6 -6
- package/build/map/next_js/resolveAxios.js.map +1 -1
- package/build/map/next_js/resolveAxiosHelpers/findAxiosClients.js +4 -4
- package/build/map/next_js/resolveAxiosHelpers/findAxiosClients.js.map +1 -1
- package/build/map/next_js/resolveAxiosHelpers/findAxiosInstance.js +2 -2
- package/build/map/next_js/resolveAxiosHelpers/findAxiosInstance.js.map +1 -1
- package/build/map/next_js/resolveAxiosHelpers/findCrossChunkParams.js +5 -5
- package/build/map/next_js/resolveAxiosHelpers/findCrossChunkParams.js.map +1 -1
- package/build/map/next_js/resolveAxiosHelpers/handleAxiosCreate.js +10 -10
- package/build/map/next_js/resolveAxiosHelpers/handleAxiosCreate.js.map +1 -1
- package/build/map/next_js/resolveAxiosHelpers/handleZDotCreate.js +13 -9
- package/build/map/next_js/resolveAxiosHelpers/handleZDotCreate.js.map +1 -1
- package/build/map/next_js/resolveAxiosHelpers/processAxiosCall.js +12 -8
- package/build/map/next_js/resolveAxiosHelpers/processAxiosCall.js.map +1 -1
- package/build/map/next_js/resolveAxiosHelpers/processDirectAxiosCall.js +12 -8
- package/build/map/next_js/resolveAxiosHelpers/processDirectAxiosCall.js.map +1 -1
- package/build/map/next_js/resolveAxiosHelpers/processExportedEndpoints.js +11 -11
- package/build/map/next_js/resolveAxiosHelpers/processExportedEndpoints.js.map +1 -1
- package/build/map/next_js/resolveAxiosHelpers/traceAxiosInstanceExports.js +16 -16
- package/build/map/next_js/resolveAxiosHelpers/traceAxiosInstanceExports.js.map +1 -1
- package/build/map/next_js/resolveFetch.js +23 -23
- package/build/map/next_js/resolveFetch.js.map +1 -1
- package/build/map/next_js/resolveNewRequest.js +10 -10
- package/build/map/next_js/resolveNewRequest.js.map +1 -1
- package/build/map/next_js/resolveServerActions.js +4 -4
- package/build/map/next_js/resolveServerActions.js.map +1 -1
- package/build/map/next_js/utils.js +8 -2
- package/build/map/next_js/utils.js.map +1 -1
- package/build/map/react_js/getReactConnections.js +21 -14
- package/build/map/react_js/getReactConnections.js.map +1 -1
- package/build/map/svelte_js/interactive.js +3 -54
- package/build/map/svelte_js/interactive.js.map +1 -1
- package/build/map/vue_js/getViteConnections.js +23 -16
- package/build/map/vue_js/getViteConnections.js.map +1 -1
- package/build/map/vue_js/interactive.js +3 -63
- package/build/map/vue_js/interactive.js.map +1 -1
- package/build/map/vue_js/interactive_helpers/commandHandler.js +34 -283
- package/build/map/vue_js/interactive_helpers/commandHandler.js.map +1 -1
- package/build/map/vue_js/interactive_helpers/helpMenu.js +2 -10
- package/build/map/vue_js/interactive_helpers/helpMenu.js.map +1 -1
- package/build/map/vue_js/taint_utils.js +1 -1
- package/build/map/vue_js/taint_utils.js.map +1 -1
- package/build/map/vue_js/vue_resolveFetch.js +12 -12
- package/build/map/vue_js/vue_resolveFetch.js.map +1 -1
- package/build/map/vue_js/vue_resolveHttpClient.js +18 -18
- package/build/map/vue_js/vue_resolveHttpClient.js.map +1 -1
- package/build/map/vue_js/vue_resolveXhr.js +11 -11
- package/build/map/vue_js/vue_resolveXhr.js.map +1 -1
- package/build/mcp/chatOneShot.js +7 -7
- package/build/mcp/chatOneShot.js.map +1 -1
- package/build/mcp/claudeCodeCreds.js +5 -5
- package/build/mcp/claudeCodeCreds.js.map +1 -1
- package/build/mcp/cli.js +36 -35
- package/build/mcp/cli.js.map +1 -1
- package/build/mcp/config.js +4 -4
- package/build/mcp/config.js.map +1 -1
- package/build/mcp/index.js +7 -7
- package/build/mcp/index.js.map +1 -1
- package/build/mcp/mcpServer.js +3 -2
- package/build/mcp/mcpServer.js.map +1 -1
- package/build/mcp/skills.js +1 -0
- package/build/mcp/skills.js.map +1 -1
- package/build/mcp/tools.js +5 -4
- package/build/mcp/tools.js.map +1 -1
- package/build/proxy/checkFeasibility.js +8 -4
- package/build/proxy/checkFeasibility.js.map +1 -1
- package/build/proxy/checkFireWallBlocking.js +23 -13
- package/build/proxy/checkFireWallBlocking.js.map +1 -1
- package/build/proxy/detectBlockedResponse.js +205 -0
- package/build/proxy/detectBlockedResponse.js.map +1 -0
- package/build/proxy/genReq.js +434 -127
- package/build/proxy/genReq.js.map +1 -1
- package/build/proxy/index.js +3 -3
- package/build/proxy/index.js.map +1 -1
- package/build/proxy/oxylabsFallback.js +110 -0
- package/build/proxy/oxylabsFallback.js.map +1 -0
- package/build/proxy/proxyFeasibilityRequest.js +11 -9
- package/build/proxy/proxyFeasibilityRequest.js.map +1 -1
- package/build/refactor/index.js +83 -79
- package/build/refactor/index.js.map +1 -1
- package/build/refactor/next/index.js +69 -26
- package/build/refactor/next/index.js.map +1 -1
- package/build/refactor/next/transform.js +11 -4
- package/build/refactor/next/transform.js.map +1 -1
- package/build/refactor/next/validator.js +7 -7
- package/build/refactor/next/validator.js.map +1 -1
- package/build/refactor/react/index.js +13 -13
- package/build/refactor/react/index.js.map +1 -1
- package/build/refactor/react/validator.js +7 -7
- package/build/refactor/react/validator.js.map +1 -1
- package/build/refactor/react-vite/index.js +3 -3
- package/build/refactor/react-vite/index.js.map +1 -1
- package/build/refactor/remote/hf-client.js +1 -0
- package/build/refactor/remote/hf-client.js.map +1 -1
- package/build/refactor/remote/version-detect.js +12 -12
- package/build/refactor/remote/version-detect.js.map +1 -1
- package/build/refactor/vue/index.js +6 -6
- package/build/refactor/vue/index.js.map +1 -1
- package/build/refactor/vue/vite.js +6 -6
- package/build/refactor/vue/vite.js.map +1 -1
- package/build/report/index.js +30 -8
- package/build/report/index.js.map +1 -1
- package/build/report/swaggerJacker.js +63 -0
- package/build/report/swaggerJacker.js.map +1 -0
- package/build/report/utility/genHtml.js +7 -7
- package/build/report/utility/genHtml.js.map +1 -1
- package/build/report/utility/populateDb/populateAnalysisFindings.js +2 -2
- package/build/report/utility/populateDb/populateAnalysisFindings.js.map +1 -1
- package/build/report/utility/populateDb/populateEndpoints.js +3 -3
- package/build/report/utility/populateDb/populateEndpoints.js.map +1 -1
- package/build/report/utility/populateDb/populateMappedJson.js +2 -2
- package/build/report/utility/populateDb/populateMappedJson.js.map +1 -1
- package/build/report/utility/populateDb/populateMappedOpenapi.js +3 -3
- package/build/report/utility/populateDb/populateMappedOpenapi.js.map +1 -1
- package/build/run/bundler-detect.js +45 -9
- package/build/run/bundler-detect.js.map +1 -1
- package/build/run/cancellableStep.js +27 -0
- package/build/run/cancellableStep.js.map +1 -0
- package/build/run/dashboard/dashboardHtml.js +150 -0
- package/build/run/dashboard/dashboardHtml.js.map +1 -0
- package/build/run/dashboard/fsBrowser.js +43 -0
- package/build/run/dashboard/fsBrowser.js.map +1 -0
- package/build/run/dashboard/server.js +123 -0
- package/build/run/dashboard/server.js.map +1 -0
- package/build/run/dashboard/state.js +97 -0
- package/build/run/dashboard/state.js.map +1 -0
- package/build/run/index.js +239 -204
- package/build/run/index.js.map +1 -1
- package/build/run/interruptHandler.js +18 -0
- package/build/run/interruptHandler.js.map +1 -1
- package/build/run/outputDirectory.js +377 -0
- package/build/run/outputDirectory.js.map +1 -0
- package/build/sourcemaps/index.js +116 -29
- package/build/sourcemaps/index.js.map +1 -1
- package/build/strings/index.js +38 -28
- package/build/strings/index.js.map +1 -1
- package/build/strings/openapi.js +4 -4
- package/build/strings/openapi.js.map +1 -1
- package/build/strings/permutate.js +4 -4
- package/build/strings/permutate.js.map +1 -1
- package/build/strings/secrets.js +1 -0
- package/build/strings/secrets.js.map +1 -1
- package/build/strings/trufflehog.js +66 -19
- package/build/strings/trufflehog.js.map +1 -1
- package/build/strings/trufflehogConfig.js +36 -0
- package/build/strings/trufflehogConfig.js.map +1 -0
- package/build/strings/trufflehogDownload.js +115 -0
- package/build/strings/trufflehogDownload.js.map +1 -0
- package/build/utility/ai.js +33 -4
- package/build/utility/ai.js.map +1 -1
- package/build/utility/banner.js +4 -3
- package/build/utility/banner.js.map +1 -1
- package/build/utility/configureSandbox.js +2 -2
- package/build/utility/configureSandbox.js.map +1 -1
- package/build/utility/downloadProgress.js +99 -0
- package/build/utility/downloadProgress.js.map +1 -0
- package/build/utility/globals.js +19 -11
- package/build/utility/globals.js.map +1 -1
- package/build/utility/heap.js +2 -1
- package/build/utility/heap.js.map +1 -1
- package/build/utility/makeReq.js +490 -257
- package/build/utility/makeReq.js.map +1 -1
- package/build/utility/openapiGenerator.js +2 -2
- package/build/utility/openapiGenerator.js.map +1 -1
- package/build/utility/printMsg.js +53 -0
- package/build/utility/printMsg.js.map +1 -0
- package/build/utility/progressLog.js +68 -7
- package/build/utility/progressLog.js.map +1 -1
- package/build/utility/resolvePath.js +2 -1
- package/build/utility/resolvePath.js.map +1 -1
- package/build/utility/ruleVersionMap.js +73 -0
- package/build/utility/ruleVersionMap.js.map +1 -0
- package/build/utility/targetInputs.js +177 -0
- package/build/utility/targetInputs.js.map +1 -0
- package/build/utility/urlUtils.js +37 -1
- package/build/utility/urlUtils.js.map +1 -1
- package/config.dist.yaml +251 -0
- package/contributing/testing.md +106 -0
- package/eslint.config.js +24 -0
- package/package.json +22 -5
- package/scripts/exploit-smoke-test.js +82 -0
- package/scripts/framework-detect-smoke-test.js +64 -0
- package/scripts/postinstall-completion.mjs +40 -0
- package/scripts/smoke-test.js +12 -0
- package/build/lazyLoad/downloadLoadedJsUtil.js +0 -98
- package/build/lazyLoad/downloadLoadedJsUtil.js.map +0 -1
- package/build/map/next_js/interactive_helpers/esqueryGen.js.map +0 -1
- package/build/map/next_js/interactive_helpers/inputPatch.js.map +0 -1
- package/build/map/next_js/interactive_helpers/keybindings.js.map +0 -1
- package/build/map/next_js/interactive_helpers/printer.js.map +0 -1
- package/build/map/next_js/interactive_helpers/ui.js.map +0 -1
- /package/build/map/{next_js/interactive_helpers → interactive-mode}/esqueryGen.js +0 -0
- /package/build/map/{next_js/interactive_helpers → interactive-mode}/inputPatch.js +0 -0
- /package/build/map/{next_js/interactive_helpers → interactive-mode}/keybindings.js +0 -0
- /package/build/map/{next_js/interactive_helpers → interactive-mode}/printer.js +0 -0
- /package/build/map/{next_js/interactive_helpers → interactive-mode}/ui.js +0 -0
package/build/run/index.js
CHANGED
|
@@ -14,19 +14,26 @@ import * as globalsUtil from "../utility/globals.js";
|
|
|
14
14
|
import * as fs from "fs";
|
|
15
15
|
import lazyLoad from "../lazyLoad/index.js";
|
|
16
16
|
import chalk from "chalk";
|
|
17
|
-
import CONFIG from "../globalConfig.js";
|
|
18
17
|
import analyze from "../analyze/index.js";
|
|
19
18
|
import report from "../report/index.js";
|
|
20
19
|
import refactor from "../refactor/index.js";
|
|
21
20
|
import initGlobalReportDb from "../report/utility/initGlobalReportDb.js";
|
|
22
21
|
import mergeDomainIntoGlobalDb from "../report/utility/mergeDomainIntoGlobalDb.js";
|
|
23
|
-
import { clearJsUrls, clearJsonUrls, getJsUrls } from "../lazyLoad/globals.js";
|
|
22
|
+
import { clearJsUrls, clearJsonUrls, clearJsFileHashCounts, getJsUrls } from "../lazyLoad/globals.js";
|
|
24
23
|
import path from "path";
|
|
25
24
|
import { installSigintHandler, removeSigintHandler, getSkipStepPromise, resetSkipStep, shouldSkipTarget, resetSkipTarget, waitForPendingInterrupt, } from "./interruptHandler.js";
|
|
26
25
|
import { detectBundler } from "./bundler-detect.js";
|
|
26
|
+
import { printMsg, MSG, setHeaderListener } from "../utility/printMsg.js";
|
|
27
27
|
import configureProxy from "../utility/configureProxy.js";
|
|
28
|
+
import { getOxylabsFallbackConfiguration } from "../proxy/oxylabsFallback.js";
|
|
28
29
|
import { probeFeasibility } from "../proxy/checkFeasibility.js";
|
|
29
30
|
import { getResolvedProxyConfigFromGlobals } from "../utility/makeReq.js";
|
|
31
|
+
import { resolveHostOutputDirectory } from "../lazyLoad/outputPath.js";
|
|
32
|
+
import { awaitCancellableStep } from "./cancellableStep.js";
|
|
33
|
+
import { resolveTargetInputs } from "../utility/targetInputs.js";
|
|
34
|
+
import { clearRunOutputDirectory, getBatchTargetDirectoryName, reserveRunOutputDirectory } from "./outputDirectory.js";
|
|
35
|
+
import { startDashboardServer } from "./dashboard/server.js";
|
|
36
|
+
import * as dashboardState from "./dashboard/state.js";
|
|
30
37
|
/**
|
|
31
38
|
* Determines the directory for a Content Delivery Network (CDN) if used by the target.
|
|
32
39
|
*
|
|
@@ -37,17 +44,16 @@ import { getResolvedProxyConfigFromGlobals } from "../utility/makeReq.js";
|
|
|
37
44
|
* @param outputDir - The base output directory
|
|
38
45
|
* @returns Promise that resolves to the path of the CDN directory or undefined if no CDN is detected
|
|
39
46
|
*/
|
|
40
|
-
const getCdnDir = (host, outputDir) => __awaiter(void 0, void 0, void 0, function* () {
|
|
47
|
+
const getCdnDir = (host, outputDir, isBatch) => __awaiter(void 0, void 0, void 0, function* () {
|
|
41
48
|
// get the JS URLs
|
|
42
49
|
let cdnDir;
|
|
43
50
|
for (const url of getJsUrls()) {
|
|
44
51
|
if (url.includes("_next/static/chunks")) {
|
|
45
52
|
// check if the host and url.host match
|
|
46
|
-
const urlHostDir = new URL(url).host.replace(":", "_"); // e.g. example.com_8443
|
|
47
53
|
const urlHost = new URL(url).host; // e.g. example.com:8443
|
|
48
54
|
const initialHost = new URL(host).host; // e.g. example.com:443
|
|
49
55
|
if (urlHost !== initialHost) {
|
|
50
|
-
cdnDir =
|
|
56
|
+
cdnDir = resolveHostOutputDirectory(outputDir, urlHost, isBatch);
|
|
51
57
|
break;
|
|
52
58
|
}
|
|
53
59
|
}
|
|
@@ -74,11 +80,12 @@ const getCdnDir = (host, outputDir) => __awaiter(void 0, void 0, void 0, functio
|
|
|
74
80
|
*/
|
|
75
81
|
const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_1) => __awaiter(void 0, [url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_1], void 0, function* (url, outputDir, workingDir, cmd, isBatch, includeMethods = [], excludeMethods = []) {
|
|
76
82
|
var _a, _b, _c, _d;
|
|
77
|
-
const targetHost = new URL(url).host
|
|
78
|
-
|
|
83
|
+
const targetHost = new URL(url).host;
|
|
84
|
+
printMsg(MSG.Run, `[+] Starting analysis for ${url}...`);
|
|
79
85
|
if (isBatch) {
|
|
80
86
|
clearJsUrls();
|
|
81
87
|
clearJsonUrls();
|
|
88
|
+
clearJsFileHashCounts();
|
|
82
89
|
globalsUtil.clearOpenapiOutput();
|
|
83
90
|
}
|
|
84
91
|
if (cmd.proxyWafFallback && cmd._proxyConfigured) {
|
|
@@ -89,42 +96,39 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
89
96
|
outcome = yield probeFeasibility(resolved, url);
|
|
90
97
|
}
|
|
91
98
|
catch (error) {
|
|
92
|
-
|
|
99
|
+
printMsg(MSG.Err, `[!] Proxy WAF fallback check failed: ${error}. ${isBatch ? "Skipping this target." : "Quitting."}`);
|
|
93
100
|
if (isBatch)
|
|
94
101
|
return;
|
|
95
102
|
process.exit(29);
|
|
96
103
|
}
|
|
97
|
-
|
|
104
|
+
printMsg(outcome.code === 0 ? MSG.Run : MSG.Warn, outcome.message);
|
|
98
105
|
if (outcome.code === 27) {
|
|
99
106
|
// no firewall detected without a proxy - don't use it for this target
|
|
100
107
|
globalsUtil.setUseProxy(false);
|
|
101
108
|
}
|
|
102
109
|
else if (outcome.code === 28) {
|
|
103
|
-
|
|
110
|
+
printMsg(MSG.Err, `[!] Proxy could not bypass the firewall for this target. ${isBatch ? "Skipping this target." : "Quitting."}`);
|
|
104
111
|
if (isBatch)
|
|
105
112
|
return;
|
|
106
113
|
process.exit(29);
|
|
107
114
|
}
|
|
108
115
|
// outcome.code === 0: firewall present, proxy bypasses it - keep using the proxy
|
|
109
116
|
}
|
|
110
|
-
|
|
117
|
+
printMsg(MSG.Header, "[1/8] Running lazyload to download JavaScript files...");
|
|
111
118
|
resetSkipStep();
|
|
112
|
-
yield
|
|
113
|
-
|
|
114
|
-
getSkipStepPromise(),
|
|
115
|
-
]);
|
|
116
|
-
console.log(chalk.bgGreen("[+] Lazyload complete."));
|
|
119
|
+
yield awaitCancellableStep((signal) => lazyLoad(url, outputDir, cmd.strictScope, cmd.scope.split(","), cmd.threads, false, "", cmd.insecure, false, cmd.sourcemapDir, cmd.research, cmd.researchOutput, Number(cmd.maxIterations), Number(cmd.maxJsSize), Number(cmd.lazyloadTimeout) * 60 * 1000, Number(cmd.maxPages), includeMethods, excludeMethods, Number(cmd.detectionTimeout) * 1000, signal, isBatch, Number(cmd.maxRedirects), cmd.strings, Number(cmd.stringsMaxIterations), Number(cmd.stagnationTimein) * 60 * 1000, Number(cmd.stagnationPercentage), Number(cmd.stagnationMonitor) * 60 * 1000, Number(cmd.rscParamBruteforceLimit)), getSkipStepPromise());
|
|
120
|
+
printMsg(MSG.Run, "[+] Lazyload complete.");
|
|
117
121
|
if (shouldSkipTarget())
|
|
118
122
|
return;
|
|
119
123
|
if (globalsUtil.getTech() === "") {
|
|
120
|
-
|
|
124
|
+
printMsg(MSG.Err, `[!] Technology not detected. ${isBatch ? "Skipping this target." : "Quitting."}`);
|
|
121
125
|
if (isBatch) {
|
|
122
126
|
return;
|
|
123
127
|
}
|
|
124
128
|
process.exit(10);
|
|
125
129
|
}
|
|
126
130
|
if (!["next", "vue", "nuxt", "react", "svelte", "angular"].includes(globalsUtil.getTech())) {
|
|
127
|
-
|
|
131
|
+
printMsg(MSG.Warn, `[!] The tool supports Next.JS, Vue.JS, Nuxt.JS, React, Svelte/Astro, and Angular in the run module. For ${globalsUtil.getTech()}, only downloading JS files is supported`);
|
|
128
132
|
return;
|
|
129
133
|
}
|
|
130
134
|
// Capture the tech here — subsequent lazyload passes (steps 3, 4.5) re-run framework
|
|
@@ -140,7 +144,7 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
140
144
|
const reportDbFile = isBatch ? `${workingDir}/js-recon.db` : "js-recon.db";
|
|
141
145
|
const reportFile = isBatch ? `${workingDir}/report` : "report";
|
|
142
146
|
const endpointsFile = isBatch ? `${workingDir}/endpoints` : "endpoints";
|
|
143
|
-
|
|
147
|
+
printMsg(MSG.Header, "[2/4] Running map to find functions and API calls...");
|
|
144
148
|
globalsUtil.setOpenapi(true);
|
|
145
149
|
if (isBatch) {
|
|
146
150
|
globalsUtil.setOpenapiOutputFile(openapiFile);
|
|
@@ -155,46 +159,45 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
155
159
|
map(outputDir, mappedFileReact, ["json"], "react", false, false, cmd.command || []),
|
|
156
160
|
getSkipStepPromise(),
|
|
157
161
|
]);
|
|
158
|
-
|
|
162
|
+
printMsg(MSG.Run, "[+] Map complete.");
|
|
159
163
|
if (shouldSkipTarget())
|
|
160
164
|
return;
|
|
161
|
-
|
|
165
|
+
printMsg(MSG.Header, "[3/4] Running analyze...");
|
|
162
166
|
resetSkipStep();
|
|
163
|
-
// @ts-ignore
|
|
164
167
|
yield Promise.race([
|
|
165
|
-
analyze(cmd.rules || "", mappedJsonFileReact, "react", false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck),
|
|
168
|
+
analyze(cmd.rules || "", mappedJsonFileReact, "react", false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck, false, false),
|
|
166
169
|
getSkipStepPromise(),
|
|
167
170
|
]);
|
|
168
|
-
|
|
171
|
+
printMsg(MSG.Run, "[+] Analyze complete.");
|
|
169
172
|
if (shouldSkipTarget())
|
|
170
173
|
return;
|
|
171
|
-
|
|
174
|
+
printMsg(MSG.Header, "[4/4] Running report module...");
|
|
172
175
|
const endpointsJson = `${endpointsFile}.json`;
|
|
173
176
|
if (!fs.existsSync(endpointsJson)) {
|
|
174
177
|
fs.writeFileSync(endpointsJson, "[]");
|
|
175
178
|
}
|
|
176
179
|
resetSkipStep();
|
|
177
180
|
yield Promise.race([
|
|
178
|
-
report(reportDbFile, mappedJsonFileReact, analyzeFile, endpointsJson, openapiFile, reportFile),
|
|
181
|
+
report(reportDbFile, mappedJsonFileReact, analyzeFile, endpointsJson, openapiFile, reportFile, cmd.sj, cmd.sjBin, cmd.sjArgs),
|
|
179
182
|
getSkipStepPromise(),
|
|
180
183
|
]);
|
|
181
|
-
|
|
184
|
+
printMsg(MSG.Run, "[+] Report complete.");
|
|
182
185
|
if (shouldSkipTarget())
|
|
183
186
|
return;
|
|
184
187
|
if (!cmd.disableRefactor) {
|
|
185
|
-
|
|
188
|
+
printMsg(MSG.Header, "[*] Detecting bundler via CS-MAST-S for refactor...");
|
|
186
189
|
const detectedBundlerTechReact = yield detectBundler(mappedJsonFileReact, "react", Number((_a = cmd.csMastTechDetectThreshold) !== null && _a !== void 0 ? _a : 50));
|
|
187
190
|
if (detectedBundlerTechReact) {
|
|
188
191
|
const refactorOutputDirReact = isBatch ? `${workingDir}/refactored` : "refactored";
|
|
189
192
|
if (fs.existsSync(refactorOutputDirReact))
|
|
190
193
|
fs.rmSync(refactorOutputDirReact, { recursive: true });
|
|
191
|
-
|
|
194
|
+
printMsg(MSG.Header, `[*] Running refactor (${detectedBundlerTechReact})...`);
|
|
192
195
|
// Vendor chunks may have been downloaded under a different host than the target
|
|
193
196
|
// (CDN) — resolve the assets dir from an actual downloaded JS URL's host instead
|
|
194
197
|
// of always assuming targetHost, mirroring getCdnDir's approach for the map step.
|
|
195
198
|
let reactAssetsHostDir = targetHost;
|
|
196
199
|
for (const jsUrl of getJsUrls()) {
|
|
197
|
-
const jsUrlHost = new URL(jsUrl).host
|
|
200
|
+
const jsUrlHost = new URL(jsUrl).host;
|
|
198
201
|
if (jsUrlHost !== targetHost) {
|
|
199
202
|
reactAssetsHostDir = jsUrlHost;
|
|
200
203
|
break;
|
|
@@ -202,21 +205,21 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
202
205
|
}
|
|
203
206
|
resetSkipStep();
|
|
204
207
|
yield Promise.race([
|
|
205
|
-
refactor(mappedJsonFileReact, refactorOutputDirReact, detectedBundlerTechReact, false, undefined, undefined,
|
|
208
|
+
refactor(mappedJsonFileReact, refactorOutputDirReact, detectedBundlerTechReact, false, undefined, undefined, path.join(resolveHostOutputDirectory(outputDir, reactAssetsHostDir, isBatch), "assets")),
|
|
206
209
|
getSkipStepPromise(),
|
|
207
210
|
]);
|
|
208
211
|
if (shouldSkipTarget())
|
|
209
212
|
return;
|
|
210
|
-
|
|
213
|
+
printMsg(MSG.Run, "[+] Refactor complete.");
|
|
211
214
|
}
|
|
212
215
|
else {
|
|
213
|
-
|
|
216
|
+
printMsg(MSG.Warn, "[!] Bundler not detected via CS-MAST-S, skipping refactor.");
|
|
214
217
|
}
|
|
215
218
|
}
|
|
216
219
|
else {
|
|
217
|
-
|
|
220
|
+
printMsg(MSG.Warn, "[!] Refactor step disabled via --disable-refactor, skipping.");
|
|
218
221
|
}
|
|
219
|
-
|
|
222
|
+
printMsg(MSG.Run, `[+] Analysis complete for ${url}.`);
|
|
220
223
|
return;
|
|
221
224
|
}
|
|
222
225
|
if (detectedTech === "vue") {
|
|
@@ -230,7 +233,7 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
230
233
|
const reportDbFile = isBatch ? `${workingDir}/js-recon.db` : "js-recon.db";
|
|
231
234
|
const reportFile = isBatch ? `${workingDir}/report` : "report";
|
|
232
235
|
const endpointsFile = isBatch ? `${workingDir}/endpoints` : "endpoints";
|
|
233
|
-
|
|
236
|
+
printMsg(MSG.Header, "[2/4] Running map to find functions and API calls...");
|
|
234
237
|
globalsUtil.setOpenapi(true);
|
|
235
238
|
if (isBatch) {
|
|
236
239
|
globalsUtil.setOpenapiOutputFile(openapiFile);
|
|
@@ -245,20 +248,19 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
245
248
|
map(outputDir, mappedFileVue, ["json"], "vue", false, false, cmd.command || []),
|
|
246
249
|
getSkipStepPromise(),
|
|
247
250
|
]);
|
|
248
|
-
|
|
251
|
+
printMsg(MSG.Run, "[+] Map complete.");
|
|
249
252
|
if (shouldSkipTarget())
|
|
250
253
|
return;
|
|
251
|
-
|
|
254
|
+
printMsg(MSG.Header, "[3/4] Running analyze...");
|
|
252
255
|
resetSkipStep();
|
|
253
|
-
// @ts-ignore
|
|
254
256
|
yield Promise.race([
|
|
255
|
-
analyze(cmd.rules || "", mappedJsonFileVue, "vue", false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck),
|
|
257
|
+
analyze(cmd.rules || "", mappedJsonFileVue, "vue", false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck, false, false),
|
|
256
258
|
getSkipStepPromise(),
|
|
257
259
|
]);
|
|
258
|
-
|
|
260
|
+
printMsg(MSG.Run, "[+] Analyze complete.");
|
|
259
261
|
if (shouldSkipTarget())
|
|
260
262
|
return;
|
|
261
|
-
|
|
263
|
+
printMsg(MSG.Header, "[4/4] Running report module...");
|
|
262
264
|
// Endpoints extraction isn't implemented for Vue yet; pass an empty file if absent.
|
|
263
265
|
const endpointsJson = `${endpointsFile}.json`;
|
|
264
266
|
if (!fs.existsSync(endpointsJson)) {
|
|
@@ -266,20 +268,20 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
266
268
|
}
|
|
267
269
|
resetSkipStep();
|
|
268
270
|
yield Promise.race([
|
|
269
|
-
report(reportDbFile, mappedJsonFileVue, analyzeFile, endpointsJson, openapiFile, reportFile),
|
|
271
|
+
report(reportDbFile, mappedJsonFileVue, analyzeFile, endpointsJson, openapiFile, reportFile, cmd.sj, cmd.sjBin, cmd.sjArgs),
|
|
270
272
|
getSkipStepPromise(),
|
|
271
273
|
]);
|
|
272
|
-
|
|
274
|
+
printMsg(MSG.Run, "[+] Report complete.");
|
|
273
275
|
if (shouldSkipTarget())
|
|
274
276
|
return;
|
|
275
277
|
if (!cmd.disableRefactor) {
|
|
276
|
-
|
|
278
|
+
printMsg(MSG.Header, "[*] Detecting bundler via CS-MAST-S for refactor...");
|
|
277
279
|
const detectedBundlerTechVue = yield detectBundler(mappedJsonFileVue, "vue", Number((_b = cmd.csMastTechDetectThreshold) !== null && _b !== void 0 ? _b : 50));
|
|
278
280
|
if (detectedBundlerTechVue) {
|
|
279
281
|
const refactorOutputDirVue = isBatch ? `${workingDir}/refactored` : "refactored";
|
|
280
282
|
if (fs.existsSync(refactorOutputDirVue))
|
|
281
283
|
fs.rmSync(refactorOutputDirVue, { recursive: true });
|
|
282
|
-
|
|
284
|
+
printMsg(MSG.Header, `[*] Running refactor (${detectedBundlerTechVue})...`);
|
|
283
285
|
resetSkipStep();
|
|
284
286
|
yield Promise.race([
|
|
285
287
|
refactor(mappedJsonFileVue, refactorOutputDirVue, detectedBundlerTechVue, false),
|
|
@@ -287,16 +289,16 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
287
289
|
]);
|
|
288
290
|
if (shouldSkipTarget())
|
|
289
291
|
return;
|
|
290
|
-
|
|
292
|
+
printMsg(MSG.Run, "[+] Refactor complete.");
|
|
291
293
|
}
|
|
292
294
|
else {
|
|
293
|
-
|
|
295
|
+
printMsg(MSG.Warn, "[!] Bundler not detected via CS-MAST-S, skipping refactor.");
|
|
294
296
|
}
|
|
295
297
|
}
|
|
296
298
|
else {
|
|
297
|
-
|
|
299
|
+
printMsg(MSG.Warn, "[!] Refactor step disabled via --disable-refactor, skipping.");
|
|
298
300
|
}
|
|
299
|
-
|
|
301
|
+
printMsg(MSG.Run, `[+] Analysis complete for ${url}.`);
|
|
300
302
|
return;
|
|
301
303
|
}
|
|
302
304
|
if (detectedTech === "nuxt") {
|
|
@@ -308,7 +310,7 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
308
310
|
const reportDbFile = isBatch ? `${workingDir}/js-recon.db` : "js-recon.db";
|
|
309
311
|
const reportFile = isBatch ? `${workingDir}/report` : "report";
|
|
310
312
|
const endpointsFile = isBatch ? `${workingDir}/endpoints` : "endpoints";
|
|
311
|
-
|
|
313
|
+
printMsg(MSG.Header, "[2/4] Running map to find functions and API calls...");
|
|
312
314
|
globalsUtil.setOpenapi(true);
|
|
313
315
|
if (isBatch) {
|
|
314
316
|
globalsUtil.setOpenapiOutputFile(openapiFile);
|
|
@@ -323,40 +325,39 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
323
325
|
map(outputDir, mappedFileNuxt, ["json"], "vue", false, false, cmd.command || []),
|
|
324
326
|
getSkipStepPromise(),
|
|
325
327
|
]);
|
|
326
|
-
|
|
328
|
+
printMsg(MSG.Run, "[+] Map complete.");
|
|
327
329
|
if (shouldSkipTarget())
|
|
328
330
|
return;
|
|
329
|
-
|
|
331
|
+
printMsg(MSG.Header, "[3/4] Running analyze...");
|
|
330
332
|
resetSkipStep();
|
|
331
|
-
// @ts-ignore
|
|
332
333
|
yield Promise.race([
|
|
333
|
-
analyze(cmd.rules || "", mappedJsonFileNuxt, "vue", false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck),
|
|
334
|
+
analyze(cmd.rules || "", mappedJsonFileNuxt, "vue", false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck, false, false),
|
|
334
335
|
getSkipStepPromise(),
|
|
335
336
|
]);
|
|
336
|
-
|
|
337
|
+
printMsg(MSG.Run, "[+] Analyze complete.");
|
|
337
338
|
if (shouldSkipTarget())
|
|
338
339
|
return;
|
|
339
|
-
|
|
340
|
+
printMsg(MSG.Header, "[4/4] Running report module...");
|
|
340
341
|
const endpointsJson = `${endpointsFile}.json`;
|
|
341
342
|
if (!fs.existsSync(endpointsJson)) {
|
|
342
343
|
fs.writeFileSync(endpointsJson, "[]");
|
|
343
344
|
}
|
|
344
345
|
resetSkipStep();
|
|
345
346
|
yield Promise.race([
|
|
346
|
-
report(reportDbFile, mappedJsonFileNuxt, analyzeFile, endpointsJson, openapiFile, reportFile),
|
|
347
|
+
report(reportDbFile, mappedJsonFileNuxt, analyzeFile, endpointsJson, openapiFile, reportFile, cmd.sj, cmd.sjBin, cmd.sjArgs),
|
|
347
348
|
getSkipStepPromise(),
|
|
348
349
|
]);
|
|
349
|
-
|
|
350
|
+
printMsg(MSG.Run, "[+] Report complete.");
|
|
350
351
|
if (shouldSkipTarget())
|
|
351
352
|
return;
|
|
352
353
|
if (!cmd.disableRefactor) {
|
|
353
|
-
|
|
354
|
+
printMsg(MSG.Header, "[*] Detecting bundler via CS-MAST-S for refactor...");
|
|
354
355
|
const detectedBundlerTechNuxt = yield detectBundler(mappedJsonFileNuxt, "nuxt", Number((_c = cmd.csMastTechDetectThreshold) !== null && _c !== void 0 ? _c : 50));
|
|
355
356
|
if (detectedBundlerTechNuxt) {
|
|
356
357
|
const refactorOutputDirNuxt = isBatch ? `${workingDir}/refactored` : "refactored";
|
|
357
358
|
if (fs.existsSync(refactorOutputDirNuxt))
|
|
358
359
|
fs.rmSync(refactorOutputDirNuxt, { recursive: true });
|
|
359
|
-
|
|
360
|
+
printMsg(MSG.Header, `[*] Running refactor (${detectedBundlerTechNuxt})...`);
|
|
360
361
|
resetSkipStep();
|
|
361
362
|
yield Promise.race([
|
|
362
363
|
refactor(mappedJsonFileNuxt, refactorOutputDirNuxt, detectedBundlerTechNuxt, false),
|
|
@@ -364,16 +365,16 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
364
365
|
]);
|
|
365
366
|
if (shouldSkipTarget())
|
|
366
367
|
return;
|
|
367
|
-
|
|
368
|
+
printMsg(MSG.Run, "[+] Refactor complete.");
|
|
368
369
|
}
|
|
369
370
|
else {
|
|
370
|
-
|
|
371
|
+
printMsg(MSG.Warn, "[!] Bundler not detected via CS-MAST-S, skipping refactor.");
|
|
371
372
|
}
|
|
372
373
|
}
|
|
373
374
|
else {
|
|
374
|
-
|
|
375
|
+
printMsg(MSG.Warn, "[!] Refactor step disabled via --disable-refactor, skipping.");
|
|
375
376
|
}
|
|
376
|
-
|
|
377
|
+
printMsg(MSG.Run, `[+] Analysis complete for ${url}.`);
|
|
377
378
|
return;
|
|
378
379
|
}
|
|
379
380
|
if (detectedTech === "svelte") {
|
|
@@ -384,7 +385,7 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
384
385
|
const reportDbFile = isBatch ? `${workingDir}/js-recon.db` : "js-recon.db";
|
|
385
386
|
const reportFile = isBatch ? `${workingDir}/report` : "report";
|
|
386
387
|
const endpointsFile = isBatch ? `${workingDir}/endpoints` : "endpoints";
|
|
387
|
-
|
|
388
|
+
printMsg(MSG.Header, "[2/4] Running map to find functions and API calls...");
|
|
388
389
|
globalsUtil.setOpenapi(true);
|
|
389
390
|
if (isBatch) {
|
|
390
391
|
globalsUtil.setOpenapiOutputFile(openapiFile);
|
|
@@ -399,31 +400,30 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
399
400
|
map(outputDir, mappedFileSvelte, ["json"], "svelte", false, false, cmd.command || []),
|
|
400
401
|
getSkipStepPromise(),
|
|
401
402
|
]);
|
|
402
|
-
|
|
403
|
+
printMsg(MSG.Run, "[+] Map complete.");
|
|
403
404
|
if (shouldSkipTarget())
|
|
404
405
|
return;
|
|
405
|
-
|
|
406
|
+
printMsg(MSG.Header, "[3/4] Running analyze...");
|
|
406
407
|
resetSkipStep();
|
|
407
|
-
// @ts-ignore
|
|
408
408
|
yield Promise.race([
|
|
409
|
-
analyze(cmd.rules || "", mappedJsonFileSvelte, "svelte", false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck),
|
|
409
|
+
analyze(cmd.rules || "", mappedJsonFileSvelte, "svelte", false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck, false, false),
|
|
410
410
|
getSkipStepPromise(),
|
|
411
411
|
]);
|
|
412
|
-
|
|
412
|
+
printMsg(MSG.Run, "[+] Analyze complete.");
|
|
413
413
|
if (shouldSkipTarget())
|
|
414
414
|
return;
|
|
415
|
-
|
|
415
|
+
printMsg(MSG.Header, "[4/4] Running report module...");
|
|
416
416
|
const endpointsJson = `${endpointsFile}.json`;
|
|
417
417
|
if (!fs.existsSync(endpointsJson)) {
|
|
418
418
|
fs.writeFileSync(endpointsJson, "[]");
|
|
419
419
|
}
|
|
420
420
|
resetSkipStep();
|
|
421
421
|
yield Promise.race([
|
|
422
|
-
report(reportDbFile, mappedJsonFileSvelte, analyzeFile, endpointsJson, openapiFile, reportFile),
|
|
422
|
+
report(reportDbFile, mappedJsonFileSvelte, analyzeFile, endpointsJson, openapiFile, reportFile, cmd.sj, cmd.sjBin, cmd.sjArgs),
|
|
423
423
|
getSkipStepPromise(),
|
|
424
424
|
]);
|
|
425
|
-
|
|
426
|
-
|
|
425
|
+
printMsg(MSG.Run, "[+] Report complete.");
|
|
426
|
+
printMsg(MSG.Run, `[+] Analysis complete for ${url}.`);
|
|
427
427
|
return;
|
|
428
428
|
}
|
|
429
429
|
if (detectedTech === "angular") {
|
|
@@ -437,8 +437,8 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
437
437
|
const reportDbFile = isBatch ? `${workingDir}/js-recon.db` : "js-recon.db";
|
|
438
438
|
const reportFile = isBatch ? `${workingDir}/report` : "report";
|
|
439
439
|
const endpointsFile = isBatch ? `${workingDir}/endpoints` : "endpoints";
|
|
440
|
-
const angularHostDir =
|
|
441
|
-
|
|
440
|
+
const angularHostDir = resolveHostOutputDirectory(outputDir, targetHost, isBatch);
|
|
441
|
+
printMsg(MSG.Header, "[2/4] Running map to find functions and API calls...");
|
|
442
442
|
globalsUtil.setOpenapi(true);
|
|
443
443
|
if (isBatch) {
|
|
444
444
|
globalsUtil.setOpenapiOutputFile(openapiFile);
|
|
@@ -453,31 +453,30 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
453
453
|
map(angularHostDir, mappedFileAngular, ["json"], "angular", false, false, cmd.command || []),
|
|
454
454
|
getSkipStepPromise(),
|
|
455
455
|
]);
|
|
456
|
-
|
|
456
|
+
printMsg(MSG.Run, "[+] Map complete.");
|
|
457
457
|
if (shouldSkipTarget())
|
|
458
458
|
return;
|
|
459
|
-
|
|
459
|
+
printMsg(MSG.Header, "[3/4] Running analyze...");
|
|
460
460
|
resetSkipStep();
|
|
461
|
-
// @ts-ignore
|
|
462
461
|
yield Promise.race([
|
|
463
|
-
analyze(cmd.rules || "", mappedJsonFileAngular, "angular", false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck),
|
|
462
|
+
analyze(cmd.rules || "", mappedJsonFileAngular, "angular", false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck, false, false),
|
|
464
463
|
getSkipStepPromise(),
|
|
465
464
|
]);
|
|
466
|
-
|
|
465
|
+
printMsg(MSG.Run, "[+] Analyze complete.");
|
|
467
466
|
if (shouldSkipTarget())
|
|
468
467
|
return;
|
|
469
|
-
|
|
468
|
+
printMsg(MSG.Header, "[4/4] Running report module...");
|
|
470
469
|
const endpointsJson = `${endpointsFile}.json`;
|
|
471
470
|
if (!fs.existsSync(endpointsJson)) {
|
|
472
471
|
fs.writeFileSync(endpointsJson, "[]");
|
|
473
472
|
}
|
|
474
473
|
resetSkipStep();
|
|
475
474
|
yield Promise.race([
|
|
476
|
-
report(reportDbFile, mappedJsonFileAngular, analyzeFile, endpointsJson, openapiFile, reportFile),
|
|
475
|
+
report(reportDbFile, mappedJsonFileAngular, analyzeFile, endpointsJson, openapiFile, reportFile, cmd.sj, cmd.sjBin, cmd.sjArgs),
|
|
477
476
|
getSkipStepPromise(),
|
|
478
477
|
]);
|
|
479
|
-
|
|
480
|
-
|
|
478
|
+
printMsg(MSG.Run, "[+] Report complete.");
|
|
479
|
+
printMsg(MSG.Run, `[+] Analysis complete for ${url}.`);
|
|
481
480
|
return;
|
|
482
481
|
}
|
|
483
482
|
const stringsFile = isBatch ? `${workingDir}/strings.json` : "strings.json";
|
|
@@ -492,58 +491,52 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
492
491
|
// if the target is using a CDN, then just passing the outputDir/host won't work, and would throw an error.
|
|
493
492
|
// So, if the target was found to be using a CDN, scan the CDN directory rather than the outputDir/host
|
|
494
493
|
// One IMPORTANT thing: this is only meant for modules that rely on just the code (map)
|
|
495
|
-
const cdnDir = yield getCdnDir(url, outputDir);
|
|
496
|
-
const cdnOutputDir = cdnDir ? cdnDir : outputDir
|
|
497
|
-
|
|
494
|
+
const cdnDir = yield getCdnDir(url, outputDir, isBatch);
|
|
495
|
+
const cdnOutputDir = cdnDir ? cdnDir : resolveHostOutputDirectory(outputDir, targetHost, isBatch);
|
|
496
|
+
printMsg(MSG.Header, "[2/8] Running strings to extract endpoints...");
|
|
498
497
|
resetSkipStep();
|
|
499
498
|
yield Promise.race([
|
|
500
499
|
strings(outputDir, stringsFile, true, extractedUrlsFile, false, false, false, false),
|
|
501
500
|
getSkipStepPromise(),
|
|
502
501
|
]);
|
|
503
|
-
|
|
502
|
+
printMsg(MSG.Run, "[+] Strings complete.");
|
|
504
503
|
if (shouldSkipTarget())
|
|
505
504
|
return;
|
|
506
|
-
|
|
505
|
+
printMsg(MSG.Header, "[3/8] Running lazyload with subsequent requests to download JavaScript files...");
|
|
507
506
|
resetSkipStep();
|
|
508
|
-
yield
|
|
509
|
-
|
|
510
|
-
getSkipStepPromise(),
|
|
511
|
-
]);
|
|
512
|
-
console.log(chalk.bgGreen("[+] Lazyload with subsequent requests complete."));
|
|
507
|
+
yield awaitCancellableStep((signal) => lazyLoad(url, outputDir, cmd.strictScope, cmd.scope.split(","), cmd.threads, true, `${extractedUrlsFile}.json`, cmd.insecure, true, cmd.sourcemapDir, cmd.research, cmd.researchOutput, Number(cmd.maxIterations), Number(cmd.maxJsSize), Number(cmd.lazyloadTimeout) * 60 * 1000, Number(cmd.maxPages), includeMethods, excludeMethods, Number(cmd.detectionTimeout) * 1000, signal, isBatch, Number(cmd.maxRedirects), cmd.strings, Number(cmd.stringsMaxIterations), Number(cmd.stagnationTimein) * 60 * 1000, Number(cmd.stagnationPercentage), Number(cmd.stagnationMonitor) * 60 * 1000, Number(cmd.rscParamBruteforceLimit)), getSkipStepPromise());
|
|
508
|
+
printMsg(MSG.Run, "[+] Lazyload with subsequent requests complete.");
|
|
513
509
|
if (shouldSkipTarget())
|
|
514
510
|
return;
|
|
515
|
-
|
|
511
|
+
printMsg(MSG.Header, "[4/8] Running strings again to extract endpoints...");
|
|
516
512
|
resetSkipStep();
|
|
517
513
|
yield Promise.race([
|
|
518
|
-
strings(outputDir, stringsFile, true, extractedUrlsFile, cmd.secrets, true, true, cmd.trufflehog),
|
|
514
|
+
strings(outputDir, stringsFile, true, extractedUrlsFile, cmd.secrets, true, true, cmd.trufflehog, cmd.trufflehogBin, cmd.trufflehogAcceptTerms),
|
|
519
515
|
getSkipStepPromise(),
|
|
520
516
|
]);
|
|
521
|
-
|
|
517
|
+
printMsg(MSG.Run, "[+] Strings complete.");
|
|
522
518
|
if (shouldSkipTarget())
|
|
523
519
|
return;
|
|
524
520
|
// a second subsequent_requests pass: the first strings pass only sees initial chunks,
|
|
525
521
|
// so dynamic routes such as `/post/1` are only discovered after the first subsequent
|
|
526
522
|
// crawl + second strings extraction. Re-running subsequent_requests with the freshly
|
|
527
523
|
// updated paths picks up chunks for those dynamic routes (e.g. the post page).
|
|
528
|
-
|
|
524
|
+
printMsg(MSG.Header, "[4.5/8] Re-running lazyload with subsequent requests for newly discovered paths...");
|
|
529
525
|
resetSkipStep();
|
|
530
|
-
yield
|
|
531
|
-
|
|
532
|
-
getSkipStepPromise(),
|
|
533
|
-
]);
|
|
534
|
-
console.log(chalk.bgGreen("[+] Lazyload re-pass complete."));
|
|
526
|
+
yield awaitCancellableStep((signal) => lazyLoad(url, outputDir, cmd.strictScope, cmd.scope.split(","), cmd.threads, true, `${extractedUrlsFile}.json`, cmd.insecure, false, cmd.sourcemapDir, cmd.research, cmd.researchOutput, Number(cmd.maxIterations), Number(cmd.maxJsSize), Number(cmd.lazyloadTimeout) * 60 * 1000, Number(cmd.maxPages), includeMethods, excludeMethods, Number(cmd.detectionTimeout) * 1000, signal, isBatch, Number(cmd.maxRedirects), cmd.strings, Number(cmd.stringsMaxIterations), Number(cmd.stagnationTimein) * 60 * 1000, Number(cmd.stagnationPercentage), Number(cmd.stagnationMonitor) * 60 * 1000, Number(cmd.rscParamBruteforceLimit)), getSkipStepPromise());
|
|
527
|
+
printMsg(MSG.Run, "[+] Lazyload re-pass complete.");
|
|
535
528
|
if (shouldSkipTarget())
|
|
536
529
|
return;
|
|
537
|
-
|
|
530
|
+
printMsg(MSG.Header, "[4.6/8] Re-running strings for chunks from the re-pass...");
|
|
538
531
|
resetSkipStep();
|
|
539
532
|
yield Promise.race([
|
|
540
|
-
strings(outputDir, stringsFile, true, extractedUrlsFile, cmd.secrets, true, true, cmd.trufflehog),
|
|
533
|
+
strings(outputDir, stringsFile, true, extractedUrlsFile, cmd.secrets, true, true, cmd.trufflehog, cmd.trufflehogBin, cmd.trufflehogAcceptTerms),
|
|
541
534
|
getSkipStepPromise(),
|
|
542
535
|
]);
|
|
543
|
-
|
|
536
|
+
printMsg(MSG.Run, "[+] Strings re-pass complete.");
|
|
544
537
|
if (shouldSkipTarget())
|
|
545
538
|
return;
|
|
546
|
-
|
|
539
|
+
printMsg(MSG.Header, "[5/8] Running map to find functions...");
|
|
547
540
|
globalsUtil.setOpenapi(true);
|
|
548
541
|
if (isBatch) {
|
|
549
542
|
globalsUtil.setOpenapiOutputFile(openapiFile);
|
|
@@ -561,14 +554,15 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
561
554
|
map(cdnOutputDir, mappedFile, ["json"], detectedTech, false, false, cmd.command || []),
|
|
562
555
|
getSkipStepPromise(),
|
|
563
556
|
]);
|
|
564
|
-
|
|
557
|
+
printMsg(MSG.Run, "[+] Map complete.");
|
|
565
558
|
if (shouldSkipTarget())
|
|
566
559
|
return;
|
|
567
|
-
|
|
560
|
+
printMsg(MSG.Header, "[6/8] Running endpoints to extract endpoints...");
|
|
568
561
|
resetSkipStep();
|
|
569
|
-
|
|
562
|
+
const targetOutputDir = resolveHostOutputDirectory(outputDir, targetHost, isBatch);
|
|
563
|
+
if (fs.existsSync(path.join(targetOutputDir, "___subsequent_requests"))) {
|
|
570
564
|
yield Promise.race([
|
|
571
|
-
endpoints(url,
|
|
565
|
+
endpoints(url, targetOutputDir, endpointsFile, ["json"], "next", false, mappedJsonFile),
|
|
572
566
|
getSkipStepPromise(),
|
|
573
567
|
]);
|
|
574
568
|
}
|
|
@@ -578,35 +572,35 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
578
572
|
getSkipStepPromise(),
|
|
579
573
|
]);
|
|
580
574
|
}
|
|
581
|
-
|
|
575
|
+
printMsg(MSG.Run, "[+] Endpoints complete.");
|
|
582
576
|
if (shouldSkipTarget())
|
|
583
577
|
return;
|
|
584
|
-
|
|
578
|
+
printMsg(MSG.Header, "[7/8] Running analyze to extract endpoints...");
|
|
585
579
|
resetSkipStep();
|
|
586
580
|
yield Promise.race([
|
|
587
|
-
analyze(cmd.rules || "", mappedJsonFile, detectedTech, false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck),
|
|
581
|
+
analyze(cmd.rules || "", mappedJsonFile, detectedTech, false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck, false, false),
|
|
588
582
|
getSkipStepPromise(),
|
|
589
583
|
]);
|
|
590
|
-
|
|
584
|
+
printMsg(MSG.Run, "[+] Analyze complete.");
|
|
591
585
|
if (shouldSkipTarget())
|
|
592
586
|
return;
|
|
593
|
-
|
|
587
|
+
printMsg(MSG.Header, "[8/8] Running report module...");
|
|
594
588
|
resetSkipStep();
|
|
595
589
|
yield Promise.race([
|
|
596
|
-
report(reportDbFile, mappedJsonFile, analyzeFile, `${endpointsFile}.json`, openapiFile, reportFile),
|
|
590
|
+
report(reportDbFile, mappedJsonFile, analyzeFile, `${endpointsFile}.json`, openapiFile, reportFile, cmd.sj, cmd.sjBin, cmd.sjArgs),
|
|
597
591
|
getSkipStepPromise(),
|
|
598
592
|
]);
|
|
599
|
-
|
|
593
|
+
printMsg(MSG.Run, "[+] Report complete.");
|
|
600
594
|
if (shouldSkipTarget())
|
|
601
595
|
return;
|
|
602
596
|
if (!cmd.disableRefactor) {
|
|
603
|
-
|
|
597
|
+
printMsg(MSG.Header, "[*] Detecting bundler via CS-MAST-S for refactor...");
|
|
604
598
|
const detectedBundlerTechNext = yield detectBundler(mappedJsonFile, detectedTech, Number((_d = cmd.csMastTechDetectThreshold) !== null && _d !== void 0 ? _d : 50));
|
|
605
599
|
if (detectedBundlerTechNext) {
|
|
606
600
|
const refactorOutputDirNext = isBatch ? `${workingDir}/refactored` : "refactored";
|
|
607
601
|
if (fs.existsSync(refactorOutputDirNext))
|
|
608
602
|
fs.rmSync(refactorOutputDirNext, { recursive: true });
|
|
609
|
-
|
|
603
|
+
printMsg(MSG.Header, `[*] Running refactor (${detectedBundlerTechNext})...`);
|
|
610
604
|
resetSkipStep();
|
|
611
605
|
yield Promise.race([
|
|
612
606
|
refactor(mappedJsonFile, refactorOutputDirNext, detectedBundlerTechNext, false),
|
|
@@ -614,29 +608,17 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
|
|
|
614
608
|
]);
|
|
615
609
|
if (shouldSkipTarget())
|
|
616
610
|
return;
|
|
617
|
-
|
|
611
|
+
printMsg(MSG.Run, "[+] Refactor complete.");
|
|
618
612
|
}
|
|
619
613
|
else {
|
|
620
|
-
|
|
614
|
+
printMsg(MSG.Warn, "[!] Bundler not detected via CS-MAST-S, skipping refactor.");
|
|
621
615
|
}
|
|
622
616
|
}
|
|
623
617
|
else {
|
|
624
|
-
|
|
618
|
+
printMsg(MSG.Warn, "[!] Refactor step disabled via --disable-refactor, skipping.");
|
|
625
619
|
}
|
|
626
|
-
|
|
620
|
+
printMsg(MSG.Run, `[+] Analysis complete for ${url}.`);
|
|
627
621
|
});
|
|
628
|
-
/**
|
|
629
|
-
* Removes everything inside a directory without removing the directory itself.
|
|
630
|
-
*
|
|
631
|
-
* Used instead of `fs.rmSync(dir, { recursive: true })` for --output-overwrite: the output
|
|
632
|
-
* directory may be a Docker bind-mount point, and removing a mount point throws EBUSY
|
|
633
|
-
* ("Device or resource busy") even from inside the container's own mount namespace.
|
|
634
|
-
*/
|
|
635
|
-
const emptyDir = (dir) => {
|
|
636
|
-
for (const entry of fs.readdirSync(dir)) {
|
|
637
|
-
fs.rmSync(path.join(dir, entry), { recursive: true, force: true });
|
|
638
|
-
}
|
|
639
|
-
};
|
|
640
622
|
/**
|
|
641
623
|
* Main handler for the 'run' command that executes the complete js-recon analysis pipeline.
|
|
642
624
|
*
|
|
@@ -647,109 +629,162 @@ const emptyDir = (dir) => {
|
|
|
647
629
|
* @param cmd - The command-line options object from commander.js
|
|
648
630
|
* @returns Promise that resolves when all URL processing is complete
|
|
649
631
|
*/
|
|
632
|
+
/**
|
|
633
|
+
* Parses a batch/single `cmd.url` into the `{ url, hostDir, dir }` entries the
|
|
634
|
+
* dashboard state store needs, mirroring the hostDir/dir resolution the batch
|
|
635
|
+
* loop and single-target path use below. Invalid URLs are dropped — they're
|
|
636
|
+
* reported (and skipped) by the existing validation further down.
|
|
637
|
+
*/
|
|
638
|
+
const buildDashboardTargetEntries = (cmd, isBatch) => {
|
|
639
|
+
const toEntry = (url, dir) => {
|
|
640
|
+
try {
|
|
641
|
+
return { url, hostDir: new URL(url).host.replace(":", "_"), dir };
|
|
642
|
+
}
|
|
643
|
+
catch (_a) {
|
|
644
|
+
return null;
|
|
645
|
+
}
|
|
646
|
+
};
|
|
647
|
+
if (!isBatch) {
|
|
648
|
+
const entry = toEntry(cmd.url, cmd.output);
|
|
649
|
+
return entry ? [entry] : [];
|
|
650
|
+
}
|
|
651
|
+
return fs
|
|
652
|
+
.readFileSync(cmd.url, "utf-8")
|
|
653
|
+
.split("\n")
|
|
654
|
+
.filter((url) => url !== "")
|
|
655
|
+
.map((url) => toEntry(url, `${cmd.output}/${new URL(url).host.replace(":", "_")}`))
|
|
656
|
+
.filter((e) => e !== null);
|
|
657
|
+
};
|
|
650
658
|
export default (cmd) => __awaiter(void 0, void 0, void 0, function* () {
|
|
651
|
-
var _a, _b, _c, _d, _e;
|
|
659
|
+
var _a, _b, _c, _d, _e, _f;
|
|
660
|
+
const resolvedTargets = resolveTargetInputs(cmd.url);
|
|
652
661
|
configureProxy(cmd);
|
|
662
|
+
if (getOxylabsFallbackConfiguration().enabled)
|
|
663
|
+
globalsUtil.setUseProxy(false);
|
|
653
664
|
// Snapshot the originally-configured proxy state so `processUrl`'s --proxy-waf-fallback check
|
|
654
665
|
// can reset it before each target in batch mode, regardless of what a previous target left it as.
|
|
655
|
-
cmd._proxyConfigured = globalsUtil.getUseProxy();
|
|
656
666
|
globalsUtil.setDisableCache(cmd.disableCache);
|
|
657
667
|
globalsUtil.setRespCacheFile(cmd.cacheFile);
|
|
658
668
|
globalsUtil.setYes(cmd.yes);
|
|
659
|
-
const
|
|
669
|
+
const outputOverwrite = cmd.outputOverwrite === true;
|
|
670
|
+
const outputReservation = reserveRunOutputDirectory(cmd.output, outputOverwrite);
|
|
671
|
+
const isBatch = resolvedTargets.isBatch;
|
|
672
|
+
const runCommand = Object.freeze(Object.assign(Object.assign({}, cmd), { output: outputReservation.path, _proxyConfigured: globalsUtil.getUseProxy() }));
|
|
673
|
+
if (outputReservation.redirected) {
|
|
674
|
+
console.log(chalk.yellow(`[i] Output directory ${cmd.output} is already occupied; using ${outputReservation.path} instead.`));
|
|
675
|
+
}
|
|
676
|
+
if (outputOverwrite && outputReservation.occupied) {
|
|
677
|
+
console.log(chalk.yellow(`[!] Output directory ${runCommand.output} already exists. Overwriting it.`));
|
|
678
|
+
clearRunOutputDirectory(runCommand.output);
|
|
679
|
+
}
|
|
660
680
|
installSigintHandler(isBatch);
|
|
661
|
-
|
|
681
|
+
let dashboard = null;
|
|
682
|
+
if (cmd.webStatsDashboard) {
|
|
683
|
+
dashboardState.registerTargets(buildDashboardTargetEntries(cmd, isBatch));
|
|
684
|
+
dashboard = yield startDashboardServer(Number(cmd.webStatsPort));
|
|
685
|
+
printMsg(MSG.Run, `[+] Web stats dashboard running at ${dashboard.url}`);
|
|
686
|
+
setHeaderListener((msg) => dashboardState.markStep(msg));
|
|
687
|
+
}
|
|
662
688
|
try {
|
|
663
|
-
// check if the given URL is a file
|
|
664
689
|
if (!isBatch) {
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
if (fs.existsSync(cmd.output)) {
|
|
669
|
-
if (outputOverwrite) {
|
|
670
|
-
console.log(chalk.yellow(`[!] Output directory ${cmd.output} already exists. Overwriting it.`));
|
|
671
|
-
emptyDir(cmd.output);
|
|
672
|
-
}
|
|
673
|
-
else {
|
|
674
|
-
console.error(chalk.red(`[!] Output directory ${cmd.output} already exists. Please switch to other directory or it might conflict with this process.`));
|
|
675
|
-
console.log(chalk.yellow(`[i] For advanced users: use the individual modules separately. See docs at ${CONFIG.modulesDocs}`));
|
|
676
|
-
process.exit(11);
|
|
677
|
-
}
|
|
690
|
+
if (cmd.webStatsDashboard) {
|
|
691
|
+
dashboardState.setCurrentUrl(resolvedTargets.targets[0]);
|
|
692
|
+
dashboardState.markRunning(resolvedTargets.targets[0]);
|
|
678
693
|
}
|
|
679
694
|
try {
|
|
680
|
-
|
|
695
|
+
yield processUrl(resolvedTargets.targets[0], runCommand.output, ".", runCommand, false, (_a = runCommand._includeMethods) !== null && _a !== void 0 ? _a : [], (_b = runCommand._excludeMethods) !== null && _b !== void 0 ? _b : []);
|
|
696
|
+
if (cmd.webStatsDashboard)
|
|
697
|
+
dashboardState.markCompleted(resolvedTargets.targets[0]);
|
|
681
698
|
}
|
|
682
699
|
catch (e) {
|
|
683
|
-
|
|
684
|
-
|
|
700
|
+
if (cmd.webStatsDashboard)
|
|
701
|
+
dashboardState.markError(resolvedTargets.targets[0], e instanceof Error ? e.message : String(e));
|
|
702
|
+
throw e;
|
|
685
703
|
}
|
|
686
|
-
yield processUrl(cmd.url, cmd.output, ".", cmd, false, (_a = cmd._includeMethods) !== null && _a !== void 0 ? _a : [], (_b = cmd._excludeMethods) !== null && _b !== void 0 ? _b : []);
|
|
687
704
|
}
|
|
688
705
|
else {
|
|
689
|
-
|
|
690
|
-
const urls = fs
|
|
691
|
-
.readFileSync(cmd.url, "utf-8")
|
|
692
|
-
.split("\n")
|
|
693
|
-
.filter((url) => url !== "");
|
|
694
|
-
if (!fs.existsSync(cmd.output)) {
|
|
695
|
-
fs.mkdirSync(cmd.output, { recursive: true });
|
|
696
|
-
}
|
|
697
|
-
const globalDbPath = `${cmd.output}/js-recon.db`;
|
|
706
|
+
const globalDbPath = `${runCommand.output}/js-recon.db`;
|
|
698
707
|
yield initGlobalReportDb(globalDbPath);
|
|
699
|
-
|
|
708
|
+
const targetHosts = resolvedTargets.targets.map((target) => new URL(target).host);
|
|
709
|
+
const hostFrequencies = targetHosts.reduce((frequencies, host) => { var _a; return new Map(frequencies).set(host, ((_a = frequencies.get(host)) !== null && _a !== void 0 ? _a : 0) + 1); }, new Map());
|
|
710
|
+
for (const url of resolvedTargets.targets) {
|
|
700
711
|
resetSkipTarget();
|
|
701
|
-
|
|
702
|
-
let urlObj;
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
continue;
|
|
709
|
-
}
|
|
710
|
-
const hostDir = urlObj.host.replace(":", "_");
|
|
711
|
-
const thisTargetDir = `${cmd.output}/${hostDir}`;
|
|
712
|
-
if (fs.existsSync(thisTargetDir) && outputOverwrite) {
|
|
712
|
+
const urlObj = new URL(url);
|
|
713
|
+
let hostDir = getBatchTargetDirectoryName(url, ((_c = hostFrequencies.get(urlObj.host)) !== null && _c !== void 0 ? _c : 0) > 1);
|
|
714
|
+
const requestedTargetDir = path.join(runCommand.output, hostDir);
|
|
715
|
+
const targetReservation = reserveRunOutputDirectory(requestedTargetDir, outputOverwrite);
|
|
716
|
+
const thisTargetDir = targetReservation.path;
|
|
717
|
+
hostDir = path.basename(thisTargetDir);
|
|
718
|
+
if (outputOverwrite && targetReservation.occupied) {
|
|
713
719
|
console.log(chalk.yellow(`[!] Output directory ${thisTargetDir} already exists. Overwriting it.`));
|
|
714
|
-
|
|
720
|
+
clearRunOutputDirectory(thisTargetDir);
|
|
715
721
|
}
|
|
716
|
-
else if (
|
|
717
|
-
console.
|
|
718
|
-
console.log(chalk.yellow(`[i] For advanced users: use the individual modules separately. See docs at ${CONFIG.modulesDocs}`));
|
|
719
|
-
continue;
|
|
722
|
+
else if (targetReservation.redirected) {
|
|
723
|
+
console.log(chalk.yellow(`[i] Target output already exists; using ${thisTargetDir} for ${url}.`));
|
|
720
724
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
catch (error) {
|
|
726
|
-
console.error(chalk.bgRed(`[!] Unhandled error while processing ${url}: ${error}`));
|
|
727
|
-
process.exitCode = 1;
|
|
725
|
+
if (cmd.webStatsDashboard && dashboardState.isSkipRequested(url)) {
|
|
726
|
+
printMsg(MSG.Warn, `[!] Skipping ${url} (skipped from the web dashboard).`);
|
|
727
|
+
dashboardState.markSkipped(url);
|
|
728
|
+
targetReservation.release();
|
|
728
729
|
continue;
|
|
729
730
|
}
|
|
730
|
-
|
|
731
|
-
|
|
731
|
+
if (cmd.webStatsDashboard) {
|
|
732
|
+
dashboardState.setCurrentUrl(url);
|
|
733
|
+
dashboardState.markRunning(url);
|
|
734
|
+
}
|
|
735
|
+
try {
|
|
732
736
|
try {
|
|
733
|
-
|
|
737
|
+
yield processUrl(url, thisTargetDir, thisTargetDir, runCommand, true, (_d = runCommand._includeMethods) !== null && _d !== void 0 ? _d : [], (_e = runCommand._excludeMethods) !== null && _e !== void 0 ? _e : []);
|
|
738
|
+
if (cmd.webStatsDashboard) {
|
|
739
|
+
if (shouldSkipTarget())
|
|
740
|
+
dashboardState.markSkipped(url);
|
|
741
|
+
else
|
|
742
|
+
dashboardState.markCompleted(url);
|
|
743
|
+
}
|
|
734
744
|
}
|
|
735
745
|
catch (error) {
|
|
736
|
-
|
|
746
|
+
if (cmd.webStatsDashboard)
|
|
747
|
+
dashboardState.markError(url, error instanceof Error ? error.message : String(error));
|
|
748
|
+
printMsg(MSG.Err, `[!] Unhandled error while processing ${url}: ${error}`);
|
|
749
|
+
process.exitCode = 1;
|
|
750
|
+
continue;
|
|
751
|
+
}
|
|
752
|
+
const domainDbPath = `${thisTargetDir}/js-recon.db`;
|
|
753
|
+
if (fs.existsSync(domainDbPath)) {
|
|
754
|
+
try {
|
|
755
|
+
mergeDomainIntoGlobalDb(globalDbPath, domainDbPath, hostDir);
|
|
756
|
+
}
|
|
757
|
+
catch (error) {
|
|
758
|
+
printMsg(MSG.Warn, `[!] Failed to merge ${hostDir} into the global js-recon.db: ${error}`);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
else {
|
|
762
|
+
printMsg(MSG.Warn, `[i] No js-recon.db found for ${hostDir}, skipping merge into the global database.`);
|
|
737
763
|
}
|
|
738
764
|
}
|
|
739
|
-
|
|
740
|
-
|
|
765
|
+
finally {
|
|
766
|
+
targetReservation.release();
|
|
741
767
|
}
|
|
742
768
|
}
|
|
743
769
|
}
|
|
744
770
|
}
|
|
745
771
|
catch (error) {
|
|
746
|
-
|
|
772
|
+
printMsg(MSG.Err, `[!] Unhandled error: ${error}`);
|
|
747
773
|
process.exitCode = 1;
|
|
748
774
|
}
|
|
749
775
|
finally {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
776
|
+
if (dashboard) {
|
|
777
|
+
setHeaderListener(null);
|
|
778
|
+
yield dashboard.stop();
|
|
779
|
+
}
|
|
780
|
+
try {
|
|
781
|
+
yield waitForPendingInterrupt();
|
|
782
|
+
}
|
|
783
|
+
finally {
|
|
784
|
+
removeSigintHandler();
|
|
785
|
+
outputReservation.release();
|
|
786
|
+
}
|
|
787
|
+
process.exit((_f = process.exitCode) !== null && _f !== void 0 ? _f : 0);
|
|
753
788
|
}
|
|
754
789
|
});
|
|
755
790
|
//# sourceMappingURL=index.js.map
|