@js-recon/js-recon 1.4.2 → 1.4.4
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/.github/workflows/build-and-prettify.yaml +6 -6
- package/.github/workflows/rules-smoke-test.yaml +2 -2
- package/CHANGELOG.md +30 -0
- package/Dockerfile +13 -2
- package/Dockerfile.release +12 -2
- package/Dockerfile.w-rules +0 -1
- package/README.md +52 -0
- package/build/analyze/helpers/initRules.js +34 -16
- package/build/analyze/helpers/initRules.js.map +1 -1
- package/build/completion/index.js +44 -3
- package/build/completion/index.js.map +1 -1
- package/build/config/applicationConfig.js +493 -0
- package/build/config/applicationConfig.js.map +1 -0
- package/build/fingerprint/index.js +8 -19
- package/build/fingerprint/index.js.map +1 -1
- package/build/globalConfig.js +1 -1
- package/build/index.js +62 -9
- package/build/index.js.map +1 -1
- package/build/lazyLoad/downloadFilesUtil.js +40 -32
- package/build/lazyLoad/downloadFilesUtil.js.map +1 -1
- package/build/lazyLoad/downloadQueue.js +150 -50
- package/build/lazyLoad/downloadQueue.js.map +1 -1
- package/build/lazyLoad/downloadResponse.js +112 -0
- package/build/lazyLoad/downloadResponse.js.map +1 -0
- package/build/lazyLoad/globals.js +4 -0
- package/build/lazyLoad/globals.js.map +1 -1
- package/build/lazyLoad/index.js +188 -115
- package/build/lazyLoad/index.js.map +1 -1
- package/build/lazyLoad/next_js/NextJsCrawler.js +3 -2
- package/build/lazyLoad/next_js/NextJsCrawler.js.map +1 -1
- package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js +8 -9
- package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js.map +1 -1
- package/build/lazyLoad/next_js/next_SubsequentRequests.js +93 -93
- package/build/lazyLoad/next_js/next_SubsequentRequests.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 +2 -1
- package/build/lazyLoad/react/react_webpackChunkPaths.js.map +1 -1
- package/build/lazyLoad/techDetect/index.js +93 -59
- 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 +8 -3
- package/build/lazyLoad/vue/vue_SingleJsFileOnHome.js.map +1 -1
- package/build/lazyLoad/vue/vue_discoverJsFiles.js +10 -9
- package/build/lazyLoad/vue/vue_discoverJsFiles.js.map +1 -1
- package/build/lazyLoad/vue/vue_getClientSidePaths.js +69 -45
- 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 +2 -1
- package/build/lazyLoad/vue/vue_pageSrc.js.map +1 -1
- package/build/lazyLoad/vue/vue_reconstructSourceMaps.js +4 -3
- package/build/lazyLoad/vue/vue_reconstructSourceMaps.js.map +1 -1
- package/build/lazyLoad/vue/vue_recursiveClientSidePathDownload.js +9 -20
- package/build/lazyLoad/vue/vue_recursiveClientSidePathDownload.js.map +1 -1
- package/build/lazyLoad/vue/vue_severalJsFilesHome.js +2 -1
- 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/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 +203 -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/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/run/cancellableStep.js +27 -0
- package/build/run/cancellableStep.js.map +1 -0
- package/build/run/index.js +80 -85
- package/build/run/index.js.map +1 -1
- package/build/run/outputDirectory.js +377 -0
- package/build/run/outputDirectory.js.map +1 -0
- package/build/sourcemaps/index.js +109 -23
- package/build/sourcemaps/index.js.map +1 -1
- package/build/strings/index.js +12 -5
- package/build/strings/index.js.map +1 -1
- package/build/utility/downloadProgress.js +99 -0
- package/build/utility/downloadProgress.js.map +1 -0
- package/build/utility/makeReq.js +490 -257
- package/build/utility/makeReq.js.map +1 -1
- package/build/utility/progressLog.js +64 -4
- package/build/utility/progressLog.js.map +1 -1
- 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/docker-entrypoint.sh +16 -0
- package/package.json +2 -2
|
@@ -218,14 +218,14 @@ jobs:
|
|
|
218
218
|
docker rm js-recon-run
|
|
219
219
|
|
|
220
220
|
- name: Verify all rules fired
|
|
221
|
-
run: node scripts/smoke-test.js
|
|
221
|
+
run: node scripts/smoke-test.js "$(find output -name analyze.json | head -n1)"
|
|
222
222
|
|
|
223
223
|
- name: Upload analyze.json on failure
|
|
224
224
|
if: failure()
|
|
225
225
|
uses: actions/upload-artifact@v4
|
|
226
226
|
with:
|
|
227
227
|
name: analyze-json-docker
|
|
228
|
-
path: output
|
|
228
|
+
path: output/**/analyze.json
|
|
229
229
|
if-no-files-found: ignore
|
|
230
230
|
|
|
231
231
|
- name: Build the rules-bundled (-w-rules) image
|
|
@@ -252,14 +252,14 @@ jobs:
|
|
|
252
252
|
}
|
|
253
253
|
|
|
254
254
|
- name: Verify all rules fired (w-rules image)
|
|
255
|
-
run: node scripts/smoke-test.js output-w-rules
|
|
255
|
+
run: node scripts/smoke-test.js "$(find output-w-rules -name analyze.json | head -n1)"
|
|
256
256
|
|
|
257
257
|
- name: Upload w-rules analyze.json on failure
|
|
258
258
|
if: failure()
|
|
259
259
|
uses: actions/upload-artifact@v4
|
|
260
260
|
with:
|
|
261
261
|
name: analyze-json-docker-w-rules
|
|
262
|
-
path: output-w-rules
|
|
262
|
+
path: output-w-rules/**/analyze.json
|
|
263
263
|
if-no-files-found: ignore
|
|
264
264
|
|
|
265
265
|
integration-test-macos:
|
|
@@ -343,12 +343,12 @@ jobs:
|
|
|
343
343
|
PUPPETEER_EXECUTABLE_PATH: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
|
|
344
344
|
|
|
345
345
|
- name: Verify all rules fired
|
|
346
|
-
run: node scripts/smoke-test.js
|
|
346
|
+
run: node scripts/smoke-test.js "$(find output -name analyze.json | head -n1)"
|
|
347
347
|
|
|
348
348
|
- name: Upload analyze.json on failure
|
|
349
349
|
if: failure()
|
|
350
350
|
uses: actions/upload-artifact@v4
|
|
351
351
|
with:
|
|
352
352
|
name: analyze-json-macos
|
|
353
|
-
path: output
|
|
353
|
+
path: output/**/analyze.json
|
|
354
354
|
if-no-files-found: ignore
|
|
@@ -68,12 +68,12 @@ jobs:
|
|
|
68
68
|
PUPPETEER_EXECUTABLE_PATH: /usr/bin/google-chrome-stable
|
|
69
69
|
|
|
70
70
|
- name: Verify all rules fired
|
|
71
|
-
run: node scripts/smoke-test.js
|
|
71
|
+
run: node scripts/smoke-test.js "$(find output -name analyze.json | head -n1)"
|
|
72
72
|
|
|
73
73
|
- name: Upload analyze.json on failure
|
|
74
74
|
if: failure()
|
|
75
75
|
uses: actions/upload-artifact@v4
|
|
76
76
|
with:
|
|
77
77
|
name: analyze-json
|
|
78
|
-
path: output
|
|
78
|
+
path: output/**/analyze.json
|
|
79
79
|
if-no-files-found: ignore
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 1.4.4 - 2026-08-03
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `run`, `lazyload`, `fingerprint`: `-u/--url` now accepts one URL, the flag repeated multiple times, a comma-separated list of URLs, or a target file (previously a single URL or a single target file). Precedence across environment variable, CLI flag, and YAML config is preserved for all forms. (`run`, `lazyload`, `fingerprint`)
|
|
8
|
+
- `run`: output directory handling is now non-destructive by default. An existing **empty** output directory is reused; an existing **non-empty** one is left untouched and js-recon allocates the next available sibling (`output-2`, `output-3`, ...) instead. `--output-overwrite` is now scoped to canonical, js-recon-owned directories — it rejects symlinked or otherwise protected paths rather than overwriting them. Concurrent runs targeting the same output coordinate via PID/host-aware atomic locks with stale-owner recovery and signal cleanup, so simultaneous invocations no longer race on the same directory. (`run`)
|
|
9
|
+
- Added application-level YAML configuration. On first use, js-recon creates `~/.config/js-recon/config.yaml` (restrictive permissions) with a key for every command option; an alternate file can be selected with the new top-level `--config <file>` flag (before the subcommand) or `JS_RECON_CONFIG`. Values resolve as environment variable → CLI flag → YAML config → built-in default, using `JS_RECON_<COMMAND>_<OPTION>` for any command option (e.g. `JS_RECON_RUN_THREADS=8`). Targets can also be configured as a YAML list under `commands.<command>.url`; an env value or CLI `-u` replaces the whole list per the usual precedence. See `config.dist.yaml` for the full schema. The existing command-specific `proxy --config` / `mcp --config` flags are unaffected — place the application-level `--config` before the subcommand to avoid ambiguity. (`config`, `run`, `lazyload`, `fingerprint`)
|
|
10
|
+
- `run`/`lazyload`: added opt-in Oxylabs recovery for strongly corroborated CDN/WAF blocks, enabled via the new `--oxylabs-waf-fallback` flag once `oxylabs.username`/`oxylabs.password` are set in an explicitly selected YAML config (`JS_RECON_OXYLABS_USERNAME`/`_PASSWORD`/`_COUNTRY` override the YAML values unless `--ignore-proxy-env` is set). Direct requests remain the default path; Oxylabs is only used after direct header-based strategies are exhausted, bounded by new `--oxylabs-fallback-max-requests` (default `10`, per origin), `--oxylabs-fallback-max-total` (default `100`, per run), and `--oxylabs-fallback-max-origins` (default `25`, per run) flags. (`run`, `lazyload`, `proxy`)
|
|
11
|
+
- React/webpack chunk downloads now show a responsive, TTY-aware aggregate progress bar; piped/CI output stays compact with no per-file error spam. Download/response/formatting/write failures are tracked independently and cooperative cancellation is honored throughout discovery, requests, browser fallback, cache access, and post-processing. URL host/path/filename sanitization is now centralized to prevent malformed JS-expression paths, queries, ports, IPv6 hosts, traversal attempts, or hostile source-map entries from escaping or overwriting output boundaries. (`lazyload`, `run`)
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- `run`: batch mode (`-u <target-file>`) aborted the entire run if any single line in the target file was malformed, even when other lines were valid targets that appeared before it — no output was produced at all. A malformed line is now logged with a `[!]` warning and skipped; the rest of the file's valid targets are still processed. The run only fails outright if the target file contains zero valid targets. (`run`)
|
|
16
|
+
- `checkFireWallBlocking` (used by `proxy --feasibility` and the AWS API Gateway request path in `makeReq.ts`) hardcoded a fake `503` status and never passed real response headers to `detectBlockedResponse`'s CDN-header-corroborated detection path, so a genuine `403` "Access Denied" WAF/CDN block (e.g. a real Cloudflare `cf-ray` header) was silently missed even though the underlying detector correctly flags it when given real inputs. `checkFireWallBlocking` now accepts the real HTTP status and headers at all three call sites; when they genuinely aren't available, the status-corroborated detection path is skipped rather than spoofed against the wrong status. (`proxy`)
|
|
17
|
+
- `strings`: the main per-file parse loop had no `try/catch`, unlike the `___subsequent_requests` branch a few lines above (and unlike `sourcemaps`/`cs-mast`). A single malformed or truncated `.js` file among otherwise-valid files threw an uncaught `SyntaxError` and aborted the entire strings extraction with no output at all — including for the `run` pipeline's steps 2/4/4.6. Unparseable files are now skipped with a warning instead of crashing the run. (`strings`, `run`)
|
|
18
|
+
- `run`: requesting `-o <path>` where `<path>` already exists as a regular file (not a directory) silently fell through to the output-reservation retry loop and created `<path>-2` instead of reporting the problem, unless `--output-overwrite` was passed — with `--output-overwrite` it already errored correctly, but without it (the default) there was no indication the requested path wasn't a directory at all. A file at the output path is now rejected outright regardless of `--output-overwrite`. (`run`)
|
|
19
|
+
- `lazyload`/`run`: the output-directory host-nesting heuristic (used to avoid double-nesting a batch target's already-host-owned per-target directory) was applied unconditionally at every call site instead of only the batch per-target root it was written for. A single-target `-o <dir>` run whose directory basename happened to match the sanitized target host silently collapsed the output layout instead of nesting under `<dir>/<host>/...`. The heuristic is now gated behind an explicit batch-only flag threaded through lazyload/crawler/download-queue internals, so single-target runs always nest correctly. (`lazyload`, `run`)
|
|
20
|
+
- `proxy`: the AWS API Gateway resource path (`resourcePathPart`) mixed a per-call random UUID into its hash, so it was never the same twice for the same URL — the existing-resource reuse lookup could never match a previously-provisioned resource, and every proxied request via the `aws` proxy method created a brand-new API Gateway resource instead of reusing one. It's now derived from the URL alone (still SHA-256) so resource reuse works across repeat requests to the same URL. (`proxy`)
|
|
21
|
+
|
|
22
|
+
## 1.4.3 - 2026-07-30
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- `run`: added an `--output-overwrite` flag (also settable via the `JS_RECON_OUTPUT_OVERWRITE=true` environment variable) that overwrites the output directory instead of erroring out when it already exists, in both single-URL and batch mode. This was needed for Docker usage: a bind-mounted `output/` directory always pre-exists from the mount itself, so `run` inside a container previously failed immediately. Both `Dockerfile` and `Dockerfile.release` now set `JS_RECON_OUTPUT_OVERWRITE=true` and pre-create `output/` by default. (`run`, `docker`)
|
|
27
|
+
- `docker`: the official images now start as root and drop to the unprivileged `pptruser` at runtime via a new `docker-entrypoint.sh`, after `chown`-ing the bind-mounted output directory. Previously, a bind-mounted `output/` directory created by Docker (or Kubernetes) with host/root ownership was unwritable by the container's non-root user, causing the pipeline to fail before processing any target. This makes `docker run -v $(pwd)/output:/home/pptruser/output ...` work out of the box regardless of who owns the directory on the host, with no manual `chown` step required. `HOME` is now pinned to `/home/pptruser` so path resolution (Puppeteer's Chrome cache, the rules cache, etc.) stays consistent whether a process runs as root or as `pptruser` — needed for invocations that bypass the entrypoint via `--entrypoint`. (`docker`)
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- `run`: batch mode (`-u <file>`) could fail silently with no output and exit code 0 if an unhandled error occurred before or during target iteration (e.g. an unwritable output directory). The error is now printed and the process exits with a non-zero code. (`run`)
|
|
32
|
+
|
|
3
33
|
## 1.4.2 - 2026-07-29
|
|
4
34
|
|
|
5
35
|
### Fixed
|
package/Dockerfile
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
FROM ghcr.io/puppeteer/puppeteer:24.43.1
|
|
2
2
|
|
|
3
3
|
WORKDIR /home/pptruser
|
|
4
|
+
# Pin HOME so path resolution (Puppeteer's Chrome cache, ~/.js-recon rules cache, etc.)
|
|
5
|
+
# is consistent regardless of which OS user actually executes the process -- root
|
|
6
|
+
# (docker-entrypoint.sh, or any --entrypoint override that bypasses it) or pptruser.
|
|
7
|
+
ENV HOME=/home/pptruser
|
|
4
8
|
|
|
5
9
|
# selectively copy the source files
|
|
6
10
|
COPY ./package.json .
|
|
7
11
|
COPY ./package-lock.json .
|
|
8
12
|
COPY ./tsconfig.json .
|
|
13
|
+
COPY ./patches ./patches
|
|
9
14
|
COPY ./src ./src
|
|
10
15
|
|
|
11
16
|
USER root
|
|
12
17
|
ENV PUPPETEER_SKIP_DOWNLOAD=true
|
|
13
18
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
14
|
-
unzip \
|
|
19
|
+
unzip gosu \
|
|
15
20
|
libnspr4 libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 \
|
|
16
21
|
libxcomposite1 libxdamage1 libxrandr2 libgbm1 libxkbcommon0 \
|
|
17
22
|
libasound2 libpangocairo-1.0-0 libxfixes3 libxi6 libxinerama1 \
|
|
@@ -28,7 +33,13 @@ RUN ./node_modules/.bin/puppeteer browsers install chrome && \
|
|
|
28
33
|
dest="/home/pptruser/.cache/puppeteer/chrome/linux-${version}"; \
|
|
29
34
|
unzip -o "$zip" -d "${dest}/" && chmod +x "${dest}/chrome-linux64/chrome"; \
|
|
30
35
|
done
|
|
36
|
+
RUN mkdir -p output
|
|
37
|
+
|
|
38
|
+
USER root
|
|
39
|
+
COPY ./docker-entrypoint.sh /docker-entrypoint.sh
|
|
40
|
+
RUN chmod +x /docker-entrypoint.sh
|
|
31
41
|
|
|
32
42
|
ENV IS_DOCKER=true
|
|
33
43
|
ENV NODE_OPTIONS="--max-http-header-size=99999999"
|
|
34
|
-
|
|
44
|
+
ENV JS_RECON_OUTPUT_OVERWRITE=true
|
|
45
|
+
ENTRYPOINT ["/docker-entrypoint.sh", "node", "build/index.js"]
|
package/Dockerfile.release
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
FROM ghcr.io/puppeteer/puppeteer:25.3.0
|
|
2
2
|
|
|
3
3
|
WORKDIR /home/pptruser
|
|
4
|
+
# Pin HOME so path resolution (Puppeteer's Chrome cache, ~/.js-recon rules cache, etc.)
|
|
5
|
+
# is consistent regardless of which OS user actually executes the process -- root
|
|
6
|
+
# (docker-entrypoint.sh, or any --entrypoint override that bypasses it) or pptruser.
|
|
7
|
+
ENV HOME=/home/pptruser
|
|
4
8
|
|
|
5
9
|
USER root
|
|
6
10
|
ENV PUPPETEER_SKIP_DOWNLOAD=true
|
|
7
11
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
8
|
-
unzip \
|
|
12
|
+
unzip gosu \
|
|
9
13
|
libnspr4 libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 \
|
|
10
14
|
libxcomposite1 libxdamage1 libxrandr2 libgbm1 libxkbcommon0 \
|
|
11
15
|
libasound2 libpangocairo-1.0-0 libxfixes3 libxi6 libxinerama1 \
|
|
@@ -23,7 +27,13 @@ RUN "$(npm root -g)/@js-recon/js-recon/node_modules/.bin/puppeteer" browsers ins
|
|
|
23
27
|
dest="/home/pptruser/.cache/puppeteer/chrome/linux-${version}"; \
|
|
24
28
|
unzip -o "$zip" -d "${dest}/" && chmod +x "${dest}/chrome-linux64/chrome"; \
|
|
25
29
|
done
|
|
30
|
+
RUN mkdir -p output
|
|
31
|
+
|
|
32
|
+
USER root
|
|
33
|
+
COPY ./docker-entrypoint.sh /docker-entrypoint.sh
|
|
34
|
+
RUN chmod +x /docker-entrypoint.sh
|
|
26
35
|
|
|
27
36
|
ENV IS_DOCKER=true
|
|
28
37
|
ENV NODE_OPTIONS="--max-http-header-size=99999999"
|
|
29
|
-
|
|
38
|
+
ENV JS_RECON_OUTPUT_OVERWRITE=true
|
|
39
|
+
ENTRYPOINT ["/docker-entrypoint.sh", "js-recon"]
|
package/Dockerfile.w-rules
CHANGED
package/README.md
CHANGED
|
@@ -74,6 +74,58 @@ To launch a quick assesment against a target, the `run` module can be used to au
|
|
|
74
74
|
js-recon run -u https://app.example.com
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
+
`run`, `lazyload`, and `fingerprint` accept one target, repeated `-u` options, a comma-separated list,
|
|
78
|
+
or a text file containing one HTTP(S) URL per line:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
js-recon run -u https://one.example.com -u https://two.example.com
|
|
82
|
+
js-recon run -u 'https://one.example.com,https://two.example.com'
|
|
83
|
+
js-recon run -u ./targets.txt
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
For `run`, an existing empty output directory is reused. If it contains files, js-recon preserves it
|
|
87
|
+
and selects the next available sibling (`output-2`, `output-3`, and so on). Use
|
|
88
|
+
`--output-overwrite` only when the contents of a previously created js-recon output should be
|
|
89
|
+
replaced. Unowned directories are never recursively cleared.
|
|
90
|
+
|
|
91
|
+
## Configuration
|
|
92
|
+
|
|
93
|
+
On first use, js-recon creates `~/.config/js-recon/config.yaml` with restrictive permissions and a key for every command option. Values resolve in this order:
|
|
94
|
+
|
|
95
|
+
1. Environment variables
|
|
96
|
+
2. Command-line flags
|
|
97
|
+
3. YAML configuration
|
|
98
|
+
4. Built-in defaults
|
|
99
|
+
|
|
100
|
+
Use `JS_RECON_<COMMAND>_<OPTION>` for any command option—for example, `JS_RECON_RUN_THREADS=8`—or select another config file before the subcommand:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
js-recon --config ./operator.yaml run -u https://app.example.com
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Targets may be configured as a YAML list. An environment value or one or more command-line `-u`
|
|
107
|
+
flags replace the entire YAML list according to the precedence above:
|
|
108
|
+
|
|
109
|
+
```yaml
|
|
110
|
+
commands:
|
|
111
|
+
run:
|
|
112
|
+
url:
|
|
113
|
+
- https://one.example.com
|
|
114
|
+
- https://two.example.com
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
See [`config.dist.yaml`](config.dist.yaml) for the complete schema. The existing `proxy --config` and `mcp --config` flags remain command-specific; place the application-level `--config` before those subcommands to avoid ambiguity.
|
|
118
|
+
|
|
119
|
+
Oxylabs CDN/WAF fallback is opt-in. Add non-empty `oxylabs.username` and `oxylabs.password` values to an explicitly selected YAML config, then enable `--oxylabs-waf-fallback` on `run` or `lazyload`. Direct requests remain the default; only strongly identified CDN/WAF blocks are retried through Oxylabs. The default paid-request limits are 10 per origin, 100 total, and 25 distinct origins per run:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
js-recon --config ./operator.yaml run \
|
|
123
|
+
--oxylabs-waf-fallback \
|
|
124
|
+
-u https://app.example.com
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`JS_RECON_OXYLABS_USERNAME`, `JS_RECON_OXYLABS_PASSWORD`, and `JS_RECON_OXYLABS_COUNTRY` override their YAML values unless `--ignore-proxy-env` is set.
|
|
128
|
+
|
|
77
129
|
## Commands
|
|
78
130
|
|
|
79
131
|
`js-recon` provides a suite of commands for comprehensive JavaScript analysis. For detailed usage and examples, please refer to its full documentation.
|
|
@@ -11,7 +11,29 @@ import chalk from "chalk";
|
|
|
11
11
|
import fs from "fs";
|
|
12
12
|
import path from "path";
|
|
13
13
|
import extract from "extract-zip";
|
|
14
|
-
import {
|
|
14
|
+
import { withActiveProxyDispatcher } from "../../utility/makeReq.js";
|
|
15
|
+
const RULES_RELEASE_URL = "https://api.github.com/repos/js-recon/js-recon-rules/releases/latest";
|
|
16
|
+
const fetchLatestRulesRelease = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
|
+
const response = yield fetch(RULES_RELEASE_URL, options);
|
|
18
|
+
if (!response.ok) {
|
|
19
|
+
throw new Error(`Rules release lookup failed with HTTP ${response.status}`);
|
|
20
|
+
}
|
|
21
|
+
const release = (yield response.json());
|
|
22
|
+
if (typeof release !== "object" || release === null) {
|
|
23
|
+
throw new Error("Rules release response was not an object");
|
|
24
|
+
}
|
|
25
|
+
const { tag_name: tagName, zipball_url: zipballUrl } = release;
|
|
26
|
+
if (typeof tagName !== "string" || typeof zipballUrl !== "string") {
|
|
27
|
+
throw new Error("Rules release response is missing tag_name or zipball_url");
|
|
28
|
+
}
|
|
29
|
+
const parsedZipballUrl = new URL(zipballUrl);
|
|
30
|
+
if (parsedZipballUrl.protocol !== "https:" ||
|
|
31
|
+
parsedZipballUrl.hostname !== "api.github.com" ||
|
|
32
|
+
!parsedZipballUrl.pathname.startsWith("/repos/js-recon/js-recon-rules/zipball/")) {
|
|
33
|
+
throw new Error("Rules release response contains an unexpected zipball URL");
|
|
34
|
+
}
|
|
35
|
+
return Object.freeze({ tagName, zipballUrl: parsedZipballUrl.toString() });
|
|
36
|
+
});
|
|
15
37
|
/**
|
|
16
38
|
* Downloads and extracts the latest analysis rules from the GitHub repository.
|
|
17
39
|
*
|
|
@@ -23,17 +45,15 @@ import { withProxyDispatcher } from "../../utility/makeReq.js";
|
|
|
23
45
|
*/
|
|
24
46
|
const downloadRules = (homeDir) => __awaiter(void 0, void 0, void 0, function* () {
|
|
25
47
|
console.log(chalk.cyan("[i] Rules not found. Downloading from GitHub..."));
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
48
|
+
const buffer = yield withActiveProxyDispatcher((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
49
|
+
const release = yield fetchLatestRulesRelease(options);
|
|
50
|
+
const downloadResponse = yield fetch(release.zipballUrl, options);
|
|
51
|
+
if (!downloadResponse.ok) {
|
|
52
|
+
throw new Error(`Failed to download rules: ${downloadResponse.statusText}`);
|
|
53
|
+
}
|
|
54
|
+
return Buffer.from(yield downloadResponse.arrayBuffer());
|
|
55
|
+
}));
|
|
30
56
|
const zipPath = path.join(homeDir, "/.js-recon/rules.zip");
|
|
31
|
-
const downloadResponse = yield fetch(zipballUrl, fetchOpts);
|
|
32
|
-
if (!downloadResponse.ok) {
|
|
33
|
-
throw new Error(`Failed to download rules: ${downloadResponse.statusText}`);
|
|
34
|
-
}
|
|
35
|
-
const arrayBuffer = yield downloadResponse.arrayBuffer();
|
|
36
|
-
const buffer = Buffer.from(arrayBuffer);
|
|
37
57
|
fs.writeFileSync(zipPath, buffer);
|
|
38
58
|
console.log(chalk.cyan("[i] Unzipping rules..."));
|
|
39
59
|
const extractPath = path.join(homeDir, "/.js-recon");
|
|
@@ -115,10 +135,8 @@ const initRules = (...args_1) => __awaiter(void 0, [...args_1], void 0, function
|
|
|
115
135
|
// also, if the version.txt exist, check if the version.txt is latest as per the latest release on github
|
|
116
136
|
const version = fs.readFileSync(versionPath, "utf8").trim();
|
|
117
137
|
try {
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
const release_tag_name = release.tag_name;
|
|
121
|
-
if (`v${version}` !== release_tag_name) {
|
|
138
|
+
const release = yield withActiveProxyDispatcher(fetchLatestRulesRelease);
|
|
139
|
+
if (`v${version}` !== release.tagName) {
|
|
122
140
|
console.error(chalk.yellow("[!] Rules are not up to date. Downloading latest version..."));
|
|
123
141
|
// remove the rules directory
|
|
124
142
|
fs.rmSync(path.join(homeDir, "/.js-recon/rules"), { recursive: true });
|
|
@@ -126,7 +144,7 @@ const initRules = (...args_1) => __awaiter(void 0, [...args_1], void 0, function
|
|
|
126
144
|
}
|
|
127
145
|
}
|
|
128
146
|
catch (_a) {
|
|
129
|
-
console.error(chalk.red("[!] An error
|
|
147
|
+
console.error(chalk.red("[!] An error occurred when fetching rules from GitHub"));
|
|
130
148
|
}
|
|
131
149
|
});
|
|
132
150
|
export default initRules;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initRules.js","sourceRoot":"","sources":["../../../src/analyze/helpers/initRules.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,OAAO,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"initRules.js","sourceRoot":"","sources":["../../../src/analyze/helpers/initRules.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,6 +31,10 @@ const FLAGS = {
|
|
|
31
31
|
"--urls-file",
|
|
32
32
|
"--proxy-config",
|
|
33
33
|
"--ignore-proxy-env",
|
|
34
|
+
"--oxylabs-waf-fallback",
|
|
35
|
+
"--oxylabs-fallback-max-requests",
|
|
36
|
+
"--oxylabs-fallback-max-total",
|
|
37
|
+
"--oxylabs-fallback-max-origins",
|
|
34
38
|
"--cache-file",
|
|
35
39
|
"--disable-cache",
|
|
36
40
|
"--cache-only",
|
|
@@ -47,6 +51,7 @@ const FLAGS = {
|
|
|
47
51
|
"--max-iterations",
|
|
48
52
|
"--max-js-size",
|
|
49
53
|
"--lazyload-timeout",
|
|
54
|
+
"--detection-timeout",
|
|
50
55
|
"--max-pages",
|
|
51
56
|
"--include-methods",
|
|
52
57
|
"--exclude-methods",
|
|
@@ -159,6 +164,7 @@ const FLAGS = {
|
|
|
159
164
|
analyze: [
|
|
160
165
|
"-r",
|
|
161
166
|
"--rules",
|
|
167
|
+
"--disable-rules-version-check",
|
|
162
168
|
"-m",
|
|
163
169
|
"--mapped-json",
|
|
164
170
|
"-t",
|
|
@@ -189,10 +195,12 @@ const FLAGS = {
|
|
|
189
195
|
"--url",
|
|
190
196
|
"-r",
|
|
191
197
|
"--rules",
|
|
198
|
+
"--disable-rules-version-check",
|
|
192
199
|
"-c",
|
|
193
200
|
"--command",
|
|
194
201
|
"-o",
|
|
195
202
|
"--output",
|
|
203
|
+
"--output-overwrite",
|
|
196
204
|
"--strict-scope",
|
|
197
205
|
"-s",
|
|
198
206
|
"--scope",
|
|
@@ -200,6 +208,11 @@ const FLAGS = {
|
|
|
200
208
|
"--threads",
|
|
201
209
|
"--proxy-config",
|
|
202
210
|
"--ignore-proxy-env",
|
|
211
|
+
"--proxy-waf-fallback",
|
|
212
|
+
"--oxylabs-waf-fallback",
|
|
213
|
+
"--oxylabs-fallback-max-requests",
|
|
214
|
+
"--oxylabs-fallback-max-total",
|
|
215
|
+
"--oxylabs-fallback-max-origins",
|
|
203
216
|
"--cache-file",
|
|
204
217
|
"--disable-cache",
|
|
205
218
|
"--cache-only",
|
|
@@ -226,6 +239,7 @@ const FLAGS = {
|
|
|
226
239
|
"--max-iterations",
|
|
227
240
|
"--max-js-size",
|
|
228
241
|
"--lazyload-timeout",
|
|
242
|
+
"--detection-timeout",
|
|
229
243
|
"--max-heap",
|
|
230
244
|
"--max-pages",
|
|
231
245
|
"--include-methods",
|
|
@@ -282,6 +296,7 @@ const FLAGS = {
|
|
|
282
296
|
};
|
|
283
297
|
function generateBashCompletion() {
|
|
284
298
|
const cmdList = COMMANDS.join(" ");
|
|
299
|
+
const cmdPattern = COMMANDS.join("|");
|
|
285
300
|
const caseBranches = Object.entries(FLAGS)
|
|
286
301
|
.map(([cmd, flags]) => ` ${cmd})\n opts="${flags.join(" ")}"\n ;;`)
|
|
287
302
|
.join("\n");
|
|
@@ -295,12 +310,23 @@ _js_recon_completion() {
|
|
|
295
310
|
words=("\${COMP_WORDS[@]}")
|
|
296
311
|
cword=\${COMP_CWORD}
|
|
297
312
|
|
|
298
|
-
if [[ \${
|
|
299
|
-
COMPREPLY=( \$(compgen -
|
|
313
|
+
if [[ \${prev} == "--config" ]]; then
|
|
314
|
+
COMPREPLY=( \$(compgen -f -- "\${cur}") )
|
|
315
|
+
return 0
|
|
316
|
+
fi
|
|
317
|
+
|
|
318
|
+
local cmd=""
|
|
319
|
+
local word
|
|
320
|
+
for word in "\${words[@]}"; do
|
|
321
|
+
case "\${word}" in
|
|
322
|
+
${cmdPattern}) cmd="\${word}"; break ;;
|
|
323
|
+
esac
|
|
324
|
+
done
|
|
325
|
+
if [[ -z \${cmd} ]]; then
|
|
326
|
+
COMPREPLY=( \$(compgen -W "--config ${cmdList}" -- "\${cur}") )
|
|
300
327
|
return 0
|
|
301
328
|
fi
|
|
302
329
|
|
|
303
|
-
local cmd="\${words[1]}"
|
|
304
330
|
opts=""
|
|
305
331
|
case "\${cmd}" in
|
|
306
332
|
${caseBranches}
|
|
@@ -348,6 +374,7 @@ _js_recon() {
|
|
|
348
374
|
_arguments -C \\
|
|
349
375
|
'(-h --help)'{-h,--help}'[Show help]' \\
|
|
350
376
|
'(-V --version)'{-V,--version}'[Show version]' \\
|
|
377
|
+
'--config[Application YAML config]:file:_files' \\
|
|
351
378
|
'1: :->command' \\
|
|
352
379
|
'*: :->args'
|
|
353
380
|
|
|
@@ -391,7 +418,19 @@ function generateFishCompletion() {
|
|
|
391
418
|
function __fish_use_subcommand
|
|
392
419
|
set -l cmd (commandline -poc)
|
|
393
420
|
set -e cmd[1]
|
|
421
|
+
set -l skip_next 0
|
|
394
422
|
for c in $cmd
|
|
423
|
+
if test $skip_next -eq 1
|
|
424
|
+
set skip_next 0
|
|
425
|
+
continue
|
|
426
|
+
end
|
|
427
|
+
if test "$c" = "--config"
|
|
428
|
+
set skip_next 1
|
|
429
|
+
continue
|
|
430
|
+
end
|
|
431
|
+
if string match -q -- '--config=*' "$c"
|
|
432
|
+
continue
|
|
433
|
+
end
|
|
395
434
|
if string match -qr '^[^-]' -- $c
|
|
396
435
|
return 1
|
|
397
436
|
end
|
|
@@ -412,6 +451,8 @@ end
|
|
|
412
451
|
|
|
413
452
|
${cmdCompletions}
|
|
414
453
|
|
|
454
|
+
complete -c js-recon -l config -r -F
|
|
455
|
+
|
|
415
456
|
${flagCompletions}
|
|
416
457
|
`;
|
|
417
458
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/completion/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/completion/index.ts"],"names":[],"mappings":"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"}
|