Changelog
This page tracks user-facing changes to js-recon, mirroring the dev-branch CHANGELOG.md in the tool's own repository.
2.0.1-beta.1 - 2026-08-17
Added
- New
nuxt-devtech: detects a Nuxt.js dev server (nuxi dev/npm run dev) as a distinct tech from a productionnuxtbuild, mirroringnext-dev/vue-dev/svelte-dev/react-dev/angular-dev(#194). Nuxt 3/4 (Vite) and Nuxt 2 (webpack) dev-server markers were both confirmed live this round — unlike several sibling*-devwebpack branches.checkNuxtDevServer.tslooks for Nuxt's own/_nuxt/-prefixed Vite client path (/_nuxt/@vite/client, distinct from vanilla Vite's root/@vite/client) plus a weak__NUXT_DEVTOOLS_TIME_METRIC__inline-script signal for Nuxt 3/4, and an unhashed_nuxt/app.jsentry filename plus a/__webpack_hmrintercepted-request pathname for Nuxt 2. The gate is checked only aftercheckNuxtJSmatches, at both the HTML-level check and the intercepted-URL fallback. No dedicated crawler was needed — the existingnuxt_js/*pipeline already handles dev mode once two shared (not dev-specific) bugs were fixed:nuxt_stringAnalysisJSFiles.ts's literal-path scanner previously matched only a bare.jssuffix, missing every cache-busted (?v=<hash>) Vite import and every raw.mjs/.ts/.vuedev-mode source reference; and a malformed/oversized literal (for example, an entire module's source embedded in a webpackeval-devtool string) could throw inside the per-file resolver and permanently block that file from ever being marked analyzed, spinning the discovery loop forever. A third, general bug (affecting every*-devwebpack branch, not just Nuxt's) was also fixed:techDetect/index.tsno longer reads the full response body of an interceptedtext/event-streamconnection (for example, a webpack-hot-middleware HMR socket), which previously hung tech detection indefinitely against any webpack dev server with an open HMR connection.run's tech allow-list and pipeline condition were extended accordingly (Nuxt's map/analyze calls already hardcode"vue"regardless of dev/prod, so no new remap arm was needed). Benchmarked at effectively complete recovery for both Nuxt generations against an independentkatanacrawl (Nuxt 3: 176/177 URLs, the one miss being a Vite-internal-only file never fetched as app content; Nuxt 2: 0 missed, full overlap) and cross-checked with ajsr-network-benchdual-capture pass showing zero real discovery gaps. (lazyload,run)
Fixed
run's generated OpenAPI spec and Postman collection now use the actual target URL instead of a placeholder:openapiGenerator.ts'sservers[].urlandpostmanGenerator.ts'sbaseUrlvariable read a newtargetUrlglobal (src/utility/globals.ts), set from the-uvalue at the start ofprocessUrl, falling back to the previous{{baseUrl}}/https://example.complaceholder if unset.setTargetUrlstripsusername/password/search/hashbefore storing, so a-uvalue carrying basic-auth credentials or a signed query token doesn't leak into the generated artifacts. (run,openapi,postman)- Nuxt 2 dev-server detection (
checkNuxtDevServer.ts) no longer misclassifies a production build asnuxt-dev: the unhashed-entry marker now requires the full/_nuxt/app.jssuffix (was matching anyapp.jsbasename, for example,/assets/app.js), and the webpack-HMR marker requires a complete__webpack_hmrpath segment instead of a bare substring match. techDetect/index.ts's event-stream content-type check is now case-insensitive, so a server returningText/Event-Stream; charset=utf-8(mixed case, with parameters) still gets skipped instead of hanging tech detection on that persistent HMR connection.refactor -t react-webpack's webpack-async-chunk-loading rewrite (requireParam.e(N).then(requireParam.bind(requireParam, N))→ dynamic import) now emits a realImportExpressionnode (t.importExpression) instead of aCallExpressionwith anImport-type callee — the latter is Babel 7's legacy shape and is no longer a valid expression under the@babel/typesv8 migrated in this same release, which silently brokerenameRouteComponents' route-component renaming for any React-Router lazy route using this webpack pattern.- AI SDK clients (
src/utility/ai.ts) are now constructed lazily on first use instead of at module load. Theopenaidependency's v7 line changed itsOpenAIclient constructor to throw immediately when noapiKeyis configured, which crashed every js-recon invocation on import — not just runs that actually use an AI feature (mcp's AI chat,analyze's AI-assisted rule helpers) — for any user who hadn't set an AI API key. The OpenAI, Ollama, and Anthropic clients are now held behind??=-memoized getters and only instantiated the first timeai()resolves a provider, so an unconfigured AI provider is inert until actually selected. (ai) - Migrated
@babel/types,@babel/parser, and@babel/traversefrom v7 to v8 (^8.0.4), dropping the now-stale@types/babel__traversepin that was shipping a duplicate nested v7 type copy. Beyond the mechanical fallout of v8 dropping default exports (namespace imports) and no longer CJS-interop-wrappingtraverse/generator(removing the(_x.default ?? _x)unwrap pattern) across roughly 120 call sites, the upgrade carried one real functional risk that was caught and fixed in the same change: v8's parser now emits a dynamicimport(...)call as anImportExpressionnode directly, rather than the v7 shape (aCallExpressionwith anImport-type callee). Four dynamic-import detection call sites still checked for the old shape —angular_recursiveChunkImports.ts,vue_jsImports.ts,react-vite's andrefactor/react/transform.ts's import-rewriting — and would have silently stopped matching any dynamic import in every affected pipeline had they not been updated to also recognizeImportExpression. Verified with a cleantscbuild, the full unit suite, an end-to-endrunagainst local targets, and arefactor -t react-webpackpass against a real code-split React bundle. (lazyload,map,analyze,refactor,endpoints,strings)
Security
- CI workflow checkouts that don't perform an authenticated git operation (
codeql.yml,plumber.yml,pr_checker.yml, the smoke-test workflows, most jobs inbuild-and-prettify.yaml/promote-js-recon.yml) now setpersist-credentials: false, so the ambientGITHUB_TOKENisn't left in.git/configfor later steps or third-party actions in that job to read.
Fixed
@babel/generator(imported directly bymap'sesqueryinteractive command) is now declared as a directdependenciesentry instead of only being present transitively via@babel/traverse/@babel/core.
2.0.1-alpha.3 - 2026-08-14
Added
- New
vue-dev,react-dev,svelte-dev, andangular-devtechs: each detects a dev server (Vite/webpack-dev-server for Vue and React, always-Vite for SvelteKit, and either the esbuild/Vite or legacy webpack builder for Angular) as a distinct tech from its production build counterpart, mirroring the existingnext-devtech.lazyloadandrunreuse each framework's existing crawler pipeline, with small additive fixes (import-following, filename sanitization, and chunk-map parsing) closing the gaps between dev-server output and production-build output.map/analyzeremap each*-devtech to its production equivalent so existing rules keep working unchanged.
Fixed
lazyload's Svelte/SvelteKit inline-<script type="module">boot-pattern scan now also matches a static ESimport ... from "...js"declaration, in addition to the dynamicimport("...")call form it already handled. Some SvelteKit builds bootstrap the client via a static import instead of a dynamic one; since the entry chunk seeds the entire downstream chunk-discovery graph, missing it caused the whole crawl to collapse to a single JS file even though framework detection succeeded.
Security
- Removed the
extract-zipdependency, which carried a high-severity, unfixed advisory (GHSA-jmr9-qjv8-65gv, unvalidated symlink path traversal on archive extraction) with no patched release available upstream.analyze's rules downloader now fetches thejs-recon-rulesrelease as a tarball and extracts it with the already-depended-on, actively maintainedtarpackage instead.
2.0.1-alpha.2 - 2026-08-12
Fixed
- The response cache is now backed by a single SQLite file (
.resp_cache.db) instead of the previous JSON-based formats.--cache-file's default changed from.resp_cache.jsonto.resp_cache.dbacrosslazyload,run, andload. This is a clean break, not an in-place migration — an existing.resp_cache.json/.entries/directory from a prior version is left untouched but never read again; the first run after upgrading simply starts with an empty cache. load(Caido/Burp import) now writes each imported entry directly into the SQLite cache instead of building one large in-memory JSON object and serializing it in a single write at the end. This also removes the previous "cache too large to serialize as one JSON string" failure mode entirely.lazyload's cache pre-creation step now opens the SQLite cache database up front instead of writing an empty JSON stub; a failure to open it is now a fatal error with a dedicated exit code (32) — see Exit Codes.
Security
- Removed the
fsnpm package from dependencies. It was never referenced by the codebase and sat unused inpackage-lock.jsonas an extraneous entry; thefspackage on npm (distinct from Node's builtin module) is flagged as malicious by OSV (MAL-2025-21003). - Enabled Dependabot version updates for the npm, Docker, and GitHub Actions ecosystems, opening weekly PRs against
devso outdated dependencies surface automatically instead of only being caught at release time.
Added
lazyload/runnow decode inline (base64 or percent-encoded)data:URI sourcemaps found in//# sourceMappingURL=...comments — for example, Vite'sbuild.sourcemap: 'inline'or webpack'sdevtool: 'inline-source-map'/eval-source-map— instead of treating the reference as a fetchable URL and losing the sourcemap entirely. Handled for every framework the crawler supports: React, Vue, and Svelte gained adata:branch; Next.js, Angular, and Nuxt gained sourcemap scanning entirely, where they previously had none.- Release CI now runs a dependency-audit job before publishing to npm, blocking the release if any dependency is a known malicious package.
report.htmlhas a fancier, dark-mode-aware UI: a light/dark theme toggle (defaults to the OS color scheme, persisted vialocalStorage) restyles the navbar, collapsible sections, and the findings/mapped views; severity values render as colored badges.report.htmlno longer depends on any CDN to render correctly, including when opened directly viafile://.- New
-H/--header <name: value>flag for authenticated scanning: repeatable, parses each value asName: Valueand applies it to every outbound request path (direct, SOCKS, HTTP, Oxylabs, AWS, and Puppeteer page loads). Available onlazyload,run, andexploit.