@js-recon/js-recon 1.3.1-beta.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.
- package/.gitattributes +2 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +29 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- package/.github/ISSUE_TEMPLATE/new_tech_support_request.md +26 -0
- package/.github/workflows/build-and-prettify.yaml +121 -0
- package/.github/workflows/pr_checker.yml +22 -0
- package/.github/workflows/publish-js-recon.yml +169 -0
- package/.prettierignore +2 -0
- package/.prettierrc +6 -0
- package/CHANGELOG.md +692 -0
- package/CLAUDE.md +290 -0
- package/Dockerfile +34 -0
- package/LICENSE +21 -0
- package/README.md +101 -0
- package/SECURITY.md +37 -0
- package/build/analyze/engine/astEngine.js +224 -0
- package/build/analyze/engine/astEngine.js.map +1 -0
- package/build/analyze/engine/index.js +59 -0
- package/build/analyze/engine/index.js.map +1 -0
- package/build/analyze/engine/requestEngine.js +100 -0
- package/build/analyze/engine/requestEngine.js.map +1 -0
- package/build/analyze/helpers/engineHelpers/findDirectAssignment.js +37 -0
- package/build/analyze/helpers/engineHelpers/findDirectAssignment.js.map +1 -0
- package/build/analyze/helpers/engineHelpers/findMemberExpressionAssignment.js +29 -0
- package/build/analyze/helpers/engineHelpers/findMemberExpressionAssignment.js.map +1 -0
- package/build/analyze/helpers/engineHelpers/resolveFunctionIdentifier.js +38 -0
- package/build/analyze/helpers/engineHelpers/resolveFunctionIdentifier.js.map +1 -0
- package/build/analyze/helpers/engineHelpers/taintFlow.js +250 -0
- package/build/analyze/helpers/engineHelpers/taintFlow.js.map +1 -0
- package/build/analyze/helpers/initRules.js +111 -0
- package/build/analyze/helpers/initRules.js.map +1 -0
- package/build/analyze/helpers/outputHelper.js +14 -0
- package/build/analyze/helpers/outputHelper.js.map +1 -0
- package/build/analyze/helpers/schemas.js +57 -0
- package/build/analyze/helpers/schemas.js.map +1 -0
- package/build/analyze/helpers/validate.js +89 -0
- package/build/analyze/helpers/validate.js.map +1 -0
- package/build/analyze/index.js +150 -0
- package/build/analyze/index.js.map +1 -0
- package/build/analyze/types/index.js +2 -0
- package/build/analyze/types/index.js.map +1 -0
- package/build/api_gateway/checkFeasibility.js +41 -0
- package/build/api_gateway/checkFeasibility.js.map +1 -0
- package/build/api_gateway/checkFireWallBlocking.js +33 -0
- package/build/api_gateway/checkFireWallBlocking.js.map +1 -0
- package/build/api_gateway/genReq.js +205 -0
- package/build/api_gateway/genReq.js.map +1 -0
- package/build/api_gateway/index.js +291 -0
- package/build/api_gateway/index.js.map +1 -0
- package/build/endpoints/gen_report/gen_json.js +30 -0
- package/build/endpoints/gen_report/gen_json.js.map +1 -0
- package/build/endpoints/gen_report/utility/iterate_n_store.js +64 -0
- package/build/endpoints/gen_report/utility/iterate_n_store.js.map +1 -0
- package/build/endpoints/index.js +101 -0
- package/build/endpoints/index.js.map +1 -0
- package/build/endpoints/next_js/client_jsFilesHref.js +100 -0
- package/build/endpoints/next_js/client_jsFilesHref.js.map +1 -0
- package/build/endpoints/next_js/client_jsonParse.js +89 -0
- package/build/endpoints/next_js/client_jsonParse.js.map +1 -0
- package/build/endpoints/next_js/client_mappedJsonFile.js +103 -0
- package/build/endpoints/next_js/client_mappedJsonFile.js.map +1 -0
- package/build/endpoints/next_js/client_subsequentRequests.js +211 -0
- package/build/endpoints/next_js/client_subsequentRequests.js.map +1 -0
- package/build/fingerprint/index.js +123 -0
- package/build/fingerprint/index.js.map +1 -0
- package/build/globalConfig.js +16 -0
- package/build/globalConfig.js.map +1 -0
- package/build/index.js +332 -0
- package/build/index.js.map +1 -0
- package/build/lazyLoad/angular/angular_getFromMainJs.js +55 -0
- package/build/lazyLoad/angular/angular_getFromMainJs.js.map +1 -0
- package/build/lazyLoad/angular/angular_getFromPageSource.js +43 -0
- package/build/lazyLoad/angular/angular_getFromPageSource.js.map +1 -0
- package/build/lazyLoad/downloadFilesUtil.js +127 -0
- package/build/lazyLoad/downloadFilesUtil.js.map +1 -0
- package/build/lazyLoad/downloadLoadedJsUtil.js +44 -0
- package/build/lazyLoad/downloadLoadedJsUtil.js.map +1 -0
- package/build/lazyLoad/downloadQueue.js +191 -0
- package/build/lazyLoad/downloadQueue.js.map +1 -0
- package/build/lazyLoad/globals.js +107 -0
- package/build/lazyLoad/globals.js.map +1 -0
- package/build/lazyLoad/index.js +377 -0
- package/build/lazyLoad/index.js.map +1 -0
- package/build/lazyLoad/next_js/NextJsCrawler.js +332 -0
- package/build/lazyLoad/next_js/NextJsCrawler.js.map +1 -0
- package/build/lazyLoad/next_js/next_GetJSScript.js +126 -0
- package/build/lazyLoad/next_js/next_GetJSScript.js.map +1 -0
- package/build/lazyLoad/next_js/next_GetLazyResourcesBuildManifestJs.js +83 -0
- package/build/lazyLoad/next_js/next_GetLazyResourcesBuildManifestJs.js.map +1 -0
- package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js +222 -0
- package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js.map +1 -0
- package/build/lazyLoad/next_js/next_SubsequentRequests.js +208 -0
- package/build/lazyLoad/next_js/next_SubsequentRequests.js.map +1 -0
- package/build/lazyLoad/next_js/next_bruteForceJsFiles.js +37 -0
- package/build/lazyLoad/next_js/next_bruteForceJsFiles.js.map +1 -0
- package/build/lazyLoad/next_js/next_buildId.js +55 -0
- package/build/lazyLoad/next_js/next_buildId.js.map +1 -0
- package/build/lazyLoad/next_js/next_getClientSidePaths.js +83 -0
- package/build/lazyLoad/next_js/next_getClientSidePaths.js.map +1 -0
- package/build/lazyLoad/next_js/next_globals.js +8 -0
- package/build/lazyLoad/next_js/next_globals.js.map +1 -0
- package/build/lazyLoad/next_js/next_parseLayoutJs.js +116 -0
- package/build/lazyLoad/next_js/next_parseLayoutJs.js.map +1 -0
- package/build/lazyLoad/next_js/next_promiseResolve.js +85 -0
- package/build/lazyLoad/next_js/next_promiseResolve.js.map +1 -0
- package/build/lazyLoad/next_js/next_scriptTagsSubsequentRequests.js +51 -0
- package/build/lazyLoad/next_js/next_scriptTagsSubsequentRequests.js.map +1 -0
- package/build/lazyLoad/nuxt_js/nuxt_astParse.js +202 -0
- package/build/lazyLoad/nuxt_js/nuxt_astParse.js.map +1 -0
- package/build/lazyLoad/nuxt_js/nuxt_getFromPageSource.js +82 -0
- package/build/lazyLoad/nuxt_js/nuxt_getFromPageSource.js.map +1 -0
- package/build/lazyLoad/nuxt_js/nuxt_stringAnalysisJSFiles.js +108 -0
- package/build/lazyLoad/nuxt_js/nuxt_stringAnalysisJSFiles.js.map +1 -0
- package/build/lazyLoad/react/react_followImports.js +105 -0
- package/build/lazyLoad/react/react_followImports.js.map +1 -0
- package/build/lazyLoad/react/react_getScriptTags.js +52 -0
- package/build/lazyLoad/react/react_getScriptTags.js.map +1 -0
- package/build/lazyLoad/react/react_sourcemapUrls.js +44 -0
- package/build/lazyLoad/react/react_sourcemapUrls.js.map +1 -0
- package/build/lazyLoad/react/react_webpackChunkPaths.js +188 -0
- package/build/lazyLoad/react/react_webpackChunkPaths.js.map +1 -0
- package/build/lazyLoad/sourcemap.js +188 -0
- package/build/lazyLoad/sourcemap.js.map +1 -0
- package/build/lazyLoad/svelte/svelte_discoverPagesFromJs.js +162 -0
- package/build/lazyLoad/svelte/svelte_discoverPagesFromJs.js.map +1 -0
- package/build/lazyLoad/svelte/svelte_getFromPageSource.js +91 -0
- package/build/lazyLoad/svelte/svelte_getFromPageSource.js.map +1 -0
- package/build/lazyLoad/svelte/svelte_recursivePageCrawl.js +180 -0
- package/build/lazyLoad/svelte/svelte_recursivePageCrawl.js.map +1 -0
- package/build/lazyLoad/svelte/svelte_stringAnalysisJSFiles.js +123 -0
- package/build/lazyLoad/svelte/svelte_stringAnalysisJSFiles.js.map +1 -0
- package/build/lazyLoad/techDetect/checkAngularJS.js +70 -0
- package/build/lazyLoad/techDetect/checkAngularJS.js.map +1 -0
- package/build/lazyLoad/techDetect/checkNextJS.js +45 -0
- package/build/lazyLoad/techDetect/checkNextJS.js.map +1 -0
- package/build/lazyLoad/techDetect/checkNuxtJS.js +39 -0
- package/build/lazyLoad/techDetect/checkNuxtJS.js.map +1 -0
- package/build/lazyLoad/techDetect/checkReact.js +86 -0
- package/build/lazyLoad/techDetect/checkReact.js.map +1 -0
- package/build/lazyLoad/techDetect/checkSvelte.js +69 -0
- package/build/lazyLoad/techDetect/checkSvelte.js.map +1 -0
- package/build/lazyLoad/techDetect/checkVueJS.js +118 -0
- package/build/lazyLoad/techDetect/checkVueJS.js.map +1 -0
- package/build/lazyLoad/techDetect/index.js +161 -0
- package/build/lazyLoad/techDetect/index.js.map +1 -0
- package/build/lazyLoad/vue/vue_RuntimeJs.js +169 -0
- package/build/lazyLoad/vue/vue_RuntimeJs.js.map +1 -0
- package/build/lazyLoad/vue/vue_SingleJsFileOnHome.js +102 -0
- package/build/lazyLoad/vue/vue_SingleJsFileOnHome.js.map +1 -0
- package/build/lazyLoad/vue/vue_discoverJsFiles.js +82 -0
- package/build/lazyLoad/vue/vue_discoverJsFiles.js.map +1 -0
- package/build/lazyLoad/vue/vue_getClientSidePaths.js +155 -0
- package/build/lazyLoad/vue/vue_getClientSidePaths.js.map +1 -0
- package/build/lazyLoad/vue/vue_jsImports.js +76 -0
- package/build/lazyLoad/vue/vue_jsImports.js.map +1 -0
- package/build/lazyLoad/vue/vue_pageSrc.js +60 -0
- package/build/lazyLoad/vue/vue_pageSrc.js.map +1 -0
- package/build/lazyLoad/vue/vue_reconstructSourceMaps.js +64 -0
- package/build/lazyLoad/vue/vue_reconstructSourceMaps.js.map +1 -0
- package/build/lazyLoad/vue/vue_recursiveClientSidePathDownload.js +142 -0
- package/build/lazyLoad/vue/vue_recursiveClientSidePathDownload.js.map +1 -0
- package/build/lazyLoad/vue/vue_severalJsFilesHome.js +57 -0
- package/build/lazyLoad/vue/vue_severalJsFilesHome.js.map +1 -0
- package/build/lazyLoad/vue/vue_sourcemapExtract.js +166 -0
- package/build/lazyLoad/vue/vue_sourcemapExtract.js.map +1 -0
- package/build/lazyLoad/vue/vue_stringJsFiles.js +148 -0
- package/build/lazyLoad/vue/vue_stringJsFiles.js.map +1 -0
- package/build/lazyLoad/vue/vue_viteMapDeps.js +89 -0
- package/build/lazyLoad/vue/vue_viteMapDeps.js.map +1 -0
- package/build/load/index.js +316 -0
- package/build/load/index.js.map +1 -0
- package/build/map/graphql/resolveGraphql.js +296 -0
- package/build/map/graphql/resolveGraphql.js.map +1 -0
- package/build/map/index.js +261 -0
- package/build/map/index.js.map +1 -0
- package/build/map/next_js/getAxiosInstances.js +64 -0
- package/build/map/next_js/getAxiosInstances.js.map +1 -0
- package/build/map/next_js/getExports.js +101 -0
- package/build/map/next_js/getExports.js.map +1 -0
- package/build/map/next_js/getFetchInstances.js +139 -0
- package/build/map/next_js/getFetchInstances.js.map +1 -0
- package/build/map/next_js/getTurbopackConnections.js +255 -0
- package/build/map/next_js/getTurbopackConnections.js.map +1 -0
- package/build/map/next_js/getWebpackConnections.js +235 -0
- package/build/map/next_js/getWebpackConnections.js.map +1 -0
- package/build/map/next_js/interactive.js +69 -0
- package/build/map/next_js/interactive.js.map +1 -0
- package/build/map/next_js/interactive_helpers/commandHandler.js +310 -0
- package/build/map/next_js/interactive_helpers/commandHandler.js.map +1 -0
- package/build/map/next_js/interactive_helpers/commandHelpers.js +245 -0
- package/build/map/next_js/interactive_helpers/commandHelpers.js.map +1 -0
- package/build/map/next_js/interactive_helpers/esqueryGen.js +370 -0
- package/build/map/next_js/interactive_helpers/esqueryGen.js.map +1 -0
- package/build/map/next_js/interactive_helpers/helpMenu.js +12 -0
- package/build/map/next_js/interactive_helpers/helpMenu.js.map +1 -0
- package/build/map/next_js/interactive_helpers/inputPatch.js +207 -0
- package/build/map/next_js/interactive_helpers/inputPatch.js.map +1 -0
- package/build/map/next_js/interactive_helpers/keybindings.js +90 -0
- package/build/map/next_js/interactive_helpers/keybindings.js.map +1 -0
- package/build/map/next_js/interactive_helpers/printer.js +23 -0
- package/build/map/next_js/interactive_helpers/printer.js.map +1 -0
- package/build/map/next_js/interactive_helpers/ui.js +88 -0
- package/build/map/next_js/interactive_helpers/ui.js.map +1 -0
- package/build/map/next_js/resolveAxios.js +152 -0
- package/build/map/next_js/resolveAxios.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/astNodeToJsonString.js +64 -0
- package/build/map/next_js/resolveAxiosHelpers/astNodeToJsonString.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/directCallsWithoutAssignment.js +48 -0
- package/build/map/next_js/resolveAxiosHelpers/directCallsWithoutAssignment.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/findAxiosClients.js +34 -0
- package/build/map/next_js/resolveAxiosHelpers/findAxiosClients.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/findAxiosInstance.js +39 -0
- package/build/map/next_js/resolveAxiosHelpers/findAxiosInstance.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/findCrossChunkParams.js +312 -0
- package/build/map/next_js/resolveAxiosHelpers/findCrossChunkParams.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/handleAxiosCreate.js +173 -0
- package/build/map/next_js/resolveAxiosHelpers/handleAxiosCreate.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/handleZDotCreate.js +261 -0
- package/build/map/next_js/resolveAxiosHelpers/handleZDotCreate.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/interceptorHeaders.js +206 -0
- package/build/map/next_js/resolveAxiosHelpers/interceptorHeaders.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/processAxiosCall.js +168 -0
- package/build/map/next_js/resolveAxiosHelpers/processAxiosCall.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/processDirectAxiosCall.js +121 -0
- package/build/map/next_js/resolveAxiosHelpers/processDirectAxiosCall.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/processExportedEndpoints.js +274 -0
- package/build/map/next_js/resolveAxiosHelpers/processExportedEndpoints.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/traceAxiosInstanceExports.js +518 -0
- package/build/map/next_js/resolveAxiosHelpers/traceAxiosInstanceExports.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/traceBody.js +913 -0
- package/build/map/next_js/resolveAxiosHelpers/traceBody.js.map +1 -0
- package/build/map/next_js/resolveFetch.js +533 -0
- package/build/map/next_js/resolveFetch.js.map +1 -0
- package/build/map/next_js/resolveNewRequest.js +749 -0
- package/build/map/next_js/resolveNewRequest.js.map +1 -0
- package/build/map/next_js/resolveServerActions.js +449 -0
- package/build/map/next_js/resolveServerActions.js.map +1 -0
- package/build/map/next_js/utils.js +1600 -0
- package/build/map/next_js/utils.js.map +1 -0
- package/build/map/react_js/getReactConnections.js +303 -0
- package/build/map/react_js/getReactConnections.js.map +1 -0
- package/build/map/react_js/interactive.js +4 -0
- package/build/map/react_js/interactive.js.map +1 -0
- package/build/map/react_js/react_resolveFetch.js +6 -0
- package/build/map/react_js/react_resolveFetch.js.map +1 -0
- package/build/map/svelte_js/interactive.js +58 -0
- package/build/map/svelte_js/interactive.js.map +1 -0
- package/build/map/svelte_js/interactive_helpers/commandHandler.js +4 -0
- package/build/map/svelte_js/interactive_helpers/commandHandler.js.map +1 -0
- package/build/map/vue_js/bodyResolver.js +477 -0
- package/build/map/vue_js/bodyResolver.js.map +1 -0
- package/build/map/vue_js/crossFileResolver.js +438 -0
- package/build/map/vue_js/crossFileResolver.js.map +1 -0
- package/build/map/vue_js/getViteConnections.js +343 -0
- package/build/map/vue_js/getViteConnections.js.map +1 -0
- package/build/map/vue_js/interactive.js +67 -0
- package/build/map/vue_js/interactive.js.map +1 -0
- package/build/map/vue_js/interactive_helpers/commandHandler.js +307 -0
- package/build/map/vue_js/interactive_helpers/commandHandler.js.map +1 -0
- package/build/map/vue_js/interactive_helpers/commandHelpers.js +39 -0
- package/build/map/vue_js/interactive_helpers/commandHelpers.js.map +1 -0
- package/build/map/vue_js/interactive_helpers/helpMenu.js +12 -0
- package/build/map/vue_js/interactive_helpers/helpMenu.js.map +1 -0
- package/build/map/vue_js/taint_utils.js +621 -0
- package/build/map/vue_js/taint_utils.js.map +1 -0
- package/build/map/vue_js/vue_resolveFetch.js +416 -0
- package/build/map/vue_js/vue_resolveFetch.js.map +1 -0
- package/build/map/vue_js/vue_resolveHttpClient.js +738 -0
- package/build/map/vue_js/vue_resolveHttpClient.js.map +1 -0
- package/build/map/vue_js/vue_resolveXhr.js +282 -0
- package/build/map/vue_js/vue_resolveXhr.js.map +1 -0
- package/build/mcp/chatOneShot.js +101 -0
- package/build/mcp/chatOneShot.js.map +1 -0
- package/build/mcp/claudeCodeCreds.js +150 -0
- package/build/mcp/claudeCodeCreds.js.map +1 -0
- package/build/mcp/cli.js +372 -0
- package/build/mcp/cli.js.map +1 -0
- package/build/mcp/commands.js +227 -0
- package/build/mcp/commands.js.map +1 -0
- package/build/mcp/config.js +68 -0
- package/build/mcp/config.js.map +1 -0
- package/build/mcp/index.js +50 -0
- package/build/mcp/index.js.map +1 -0
- package/build/mcp/intent.js +204 -0
- package/build/mcp/intent.js.map +1 -0
- package/build/mcp/jobs.js +199 -0
- package/build/mcp/jobs.js.map +1 -0
- package/build/mcp/mcpServer.js +241 -0
- package/build/mcp/mcpServer.js.map +1 -0
- package/build/mcp/providers.js +170 -0
- package/build/mcp/providers.js.map +1 -0
- package/build/mcp/skills.js +115 -0
- package/build/mcp/skills.js.map +1 -0
- package/build/mcp/tools.js +185 -0
- package/build/mcp/tools.js.map +1 -0
- package/build/refactor/index.js +85 -0
- package/build/refactor/index.js.map +1 -0
- package/build/refactor/next/index.js +109 -0
- package/build/refactor/next/index.js.map +1 -0
- package/build/refactor/react/index.js +636 -0
- package/build/refactor/react/index.js.map +1 -0
- package/build/report/index.js +68 -0
- package/build/report/index.js.map +1 -0
- package/build/report/utility/dataTables/genDataTablesPage.js +158 -0
- package/build/report/utility/dataTables/genDataTablesPage.js.map +1 -0
- package/build/report/utility/genHtml.js +516 -0
- package/build/report/utility/genHtml.js.map +1 -0
- package/build/report/utility/initReportDb.js +96 -0
- package/build/report/utility/initReportDb.js.map +1 -0
- package/build/report/utility/markdownGen/addAnalyze.js +53 -0
- package/build/report/utility/markdownGen/addAnalyze.js.map +1 -0
- package/build/report/utility/markdownGen/addMappedJson.js +33 -0
- package/build/report/utility/markdownGen/addMappedJson.js.map +1 -0
- package/build/report/utility/populateDb/populateAnalysisFindings.js +31 -0
- package/build/report/utility/populateDb/populateAnalysisFindings.js.map +1 -0
- package/build/report/utility/populateDb/populateEndpoints.js +50 -0
- package/build/report/utility/populateDb/populateEndpoints.js.map +1 -0
- package/build/report/utility/populateDb/populateMappedJson.js +31 -0
- package/build/report/utility/populateDb/populateMappedJson.js.map +1 -0
- package/build/report/utility/populateDb/populateMappedOpenapi.js +49 -0
- package/build/report/utility/populateDb/populateMappedOpenapi.js.map +1 -0
- package/build/run/index.js +446 -0
- package/build/run/index.js.map +1 -0
- package/build/run/interruptHandler.js +93 -0
- package/build/run/interruptHandler.js.map +1 -0
- package/build/strings/index.js +239 -0
- package/build/strings/index.js.map +1 -0
- package/build/strings/openapi.js +63 -0
- package/build/strings/openapi.js.map +1 -0
- package/build/strings/permutate.js +62 -0
- package/build/strings/permutate.js.map +1 -0
- package/build/strings/secrets.js +102 -0
- package/build/strings/secrets.js.map +1 -0
- package/build/utility/ai.js +97 -0
- package/build/utility/ai.js.map +1 -0
- package/build/utility/configureSandbox.js +14 -0
- package/build/utility/configureSandbox.js.map +1 -0
- package/build/utility/globals.js +322 -0
- package/build/utility/globals.js.map +1 -0
- package/build/utility/interfaces.js +2 -0
- package/build/utility/interfaces.js.map +1 -0
- package/build/utility/makeReq.js +448 -0
- package/build/utility/makeReq.js.map +1 -0
- package/build/utility/openapiGenerator.js +254 -0
- package/build/utility/openapiGenerator.js.map +1 -0
- package/build/utility/postmanGenerator.js +216 -0
- package/build/utility/postmanGenerator.js.map +1 -0
- package/build/utility/progressLog.js +50 -0
- package/build/utility/progressLog.js.map +1 -0
- package/build/utility/puppeteerInstance.js +5 -0
- package/build/utility/puppeteerInstance.js.map +1 -0
- package/build/utility/replaceUrlPlaceholders.js +48 -0
- package/build/utility/replaceUrlPlaceholders.js.map +1 -0
- package/build/utility/resolvePath.js +44 -0
- package/build/utility/resolvePath.js.map +1 -0
- package/build/utility/runSandboxed.js +42 -0
- package/build/utility/runSandboxed.js.map +1 -0
- package/build/utility/urlUtils.js +21 -0
- package/build/utility/urlUtils.js.map +1 -0
- package/contributing/nextjs.md +410 -0
- package/package.json +75 -0
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# js-recon
|
|
2
|
+
|
|
3
|
+
Static analysis tool that maps API endpoints and detects client-side security issues by analyzing Next.js (webpack/turbopack) and Vue.js bundles. Written in TypeScript, compiled to `build/` before running.
|
|
4
|
+
|
|
5
|
+
## Build & run
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm run cleanup # rm -rf build/ + tsc (full rebuild)
|
|
9
|
+
npm run start -- <subcommand> [options]
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
`cleanup` must be run before testing any TypeScript change when using the `run` command.
|
|
13
|
+
|
|
14
|
+
## Subcommands
|
|
15
|
+
|
|
16
|
+
| Command | Purpose |
|
|
17
|
+
| ------------- | ---------------------------------------------------------------------------------- |
|
|
18
|
+
| `lazyload` | Download JS chunks from a target URL |
|
|
19
|
+
| `strings` | Extract strings/paths/secrets from JS files |
|
|
20
|
+
| `map` | Parse webpack/turbopack bundles into a structured `mapped.json` |
|
|
21
|
+
| `endpoints` | Extract client-side routes |
|
|
22
|
+
| `analyze` | Run YAML rules against `mapped.json` / OpenAPI spec |
|
|
23
|
+
| `report` | Generate HTML/SQLite report |
|
|
24
|
+
| `run` | Run all of the above in sequence (primary interface) |
|
|
25
|
+
| `api-gateway` | Manage AWS API Gateway for IP rotation |
|
|
26
|
+
| `mcp` | AI-powered CLI / one-shot chat (`-c`) / Model Context Protocol server (`--server`) |
|
|
27
|
+
|
|
28
|
+
## Key source files
|
|
29
|
+
|
|
30
|
+
- `src/index.ts` — CLI entry point; all subcommand definitions and option declarations live here
|
|
31
|
+
- `src/run/index.ts` — orchestrates the full pipeline (`run` subcommand); two tech-specific flows (Next.js 8-step, Vue 4-step)
|
|
32
|
+
- `src/analyze/index.ts` — loads/validates rules, runs AST and request engines
|
|
33
|
+
- `src/analyze/helpers/initRules.ts` — downloads/caches rules from GitHub to `~/.js-recon/rules`
|
|
34
|
+
- `src/analyze/helpers/validate.ts` — validates rules and checks `js_recon_version` compatibility
|
|
35
|
+
- `src/analyze/helpers/schemas.ts` — Zod schema for rule YAML files
|
|
36
|
+
- `src/map/graphql/resolveGraphql.ts` — framework-agnostic GraphQL operation scanner. Visits every `StringLiteral` and `TemplateLiteral` in every JS file, validates with the `graphql` library's `parse()`, and emits each operation as a POST request under a flat `GraphQL` collection folder. Inlines transitively-referenced fragment definitions into each printed query so emitted requests are self-contained. Runs in every framework branch of `map/index.ts` when `--openapi` is on and `--no-graphql`/`--ngql` is not set.
|
|
37
|
+
- `src/map/next_js/resolveFetch.ts` — resolves `fetch()` calls, detects Next.js framework chunks
|
|
38
|
+
- `src/map/next_js/resolveServerActions.ts` — detects `createServerReference(actionId, ...)` calls, derives App Router routes from chunk file paths, traces argument call sites (same-chunk and cross-chunk), and emits POST endpoints with `next-action` headers and typed arg hints (e.g. `<string:userId>`) into the global OpenAPI output
|
|
39
|
+
- `src/map/next_js/utils.ts` — `resolveNodeValue`, `resolveVariableInChunk`, `substituteVariablesInString`
|
|
40
|
+
- `src/map/vue_js/vue_resolveXhr.ts` — directory-scan resolver for `new XMLHttpRequest()` + `.open()/.setRequestHeader()/.send()` patterns. Shared by Vue/React/Svelte pipelines; the `frameworkName` arg only changes log labels. Reaches ground-truth XHR sites but in axios/Got/Ky-style bundles the URL/method come from a dispatcher config (`re.url`, `re.method`) and resolve only to opaque `[member:re.url]` placeholders that taint analysis cannot unwind across the library's internal dispatch chain — those entries fail the `looksLikeUrl` check at emit time. Catch the wrapper-level call instead via `vue_resolveHttpClient`.
|
|
41
|
+
- `src/map/vue_js/vue_resolveHttpClient.ts` — directory-scan resolver for `<obj>.<verb>(<url>, [body], [config])` calls where `<verb>` ∈ {get,post,put,delete,patch,head,options}. Designed for bundles whose transport layer overrides `XMLHttpRequest.prototype.{open,send,setRequestHeader}` (axios xhrAdapter and similar wrappers): the override layer is irrelevant to URL extraction because the literal URL is composed at the client-instance method call site, not inside the adapter. The `looksLikeUrl` heuristic (post-placeholder-strip, must contain `/` or scheme) filters out `Map.get` / `Headers.delete` / `EventBus.post` false positives while keeping partially-resolved URLs like `[call:base()]<literal>/[var X]`. Three resolution stages run on every captured callsite — each addresses a separate gap exposed when an RPC wrapper is hidden behind multiple layers of webpack-exported helpers:
|
|
42
|
+
1. `resolveFromAssignments` — walks `binding.constantViolations` for `[unresolved: NAME]` markers, so identifiers declared as `let X;` and assigned later in the function body (e.g. `(X = a + "/" + b)` inside a sequence expression) resolve to their RHS. `resolveNodeValue`'s Identifier handler only looks at `binding.init`, which is empty for late-assigned locals.
|
|
43
|
+
2. `expandParamPlaceholders` — fans out one captured callsite into one URL per caller chain. Walks the `enclosingFn.parent` chain to find which named function declares each `[param:X]`, then substitutes **every** placeholder owned by that same function from a single caller's args (keeps `[param:e]`/`[param:t]` consistent across one caller — never mixing args from different callsites). Recurses on the caller's `enclosingFn` so a forwarding wrapper (`Se(e,t,n) → ae.request(e,t,n,...)`) walks up to the wrapper's own callers.
|
|
44
|
+
3. Taint substitution falls back to `substituteCallerPlaceholders` / `substituteCallerHeaders` for body/header placeholders that don't have multi-caller fan-out semantics.
|
|
45
|
+
|
|
46
|
+
Wired into Vue / React / Svelte pipelines in `map/index.ts`.
|
|
47
|
+
|
|
48
|
+
- `src/map/vue_js/taint_utils.ts` — shared taint analysis primitives. Several pieces are non-obvious and exist to make `vue_resolveHttpClient` (and `vue_resolveXhr`) work on webpack output:
|
|
49
|
+
- `EnclosingFn.paramNames` + `parent` chain: `resolveNodeValue` emits `[param:X]` for any param at any index in any enclosing function. The chain lets the helpers resolve such a marker against whichever enclosing scope actually declared X — bundled code routinely nests the resolution callsite inside an anonymous `.then(function ($) {…})` whose own params don't include X, while X is a param of an outer named function.
|
|
50
|
+
- `buildAliasMap`: collects `{ exportedName: localBinding }` and `{ exportedName: () => localBinding }` patterns from object literals on a **per-file** basis. Webpack's `a.d(b, { name: () => Binding })` getter exports and re-export registries (`const ae = { request: Me }`) hide the local minifier name behind a meaningful key; without this map, `getCallers("Me")` would miss every `ae.request(...)` / `r.default.request(...)` callsite. **The map must be file-scoped** — minifier locals (`Se`, `Me`) collide across modules, and a global alias map blends unrelated functions into the same name set.
|
|
51
|
+
- `makeGetCallers` accepts an optional `sourceFile` argument so callers can scope alias lookup to the file where the binding was declared. Direct minifier-local matches (`bindingName.length ≤ 2`) are dropped from the candidate list because they generate too many false positives across files; meaningful aliases (length > 2) are kept and used for both bare-identifier (`X(...)`) and member-expression (`<anything>.X(...)`) callsite matching. Overflow returns the partial caller list rather than nothing — the file-scoped alias map already suppresses noise, so partial coverage beats none.
|
|
52
|
+
- `src/map/next_js/getWebpackConnections.ts` — extracts chunk code from webpack bundles
|
|
53
|
+
- `src/map/next_js/interactive_helpers/esqueryGen.ts` — `esquery` interactive command: minifies a pasted snippet, matches it against each chunk's minified AST nodes, prints loose/strict selectors. Vue's command handler imports the same module — keep it framework-agnostic.
|
|
54
|
+
- `src/map/next_js/interactive.ts` / `src/map/vue_js/interactive.ts` — export both the blessed-backed `interactive()` entry and a headless `runCommands(chunks, mapFile, commands)` that pipes `outputBox.log` to stdout for `-c/--command` execution.
|
|
55
|
+
- `src/map/next_js/interactive_helpers/inputPatch.ts` — `enableCursorInput(inputBox)` patches a blessed textbox instance to support cursor movement, mid-string insertion, and paste-at-cursor. It overrides `_listener`/`setValue`/`_updateCursor`/`clearValue` on the instance. **Don't try to remove blessed's listener after the fact** — blessed re-binds `this._listener` on every focus, so overriding `_listener` on the instance is the only race-free approach. Shared by Next.js and Vue interactive entries.
|
|
56
|
+
- `src/globalConfig.ts` — current version string and tool-wide constants
|
|
57
|
+
- `src/utility/globals.ts` — mutable global state (tech detection result, AI config, OpenAPI flag, etc.)
|
|
58
|
+
|
|
59
|
+
## `run` pipeline in detail
|
|
60
|
+
|
|
61
|
+
`run` is the primary subcommand. It calls `processUrl` for each target, which dispatches to one of two pipelines based on the detected front-end framework (`globalsUtil.getTech()`).
|
|
62
|
+
|
|
63
|
+
### Next.js pipeline (8 steps)
|
|
64
|
+
|
|
65
|
+
1. **Lazyload** — downloads initial JS chunks via Puppeteer; detects framework; sets `globalsUtil.getTech()` to `"next"`
|
|
66
|
+
2. **Strings** — scans downloaded JS for strings, extracts URL paths → `extracted_urls.json`
|
|
67
|
+
3. **Lazyload (subsequent requests)** — re-crawls using the extracted paths to fetch dynamically loaded chunks; also fetches `buildId`
|
|
68
|
+
4. **Strings (pass 2)** — re-runs strings on the expanded chunk set; generates `extracted_urls.txt` (permuted) and `extracted_urls-openapi.json`; optionally scans secrets (`--secrets`)
|
|
69
|
+
5. **Lazyload re-pass (step 4.5)** — a second subsequent-requests crawl to pick up chunks for dynamic routes discovered in pass 2
|
|
70
|
+
6. **Strings re-pass (step 4.6)** — strings pass over the re-pass chunks
|
|
71
|
+
7. **Map** — parses webpack/turbopack bundles; resolves `fetch()` calls and axios usage; generates `mapped.json` and `mapped-openapi.json`; CDN-aware: if JS was served from a different host, `getCdnDir` finds the CDN output dir and passes that to map instead of `outputDir/host`
|
|
72
|
+
8. **Endpoints** — extracts client-side route paths; uses `___subsequent_requests` directory presence to decide whether to pass a JS directory
|
|
73
|
+
9. **Analyze** — loads YAML rules (from `-r/--rules` if provided, otherwise default rules cache); runs AST engine and request engine; writes `analyze.json`
|
|
74
|
+
10. **Report** — populates SQLite DB (`js-recon.db`) and generates HTML report
|
|
75
|
+
|
|
76
|
+
### Vue.js pipeline (4 steps)
|
|
77
|
+
|
|
78
|
+
1. **Lazyload** — same as Next.js step 1; sets `globalsUtil.getTech()` to `"vue"`
|
|
79
|
+
2. **Map** — scans the entire `outputDir` (Vue chunks spread across asset hosts)
|
|
80
|
+
3. **Analyze** — same rule loading as Next.js; `-r/--rules` is forwarded here too
|
|
81
|
+
4. **Report** — same as Next.js; if `endpoints.json` doesn't exist it is written as `[]` since Vue endpoints extraction isn't implemented yet
|
|
82
|
+
|
|
83
|
+
### Tech detection flow
|
|
84
|
+
|
|
85
|
+
`lazyLoad` sets the global tech string. If it remains `""` after lazyload, `run` exits (single URL) or skips (batch). Techs other than `"next"` and `"vue"` only get lazyload; the rest of the pipeline is skipped with a warning.
|
|
86
|
+
|
|
87
|
+
### Batch mode
|
|
88
|
+
|
|
89
|
+
When `-u` points to a file of URLs, each line is processed sequentially. For each URL:
|
|
90
|
+
|
|
91
|
+
- A subdirectory `output/<host>/` is created
|
|
92
|
+
- `clearJsUrls()` / `clearJsonUrls()` reset the URL sets so previous targets don't bleed over
|
|
93
|
+
- All output paths are prefixed with `workingDir/`
|
|
94
|
+
|
|
95
|
+
## Adding a new flag to `run`
|
|
96
|
+
|
|
97
|
+
1. Declare the option in `src/index.ts` on the `run` command (`.option(...)`)
|
|
98
|
+
2. If it configures a global, call the setter in the `action` handler before `await run(cmd)`
|
|
99
|
+
3. If it needs to reach a downstream module (like `analyze`), thread it through `cmd` — `processUrl` receives the full `cmd` object and passes it to submodule calls
|
|
100
|
+
|
|
101
|
+
**Example — `-r/--rules` flag (added in this codebase):**
|
|
102
|
+
|
|
103
|
+
- Declared in `src/index.ts`: `.option("-r, --rules <file/dir>", "Rules file or directory (passed to analyze module)")`
|
|
104
|
+
- In `src/run/index.ts` the `analyze` calls use `cmd.rules || ""` — empty string tells `analyze` to use the default rules cache
|
|
105
|
+
|
|
106
|
+
**Example — `--lazyload-timeout` flag:**
|
|
107
|
+
|
|
108
|
+
- Declared in `src/index.ts` on both the `lazyload` and `run` commands: `.option("--lazyload-timeout <minutes>", ..., "30")`
|
|
109
|
+
- Threaded directly into each `lazyLoad()` call as `Number(cmd.lazyloadTimeout) * 60 * 1000` (converts minutes → ms). Unlike flags that set a global, this one is passed as a parameter — no setter in the action handler.
|
|
110
|
+
|
|
111
|
+
## Interactive-mode commands
|
|
112
|
+
|
|
113
|
+
The `map -i` blessed UI dispatches user input through `interactive_helpers/commandHandler.ts`. The same handler runs headlessly when commands are supplied via `-c/--command`:
|
|
114
|
+
|
|
115
|
+
- The `-c` option's commander coerce function splits each value on `&&` (with optional whitespace) and concatenates into a single command array. So `-c "list fetch && esquery * fetch"` is two commands; passing `-c` twice has the same effect.
|
|
116
|
+
- `map`'s entry point checks `commands.length > 0` first — if non-empty, it calls `nextRunCommands` / `vueRunCommands` and skips the blessed UI even when `-i` is also set.
|
|
117
|
+
- New commands should be added to **both** `next_js/interactive_helpers/commandHandler.ts` and `vue_js/interactive_helpers/commandHandler.ts`, plus the corresponding `helpMenu.ts` entry. When the implementation is framework-agnostic (e.g. `esquery`), put it under `next_js/interactive_helpers/` and import it from the Vue handler — don't duplicate.
|
|
118
|
+
- `list server_actions` is intentionally Next.js-only (it reads from `getOpenapiOutput()` filtered by `next-action` header) and has no Vue counterpart.
|
|
119
|
+
|
|
120
|
+
## Reversing RPC-style API calls from manual browser observations
|
|
121
|
+
|
|
122
|
+
When the user supplies a call-stack screenshot or notes from a real session ("XHR sent here, sink is this prototype override, body comes from this function"), the goal isn't to reproduce that exact target — it's to find the _generic pattern_ that the bundler emitted and add resolver support for it. The reverse-engineering workflow that produced the HTTP-client resolver:
|
|
123
|
+
|
|
124
|
+
1. **Read the call stack bottom-up.** The deepest frame is almost always the transport (`XMLHttpRequest.send`, `fetch`); ignore it. The next frames going up are the HTTP library (axios's `_request` / `dispatchXhrRequest`); ignore those too unless the URL is literal at that level. Look for the first frame whose source line contains _a recognisable path fragment or template string_ — that's the wrapper callsite worth resolving.
|
|
125
|
+
2. **Identify the URL composition site.** Open the file at that frame in the downloaded bundle (`output/<host>/static/js/<chunk>.js`) and find the literal. Typical webpack patterns are `client.post(base + "literal/path/" + paramVar, body, config)` or `client.request({ url: base + "/" + paramVar, method: "POST" })`. Note what's a literal, what's a parameter, what's a local variable.
|
|
126
|
+
3. **Walk inward from the wrapper.** For every non-literal in the URL, find where it came from in the same function. If it's a `let X;` followed by `X = a + "/" + b` in a sequence expression, that's `resolveFromAssignments`' territory. If it's a function parameter, that's taint analysis' territory.
|
|
127
|
+
4. **Walk outward from the wrapper.** Look at the callers of the enclosing function. In webpack bundles the function is usually exported through one of:
|
|
128
|
+
- A registry object: `const ae = { request: Me, postUnchecked: Se }` — callsites read `ae.request(...)`, NOT `Me(...)`.
|
|
129
|
+
- A webpack getter export: `a.d(b, { request: () => Me })` — same effect, different shape.
|
|
130
|
+
- Both. The same binding often appears in multiple aliases.
|
|
131
|
+
|
|
132
|
+
Both shapes are recognised by `buildAliasMap` in `taint_utils.ts` and _must be matched per file_ — minifier locals like `Se`, `Me` collide across modules.
|
|
133
|
+
|
|
134
|
+
5. **Trace forwarding wrappers all the way out.** A wrapper like `Se(e, t, n) → ae.request(e, t, n, ...)` just forwards its parameters. After substituting at the wrapper level, recurse into Se's own callers; the externally-meaningful arguments (`s.signIn.namespace`) are several layers up.
|
|
135
|
+
6. **Confirm the literal source.** The outermost caller passes a `MemberExpression` like `s.signIn.namespace`. Find the `const s = { signIn: { namespace: "...", method: "..." } }` declaration — `resolveNodeValue` handles this naturally as long as the binding is in scope at the caller's location.
|
|
136
|
+
|
|
137
|
+
If at any layer the new resolver returns `[unresolved: X]` or `[param:X]`, that's a signal which primitive is missing — extend `taint_utils.ts` (chain walk, per-file aliases, member-expression matching, late-assignment recovery) rather than special-casing the wrapper. The goal is a primitive that resolves _similar_ RPC-style libraries in unrelated apps, not the one bundle in front of you.
|
|
138
|
+
|
|
139
|
+
**Do not encode target-specific paths or service names in code or comments.** When iterating, run `map` against the downloaded chunks and grep the resulting `mapped-openapi.json` for the expected URL fragment — never paste that fragment into source.
|
|
140
|
+
|
|
141
|
+
### How to test changes here
|
|
142
|
+
|
|
143
|
+
The HTTP-client resolver runs inside the `map` step of the React/Vue/Svelte pipeline; verify it as part of the full `run` pipeline (see "Testing a change" below). Quick iteration loop while debugging:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
npx tsc
|
|
147
|
+
node --max-old-space-size=8192 build/index.js map \
|
|
148
|
+
-d output/<host>/static/js -o /tmp/jsr-mapped -t react -f json \
|
|
149
|
+
2>&1 | grep "URL: " | sort -u
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
This bypasses the slow `lazyload` step by reusing already-downloaded chunks. The final acceptance test is still `npm run cleanup && npm run start -- run -u <target> -y -k`; grep `mapped-openapi.json` for the expected resolved URL fragment.
|
|
153
|
+
|
|
154
|
+
## Rules
|
|
155
|
+
|
|
156
|
+
Rules are YAML files (`.yml`/`.yaml`) in two places:
|
|
157
|
+
|
|
158
|
+
- **Workspace:** `../js-recon-rules/` (relative to this repo)
|
|
159
|
+
- **Installed cache:** `~/.js-recon/rules`
|
|
160
|
+
|
|
161
|
+
`initRules` downloads rules from GitHub when missing or when the cached version doesn't match the latest release. `js_recon_version` (required) must be declared in every rule (e.g. `js_recon_version: ">=X.Y.Z"`); `initRules` uses it to validate compatibility and skips incompatible rules with a warning. The version check strips prerelease suffixes (e.g. `1.3.1-alpha.3` → `[1,3,1]`).
|
|
162
|
+
|
|
163
|
+
Rule categories:
|
|
164
|
+
|
|
165
|
+
- `ast/` — AST-based pattern matching against chunk code (uses `@babel/parser` + `esquery`)
|
|
166
|
+
- `request/` — OpenAPI/request-level checks against the resolved endpoint list
|
|
167
|
+
|
|
168
|
+
When `-r` points to a single file, only that rule is loaded. When it points to a directory, all `.yml`/`.yaml` files are loaded recursively.
|
|
169
|
+
|
|
170
|
+
## Testing a change
|
|
171
|
+
|
|
172
|
+
**Testing is mandatory for every change.** Before reporting a task complete:
|
|
173
|
+
|
|
174
|
+
1. Run `npm run cleanup` to rebuild TypeScript.
|
|
175
|
+
2. Run the `run` subcommand against the target the user provides. Do not use `analyze` or other individual subcommands as a substitute — the `run` subcommand must be used to validate end-to-end behavior.
|
|
176
|
+
3. If the user has not provided a target, ask for one before proceeding.
|
|
177
|
+
|
|
178
|
+
Typical test invocation:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
npm run cleanup && npm run start -- run -u <target-url> -y -k
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Release process
|
|
185
|
+
|
|
186
|
+
Releasing a new version touches three repos. Work on `dev` (js-recon, js-recon-rules) and `stage` (js-recon-docs). Do **not** touch `js-recon-research` — it is private and excluded from releases.
|
|
187
|
+
|
|
188
|
+
**Ordering is critical**: release js-recon first (including the GitHub release so CI publishes it to npm), then snapshot and PR js-recon-docs. This ensures the docs `version_check` CI step passes instead of failing due to a missing npm package.
|
|
189
|
+
|
|
190
|
+
### When a user asks to prepare a release
|
|
191
|
+
|
|
192
|
+
Before writing any files, gather the current state:
|
|
193
|
+
|
|
194
|
+
1. Check `package.json` and `src/globalConfig.ts` for the current version — both must match. If they don't, fix them first.
|
|
195
|
+
2. Find the latest git tag: `git describe --tags --abbrev=0`
|
|
196
|
+
3. List unreleased commits: `git log <latest-tag>..HEAD --oneline | grep -E "^[a-f0-9]+ (feat|fix)"`
|
|
197
|
+
4. Check if `CHANGELOG.md` already has an `(unreleased)` entry for the current version — if so, only the date needs to be added.
|
|
198
|
+
5. Check `js-recon-rules` for unreleased commits since its last tag: `git -C ../js-recon-rules log $(git -C ../js-recon-rules describe --tags --abbrev=0)..HEAD --oneline`
|
|
199
|
+
6. Check `js-recon-docs` for commits since the last version snapshot: `git -C ../js-recon-docs log --oneline -20`
|
|
200
|
+
|
|
201
|
+
### Phase 1 — js-recon (release first)
|
|
202
|
+
|
|
203
|
+
1. **Bump version** (if not already at the target version) — update `version` in `src/globalConfig.ts` and `package.json`. Both must match.
|
|
204
|
+
|
|
205
|
+
2. **Update CHANGELOG** — if the version heading already exists as `(unreleased)`, replace it with the real date (`## <version> - <YYYY-MM-DD>`). Otherwise add the full section with `### Fixed`, `### Performance`, `### Added`, `### Changed` sub-sections. Verify every `feat`/`fix` commit since the previous tag is covered:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
git log <prev-tag>..HEAD --oneline | grep -E "^[a-f0-9]+ (feat|fix)"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
3. **Update README** — ensure the Commands table in `README.md` lists every subcommand declared in `src/index.ts`. The `refactor` and `load` subcommands are easy to miss — explicitly verify they are present.
|
|
212
|
+
|
|
213
|
+
4. **Update rules** (`js-recon-rules` repo, `dev` branch) — if there are substantive unreleased commits (not just merge/cleanup commits), update `CHANGELOG.md` and `version.txt`, push to `dev`, and open a PR (`shriyanss/js-recon-rules` dev→main, title=rules version, body=rules changelog section).
|
|
214
|
+
|
|
215
|
+
5. **Push** `js-recon` dev branch: `git push origin dev`
|
|
216
|
+
|
|
217
|
+
6. **Open PR** using `gh pr create`:
|
|
218
|
+
| Repo | Source | Target | Title | Body |
|
|
219
|
+
|------|--------|--------|-------|------|
|
|
220
|
+
| `shriyanss/js-recon` | `dev` | `main` | bare version string (e.g. `v1.3.1-alpha.4`) | raw `## <version>` changelog section |
|
|
221
|
+
|
|
222
|
+
7. **Monitor js-recon CI** — use `gh pr checks <pr-number> --repo shriyanss/js-recon` and poll until all checks complete. Handle CodeRabbit suggestions (see below). Do NOT merge — wait for user approval.
|
|
223
|
+
|
|
224
|
+
8. **Create GitHub release** — after the PR is merged to main:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
gh release create v<version> \
|
|
228
|
+
--repo shriyanss/js-recon \
|
|
229
|
+
--title "v<version>" \
|
|
230
|
+
--notes "<changelog section>" \
|
|
231
|
+
--prerelease # set for any version containing "alpha" or "beta"
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
`--latest` flag rules:
|
|
235
|
+
- **Omit** `--latest` if the version contains `alpha` or `beta`
|
|
236
|
+
- **Add** `--latest` only for stable releases (no pre-release suffix in the version string)
|
|
237
|
+
|
|
238
|
+
Previous tag is left to GitHub's automatic detection (do not set `--target` or `--tag` beyond the tag name itself).
|
|
239
|
+
|
|
240
|
+
9. **Wait for npm publish** — monitor the release pipeline: `gh run list --repo shriyanss/js-recon --workflow release`. Confirm the npm package is live at the new version before proceeding to Phase 2.
|
|
241
|
+
|
|
242
|
+
### Phase 2 — js-recon-docs (after npm is live)
|
|
243
|
+
|
|
244
|
+
10. **Fix doc gaps** — cross-check `docs/docs/modules/*.md` against `src/index.ts` and the new CHANGELOG entries. Add or update any missing flags, options, or command descriptions.
|
|
245
|
+
|
|
246
|
+
11. **Snapshot** — run inside `js-recon-docs/`:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
npx docusaurus docs:version <version>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
This creates `versioned_docs/version-<version>/`, updates `versions.json`, and creates `versioned_sidebars/version-<version>-sidebars.json`.
|
|
253
|
+
|
|
254
|
+
12. **Keep `lastVersion` stable** — `lastVersion` in `docusaurus.config.ts` stays pointing to the last stable release. Do **not** update it for alpha or beta versions.
|
|
255
|
+
|
|
256
|
+
13. **Push** `js-recon-docs` stage branch and open PR:
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
git -C ../js-recon-docs add .
|
|
260
|
+
git -C ../js-recon-docs commit -m "docs: snapshot v<version>"
|
|
261
|
+
git -C ../js-recon-docs push origin stage
|
|
262
|
+
gh pr create --repo shriyanss/js-recon-docs \
|
|
263
|
+
--head stage --base main \
|
|
264
|
+
--title "v<version>" \
|
|
265
|
+
--body "<brief summary of doc changes>"
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
14. **Monitor docs CI** — `version_check` should pass now that the npm package is live. CodeRabbit rate-limit comments are non-blocking.
|
|
269
|
+
|
|
270
|
+
### Handling CodeRabbit
|
|
271
|
+
|
|
272
|
+
After any PR is created, poll for review comments:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
gh api repos/shriyanss/js-recon/pulls/<pr>/comments
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
For each suggestion: apply a fix commit to `dev` for correctness bugs or convention violations. Skip trivial style preferences. The PR updates automatically.
|
|
279
|
+
|
|
280
|
+
### Stop before merge
|
|
281
|
+
|
|
282
|
+
Do NOT merge any PR. Once all CI checks pass and CodeRabbit suggestions are addressed, present a summary to the user: what changed in each repo, PR links, CI status, CodeRabbit disposition. Wait for explicit merge approval.
|
|
283
|
+
|
|
284
|
+
## Security / confidentiality
|
|
285
|
+
|
|
286
|
+
When a change is informed by behavior observed on a real target (URLs, endpoint names, response shapes, finding details, etc.):
|
|
287
|
+
|
|
288
|
+
- **Do not include any target information in code comments, commit messages, docstrings, variable names, or any other artifact.**
|
|
289
|
+
- This applies to hostnames, paths, parameter names, response content, or any other detail that could identify the target.
|
|
290
|
+
- If context from the target is needed to describe a change, describe it in abstract terms only (e.g. "URL parameter passed to fetch" not "https://example.com/api/docs passes `file` param to fetch").
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
FROM ghcr.io/puppeteer/puppeteer:24.43.1
|
|
2
|
+
|
|
3
|
+
WORKDIR /home/pptruser
|
|
4
|
+
|
|
5
|
+
# selectively copy the source files
|
|
6
|
+
COPY ./package.json .
|
|
7
|
+
COPY ./package-lock.json .
|
|
8
|
+
COPY ./tsconfig.json .
|
|
9
|
+
COPY ./src ./src
|
|
10
|
+
|
|
11
|
+
USER root
|
|
12
|
+
ENV PUPPETEER_SKIP_DOWNLOAD=true
|
|
13
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
14
|
+
unzip \
|
|
15
|
+
libnspr4 libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 \
|
|
16
|
+
libxcomposite1 libxdamage1 libxrandr2 libgbm1 libxkbcommon0 \
|
|
17
|
+
libasound2 libpangocairo-1.0-0 libxfixes3 libxi6 libxinerama1 \
|
|
18
|
+
libxcursor1 libdrm2 && \
|
|
19
|
+
rm -rf /var/lib/apt/lists/*
|
|
20
|
+
RUN npm ci
|
|
21
|
+
RUN npm run build
|
|
22
|
+
|
|
23
|
+
USER pptruser
|
|
24
|
+
RUN ./node_modules/.bin/puppeteer browsers install chrome && \
|
|
25
|
+
for zip in /home/pptruser/.cache/puppeteer/chrome/*-chrome-linux64.zip; do \
|
|
26
|
+
[ -f "$zip" ] || break; \
|
|
27
|
+
version="${zip%-chrome-linux64.zip}"; version="${version##*/}"; \
|
|
28
|
+
dest="/home/pptruser/.cache/puppeteer/chrome/linux-${version}"; \
|
|
29
|
+
unzip -o "$zip" -d "${dest}/" && chmod +x "${dest}/chrome-linux64/chrome"; \
|
|
30
|
+
done
|
|
31
|
+
|
|
32
|
+
ENV IS_DOCKER=true
|
|
33
|
+
ENV NODE_OPTIONS="--max-http-header-size=99999999"
|
|
34
|
+
ENTRYPOINT ["node", "build/index.js"]
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Shriyans Sudhi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# JS Recon
|
|
2
|
+
|
|
3
|
+
     
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://js-recon.io">
|
|
7
|
+
<img src="https://js-recon.io/img/js-recon-logo.png" alt="JS Recon Logo" width="100">
|
|
8
|
+
</a>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
A powerful tool for JavaScript reconnaissance. `js-recon` helps you discover, download, and analyze JavaScript files to uncover endpoints, secrets, and other valuable information from any web application running supported frameworks.
|
|
12
|
+
|
|
13
|
+
It can also reconstruct HTTP requests that the app makes to the server, and output them to the OpenAPI spec.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
This tool requires Node.JS and `npm` to be installed. The [official download page](https://nodejs.org/en/download) can be referred. Please install **22.17.0 (LTS)** or later. Downloading older versions might break the tool.
|
|
18
|
+
|
|
19
|
+
To install the tool globally, run:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm i -g @shriyanss/js-recon
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
For detailed installation and setup process, please refer to the [Installation page](https://js-recon.io/docs/docs/installation)
|
|
26
|
+
|
|
27
|
+
## Framework Support
|
|
28
|
+
|
|
29
|
+
The features in JS Recon tool are built after thorough research on apps running different frameworks.
|
|
30
|
+
|
|
31
|
+
Please refer to the [Framework Support](https://js-recon.io/docs/docs/framework-support) page for detailed information on feature compatibility across different frameworks.
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Get a list of all commands
|
|
37
|
+
js-recon --help
|
|
38
|
+
|
|
39
|
+
# Get help for a specific command
|
|
40
|
+
js-recon <command> --help
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
To launch a quick assesment against a target, the `run` module can be used to automate other modules
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
js-recon run -u https://app.example.com
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Commands
|
|
50
|
+
|
|
51
|
+
`js-recon` provides a suite of commands for comprehensive JavaScript analysis. For detailed usage and examples, please refer to its full documentation.
|
|
52
|
+
|
|
53
|
+
| Command | Description | Documentation |
|
|
54
|
+
| ------------- | ----------------------------------------------------------------------------- | -------------------------------------------------------------- |
|
|
55
|
+
| `lazyload` | Downloads dynamically loaded JavaScript files from a target. | [Read Docs](https://js-recon.io/docs/docs/modules/lazyload) |
|
|
56
|
+
| `endpoints` | Extracts API endpoints and client-side paths from JS files. | [Read Docs](https://js-recon.io/docs/docs/modules/endpoints) |
|
|
57
|
+
| `strings` | Extracts strings, URLs, and potential secrets from JS files. | [Read Docs](https://js-recon.io/docs/docs/modules/strings) |
|
|
58
|
+
| `map` | Maps function calls and analyzes code, with optional AI-powered descriptions. | [Read Docs](https://js-recon.io/docs/docs/modules/map) |
|
|
59
|
+
| `api-gateway` | Manages AWS API Gateway for IP rotation to bypass rate limits. | [Read Docs](https://js-recon.io/docs/docs/modules/api-gateway) |
|
|
60
|
+
| `run` | Runs all analysis modules automatically on a target. | [Read Docs](https://js-recon.io/docs/docs/modules/run) |
|
|
61
|
+
| `analyze` | Analyzes the code. | [Read Docs](https://js-recon.io/docs/docs/modules/analyze) |
|
|
62
|
+
| `report` | Generates a report from the analysis modules. | [Read Docs](https://js-recon.io/docs/docs/modules/report) |
|
|
63
|
+
| `mcp` | AI-powered interactive CLI, one-shot chat, and MCP stdio server. | [Read Docs](https://js-recon.io/docs/docs/modules/mcp) |
|
|
64
|
+
| `fingerprint` | Detects the JavaScript framework used by a target URL (JSON/JSONL output). | [Read Docs](https://js-recon.io/docs/docs/modules/fingerprint) |
|
|
65
|
+
| `refactor` | Refactors and deobfuscates webpack modules from a mapped JSON file. | [Read Docs](https://js-recon.io/docs/docs/modules/refactor) |
|
|
66
|
+
| `load` | Populates the response cache from a Caido or Burp Suite export. | [Read Docs](https://js-recon.io/docs/docs/modules/load) |
|
|
67
|
+
|
|
68
|
+
## Key Features
|
|
69
|
+
|
|
70
|
+
- Downloads all dynamically loaded JS files (refered as `lazyload`) from website with supported frameworks
|
|
71
|
+
- Use API gateway to rotate IP addresses to bypass firewall
|
|
72
|
+
- Extract strings from the discovered JS files, and extract potential secrets, endpoints, etc. from them
|
|
73
|
+
- Endpoints modules extracts client-side paths from the app
|
|
74
|
+
- Map feature analyzes the JS files and outputs it to a JSON file. An interactive mode can be then used to analyze it
|
|
75
|
+
- Reconstruct HTTP requests that the app makes to the server, and output them to the OpenAPI spec
|
|
76
|
+
- Run analyze to find potential issues in JS code and the HTTP requests the app makes
|
|
77
|
+
- Generate a report from the analyze module
|
|
78
|
+
|
|
79
|
+
## Example Scenario
|
|
80
|
+
|
|
81
|
+
Refer to [this page](https://js-recon.io/docs/docs/example-scenarios/next-js) where an example scenario of running this tool against a Next.JS target is demonstrated.
|
|
82
|
+
|
|
83
|
+
## Documentation
|
|
84
|
+
|
|
85
|
+
For detailed guides, command options, and advanced usage examples, please check out the JS Recon Site at https://js-recon.io
|
|
86
|
+
|
|
87
|
+
## Labs
|
|
88
|
+
|
|
89
|
+
<p align="center">
|
|
90
|
+
<img src="https://github.com/shriyanss/js-recon-labs/blob/main/static/labs-banner.png?raw=true" alt="JS Recon Labs" width="300"/>
|
|
91
|
+
</p>
|
|
92
|
+
|
|
93
|
+
Labs to test JS Recon tool are available [here](https://github.com/shriyanss/js-recon-labs). Walkthroughs are available [here](https://js-recon.io/labs).
|
|
94
|
+
|
|
95
|
+
## Contributing
|
|
96
|
+
|
|
97
|
+
Please refer to the [Contributing](https://js-recon.io/contributing) page for detailed information on contributing to this project.
|
|
98
|
+
|
|
99
|
+
## License
|
|
100
|
+
|
|
101
|
+
JS Recon is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
The three most recent versions receive security fixes. Older versions are unsupported.
|
|
6
|
+
|
|
7
|
+
## Reporting a Vulnerability
|
|
8
|
+
|
|
9
|
+
Please **do not** open a public GitHub issue for security vulnerabilities.
|
|
10
|
+
|
|
11
|
+
Report vulnerabilities by emailing: **shriyanss@ss0x00.com**
|
|
12
|
+
|
|
13
|
+
Include in your report:
|
|
14
|
+
|
|
15
|
+
- Description of the vulnerability and its potential impact
|
|
16
|
+
- Steps to reproduce or a proof-of-concept
|
|
17
|
+
- Affected version(s)
|
|
18
|
+
- Any suggested mitigations, if known
|
|
19
|
+
|
|
20
|
+
You can expect an acknowledgement within **72 hours**. If a vulnerability is confirmed, a fix will be prioritized based on severity.
|
|
21
|
+
|
|
22
|
+
## Scope
|
|
23
|
+
|
|
24
|
+
js-recon is a security research tool. Reports are in scope if they affect:
|
|
25
|
+
|
|
26
|
+
- The js-recon CLI itself (arbitrary code execution, path traversal, unsafe deserialization, etc.)
|
|
27
|
+
- The Docker container image
|
|
28
|
+
- Dependencies with known CVEs that affect js-recon's attack surface
|
|
29
|
+
|
|
30
|
+
Out of scope:
|
|
31
|
+
|
|
32
|
+
- Vulnerabilities in targets analyzed by js-recon (that is the intended use case, not a bug)
|
|
33
|
+
- Issues requiring physical access or social engineering of the operator
|
|
34
|
+
|
|
35
|
+
## Disclosure Policy
|
|
36
|
+
|
|
37
|
+
Once a fix is available, coordinated public disclosure is preferred. Please allow reasonable time (up to 90 days) for a patch to be released before public disclosure.
|