@js-recon/js-recon 1.4.1-alpha.9 → 1.4.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/.claude-sync/capture-new.sh +61 -0
  2. package/.claude-sync/capture-scan.sh +55 -0
  3. package/.claude-sync/hooks/post-checkout +16 -0
  4. package/.claude-sync/hooks/pre-commit +3 -0
  5. package/.claude-sync/setup.sh +17 -0
  6. package/.claude-sync/sync.sh +64 -0
  7. package/.claude-sync/watch.sh +17 -0
  8. package/.github/workflows/build-and-prettify.yaml +42 -0
  9. package/.github/workflows/promote-js-recon.yml +299 -0
  10. package/.vscode/tasks.json +42 -0
  11. package/CHANGELOG.md +35 -0
  12. package/Dockerfile.w-rules +13 -0
  13. package/README.md +4 -2
  14. package/build/analyze/helpers/initRules.js +28 -6
  15. package/build/analyze/helpers/initRules.js.map +1 -1
  16. package/build/analyze/index.js +3 -2
  17. package/build/analyze/index.js.map +1 -1
  18. package/build/completion/index.js +17 -11
  19. package/build/completion/index.js.map +1 -1
  20. package/build/globalConfig.js +1 -1
  21. package/build/globalConfig.js.map +1 -1
  22. package/build/index.js +55 -23
  23. package/build/index.js.map +1 -1
  24. package/build/lazyLoad/generic/generic_jsMimeTypes.js +19 -0
  25. package/build/lazyLoad/generic/generic_jsMimeTypes.js.map +1 -0
  26. package/build/lazyLoad/index.js +1 -0
  27. package/build/lazyLoad/index.js.map +1 -1
  28. package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js +8 -2
  29. package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js.map +1 -1
  30. package/build/lazyLoad/techDetect/checkInterceptedEvidence.js +18 -0
  31. package/build/lazyLoad/techDetect/checkInterceptedEvidence.js.map +1 -0
  32. package/build/lazyLoad/techDetect/index.js +58 -13
  33. package/build/lazyLoad/techDetect/index.js.map +1 -1
  34. package/build/mcp/mcpServer.js +1 -2
  35. package/build/mcp/mcpServer.js.map +1 -1
  36. package/build/mcp/tools.js +1 -2
  37. package/build/mcp/tools.js.map +1 -1
  38. package/build/proxy/awsConfig.js +45 -0
  39. package/build/proxy/awsConfig.js.map +1 -0
  40. package/build/proxy/checkFeasibility.js.map +1 -0
  41. package/build/proxy/checkFireWallBlocking.js.map +1 -0
  42. package/build/proxy/configFile.js +31 -0
  43. package/build/proxy/configFile.js.map +1 -0
  44. package/build/{api_gateway → proxy}/genReq.js +4 -5
  45. package/build/proxy/genReq.js.map +1 -0
  46. package/build/proxy/genericProxy.js +21 -0
  47. package/build/proxy/genericProxy.js.map +1 -0
  48. package/build/proxy/index.js +421 -0
  49. package/build/proxy/index.js.map +1 -0
  50. package/build/proxy/oxylabsProxy.js +34 -0
  51. package/build/proxy/oxylabsProxy.js.map +1 -0
  52. package/build/proxy/resolveProxyConfig.js +38 -0
  53. package/build/proxy/resolveProxyConfig.js.map +1 -0
  54. package/build/report/utility/initGlobalReportDb.js +111 -0
  55. package/build/report/utility/initGlobalReportDb.js.map +1 -0
  56. package/build/report/utility/mergeDomainIntoGlobalDb.js +39 -0
  57. package/build/report/utility/mergeDomainIntoGlobalDb.js.map +1 -0
  58. package/build/run/index.js +110 -74
  59. package/build/run/index.js.map +1 -1
  60. package/build/run/interruptHandler.js +17 -1
  61. package/build/run/interruptHandler.js.map +1 -1
  62. package/build/utility/configureProxy.js +60 -0
  63. package/build/utility/configureProxy.js.map +1 -0
  64. package/build/utility/globals.js +108 -13
  65. package/build/utility/globals.js.map +1 -1
  66. package/build/utility/makeReq.js +103 -10
  67. package/build/utility/makeReq.js.map +1 -1
  68. package/package.json +5 -1
  69. package/.claude/settings.local.json +0 -10
  70. package/CLAUDE.md +0 -629
  71. package/build/api_gateway/checkFeasibility.js.map +0 -1
  72. package/build/api_gateway/checkFireWallBlocking.js.map +0 -1
  73. package/build/api_gateway/genReq.js.map +0 -1
  74. package/build/api_gateway/index.js +0 -291
  75. package/build/api_gateway/index.js.map +0 -1
  76. package/urls.txt +0 -5
  77. /package/build/{api_gateway → proxy}/checkFeasibility.js +0 -0
  78. /package/build/{api_gateway → proxy}/checkFireWallBlocking.js +0 -0
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Composes the Oxylabs datacenter-proxy username: auth is entirely encoded here, no separate API.
3
+ * user-USERNAME[-country-XX]
4
+ *
5
+ * Verified against a live Oxylabs datacenter account (dc.oxylabs.io:8000) — the previous
6
+ * `customer-USERNAME-cc-XX` residential-style scheme returns a 407 Proxy Authentication Required
7
+ * against real datacenter credentials; this is the confirmed-working format per
8
+ * https://developers.oxylabs.io/products/proxies/datacenter-proxies/select-country.
9
+ *
10
+ * `city` and `sessionId` are not supported here: Oxylabs' datacenter tier has no documented
11
+ * username-level city targeting, and sticky sessions are selected by port number, not by a
12
+ * username suffix — silently encoding either into the username would produce a wrong username
13
+ * that fails auth, so both are rejected explicitly instead.
14
+ */
15
+ export const composeOxylabsUsername = (cfg) => {
16
+ if (cfg.city) {
17
+ throw new Error("Oxylabs config: `city` is not supported (no documented username-level city targeting for datacenter proxies). Omit `city`.");
18
+ }
19
+ if (cfg.sessionId) {
20
+ throw new Error("Oxylabs config: `sessionId` is not supported via username for datacenter proxies (sticky sessions are selected by port, not username). Omit `sessionId`.");
21
+ }
22
+ let username = `user-${cfg.username}`;
23
+ if (cfg.country) {
24
+ username += `-country-${cfg.country}`;
25
+ }
26
+ return username;
27
+ };
28
+ const OXYLABS_ENTRY_ENDPOINT = "dc.oxylabs.io:8000";
29
+ /** Composes the full Oxylabs datacenter proxy URL. */
30
+ export const buildOxylabsProxyUrl = (cfg) => {
31
+ const username = composeOxylabsUsername(cfg);
32
+ return `http://${encodeURIComponent(username)}:${encodeURIComponent(cfg.password)}@${OXYLABS_ENTRY_ENDPOINT}`;
33
+ };
34
+ //# sourceMappingURL=oxylabsProxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oxylabsProxy.js","sourceRoot":"","sources":["../../src/proxy/oxylabsProxy.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,GAAkB,EAAU,EAAE;IACjE,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACX,4HAA4H,CAC/H,CAAC;IACN,CAAC;IACD,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACX,0JAA0J,CAC7J,CAAC;IACN,CAAC;IAED,IAAI,QAAQ,GAAG,QAAQ,GAAG,CAAC,QAAQ,EAAE,CAAC;IACtC,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QACd,QAAQ,IAAI,YAAY,GAAG,CAAC,OAAO,EAAE,CAAC;IAC1C,CAAC;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,oBAAoB,CAAC;AAEpD,sDAAsD;AACtD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,GAAkB,EAAU,EAAE;IAC/D,MAAM,QAAQ,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;IAC7C,OAAO,UAAU,kBAAkB,CAAC,QAAQ,CAAC,IAAI,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,sBAAsB,EAAE,CAAC;AAClH,CAAC,CAAC"}
@@ -0,0 +1,38 @@
1
+ const isValidMethod = (value) => {
2
+ return value === "aws" || value === "socks" || value === "http" || value === "oxylabs";
3
+ };
4
+ export const resolveProxyConfig = (input) => {
5
+ var _a;
6
+ const { cli, env, ignoreEnv, configFileParsed } = input;
7
+ const envMethod = ignoreEnv ? undefined : env.JS_RECON_PROXY_METHOD;
8
+ const rawMethod = cli.proxyMethod || envMethod || configFileParsed.method;
9
+ const method = isValidMethod(rawMethod) ? rawMethod : null;
10
+ if (method === null) {
11
+ return { method: null };
12
+ }
13
+ if (method === "socks" || method === "http") {
14
+ const envUrl = ignoreEnv ? undefined : env.JS_RECON_PROXY_URL;
15
+ const url = cli.proxyUrl || envUrl || ((_a = configFileParsed[method]) === null || _a === void 0 ? void 0 : _a.url);
16
+ return { method, url };
17
+ }
18
+ if (method === "oxylabs") {
19
+ const envUsername = ignoreEnv ? undefined : env.JS_RECON_OXYLABS_USERNAME;
20
+ const envPassword = ignoreEnv ? undefined : env.JS_RECON_OXYLABS_PASSWORD;
21
+ const envCountry = ignoreEnv ? undefined : env.JS_RECON_OXYLABS_COUNTRY;
22
+ const envCity = ignoreEnv ? undefined : env.JS_RECON_OXYLABS_CITY;
23
+ const envSessionId = ignoreEnv ? undefined : env.JS_RECON_OXYLABS_SESSION_ID;
24
+ const fileOxylabs = configFileParsed.oxylabs || {};
25
+ const username = cli.oxylabsUsername || envUsername || fileOxylabs.username;
26
+ const password = cli.oxylabsPassword || envPassword || fileOxylabs.password;
27
+ const country = cli.oxylabsCountry || envCountry || fileOxylabs.country;
28
+ const city = cli.oxylabsCity || envCity || fileOxylabs.city;
29
+ const sessionId = cli.oxylabsSessionId || envSessionId || fileOxylabs.sessionId;
30
+ if (!username || !password) {
31
+ return { method: null };
32
+ }
33
+ return { method, oxylabs: { username, password, country, city, sessionId } };
34
+ }
35
+ // method === "aws"
36
+ return { method, awsGatewayMap: configFileParsed.aws || {} };
37
+ };
38
+ //# sourceMappingURL=resolveProxyConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveProxyConfig.js","sourceRoot":"","sources":["../../src/proxy/resolveProxyConfig.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
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 Database from "better-sqlite3";
11
+ /**
12
+ * Creates the mapped table in the global database. Adds a `domain` column and a
13
+ * `globalId` surrogate key since the original `id` (chunk module id) is only
14
+ * unique within a single domain's bundle, not across domains.
15
+ *
16
+ * @param db - The database to create the table in
17
+ */
18
+ const createMappedTable = (db) => {
19
+ db.prepare(`
20
+ CREATE TABLE IF NOT EXISTS mapped (
21
+ globalId INTEGER PRIMARY KEY AUTOINCREMENT,
22
+ domain TEXT,
23
+ id TEXT,
24
+ description TEXT,
25
+ loadedOn TEXT,
26
+ containsFetch BOOLEAN,
27
+ isAxiosClient BOOLEAN,
28
+ exports TEXT,
29
+ callStack TEXT,
30
+ code TEXT,
31
+ imports TEXT,
32
+ file TEXT
33
+ )
34
+ `).run();
35
+ };
36
+ /**
37
+ * Creates the mapped OpenAPI table in the global database. The primary key is
38
+ * widened to include `domain` since the same path/method can exist on
39
+ * different domains.
40
+ *
41
+ * @param db - The database to create the table in
42
+ */
43
+ const createMappedOpenapiTable = (db) => {
44
+ db.prepare(`
45
+ CREATE TABLE IF NOT EXISTS mapped_openapi (
46
+ domain TEXT,
47
+ path TEXT,
48
+ method TEXT,
49
+ summary TEXT,
50
+ parameters TEXT,
51
+ requestBody TEXT,
52
+ tags TEXT,
53
+ PRIMARY KEY (domain, path, method)
54
+ )
55
+ `).run();
56
+ };
57
+ /**
58
+ * Creates the endpoints table in the global database. The primary key is
59
+ * widened to include `domain` since the same URL can exist on different
60
+ * domains.
61
+ *
62
+ * @param db - The database to create the table in
63
+ */
64
+ const createEndpointsTable = (db) => {
65
+ db.prepare(`
66
+ CREATE TABLE IF NOT EXISTS endpoints (
67
+ domain TEXT,
68
+ url TEXT,
69
+ PRIMARY KEY (domain, url)
70
+ )
71
+ `).run();
72
+ };
73
+ /**
74
+ * Creates the analysis findings table in the global database. Adds a `domain`
75
+ * column and a `globalId` surrogate key.
76
+ *
77
+ * @param db - The database to create the table in
78
+ */
79
+ const createAnalysisFindingsTable = (db) => {
80
+ db.prepare(`
81
+ CREATE TABLE IF NOT EXISTS analysis_findings (
82
+ globalId INTEGER PRIMARY KEY AUTOINCREMENT,
83
+ domain TEXT,
84
+ ruleId TEXT,
85
+ ruleName TEXT,
86
+ ruleType TEXT,
87
+ ruleDescription TEXT,
88
+ ruleAuthor TEXT,
89
+ ruleTech TEXT,
90
+ severity TEXT,
91
+ message TEXT,
92
+ findingLocation TEXT
93
+ )
94
+ `).run();
95
+ };
96
+ /**
97
+ * Initializes the global report database used to aggregate the per-domain
98
+ * `js-recon.db` files produced during a batch (`-u <file>`) run.
99
+ *
100
+ * @param sqliteDbPath - The path to the global SQLite database file
101
+ */
102
+ const initGlobalReportDb = (sqliteDbPath) => __awaiter(void 0, void 0, void 0, function* () {
103
+ const db = new Database(sqliteDbPath);
104
+ createMappedTable(db);
105
+ createMappedOpenapiTable(db);
106
+ createEndpointsTable(db);
107
+ createAnalysisFindingsTable(db);
108
+ db.close();
109
+ });
110
+ export default initGlobalReportDb;
111
+ //# sourceMappingURL=initGlobalReportDb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initGlobalReportDb.js","sourceRoot":"","sources":["../../../src/report/utility/initGlobalReportDb.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC;;;;;;GAMG;AACH,MAAM,iBAAiB,GAAG,CAAC,EAAqB,EAAE,EAAE;IAChD,EAAE,CAAC,OAAO,CACN;;;;;;;;;;;;;;;KAeH,CACA,CAAC,GAAG,EAAE,CAAC;AACZ,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,wBAAwB,GAAG,CAAC,EAAqB,EAAE,EAAE;IACvD,EAAE,CAAC,OAAO,CACN;;;;;;;;;;;KAWH,CACA,CAAC,GAAG,EAAE,CAAC;AACZ,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,oBAAoB,GAAG,CAAC,EAAqB,EAAE,EAAE;IACnD,EAAE,CAAC,OAAO,CACN;;;;;;KAMH,CACA,CAAC,GAAG,EAAE,CAAC;AACZ,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,2BAA2B,GAAG,CAAC,EAAqB,EAAE,EAAE;IAC1D,EAAE,CAAC,OAAO,CACN;;;;;;;;;;;;;;KAcH,CACA,CAAC,GAAG,EAAE,CAAC;AACZ,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,kBAAkB,GAAG,CAAO,YAAoB,EAAE,EAAE;IACtD,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC;IAEtC,iBAAiB,CAAC,EAAE,CAAC,CAAC;IACtB,wBAAwB,CAAC,EAAE,CAAC,CAAC;IAC7B,oBAAoB,CAAC,EAAE,CAAC,CAAC;IACzB,2BAA2B,CAAC,EAAE,CAAC,CAAC;IAEhC,EAAE,CAAC,KAAK,EAAE,CAAC;AACf,CAAC,CAAA,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -0,0 +1,39 @@
1
+ import Database from "better-sqlite3";
2
+ /**
3
+ * Merges a single domain's fully-populated `js-recon.db` into the batch-wide
4
+ * global database, tagging every copied row with `domain` so it can be
5
+ * traced back to its source directory. Uses `ATTACH DATABASE` so rows are
6
+ * copied directly via SQL instead of re-reading the domain's JSON inputs.
7
+ *
8
+ * @param globalDbPath - Path to the global SQLite database file
9
+ * @param domainDbPath - Path to the domain's own `js-recon.db`
10
+ * @param domain - The domain identifier (sanitized host) to tag rows with
11
+ */
12
+ const mergeDomainIntoGlobalDb = (globalDbPath, domainDbPath, domain) => {
13
+ const db = new Database(globalDbPath);
14
+ try {
15
+ db.prepare(`ATTACH DATABASE ? AS src`).run(domainDbPath);
16
+ db.prepare(`
17
+ INSERT INTO mapped (domain, id, description, loadedOn, containsFetch, isAxiosClient, exports, callStack, code, imports, file)
18
+ SELECT ?, id, description, loadedOn, containsFetch, isAxiosClient, exports, callStack, code, imports, file FROM src.mapped
19
+ `).run(domain);
20
+ db.prepare(`
21
+ INSERT OR REPLACE INTO mapped_openapi (domain, path, method, summary, parameters, requestBody, tags)
22
+ SELECT ?, path, method, summary, parameters, requestBody, tags FROM src.mapped_openapi
23
+ `).run(domain);
24
+ db.prepare(`
25
+ INSERT OR IGNORE INTO endpoints (domain, url)
26
+ SELECT ?, url FROM src.endpoints
27
+ `).run(domain);
28
+ db.prepare(`
29
+ INSERT INTO analysis_findings (domain, ruleId, ruleName, ruleType, ruleDescription, ruleAuthor, ruleTech, severity, message, findingLocation)
30
+ SELECT ?, ruleId, ruleName, ruleType, ruleDescription, ruleAuthor, ruleTech, severity, message, findingLocation FROM src.analysis_findings
31
+ `).run(domain);
32
+ db.prepare(`DETACH DATABASE src`).run();
33
+ }
34
+ finally {
35
+ db.close();
36
+ }
37
+ };
38
+ export default mergeDomainIntoGlobalDb;
39
+ //# sourceMappingURL=mergeDomainIntoGlobalDb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeDomainIntoGlobalDb.js","sourceRoot":"","sources":["../../../src/report/utility/mergeDomainIntoGlobalDb.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC;;;;;;;;;GASG;AACH,MAAM,uBAAuB,GAAG,CAAC,YAAoB,EAAE,YAAoB,EAAE,MAAc,EAAE,EAAE;IAC3F,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC;IAEtC,IAAI,CAAC;QACD,EAAE,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAEzD,EAAE,CAAC,OAAO,CACN;;;SAGH,CACA,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAEd,EAAE,CAAC,OAAO,CACN;;;SAGH,CACA,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAEd,EAAE,CAAC,OAAO,CACN;;;SAGH,CACA,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAEd,EAAE,CAAC,OAAO,CACN;;;SAGH,CACA,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAEd,EAAE,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,GAAG,EAAE,CAAC;IAC5C,CAAC;YAAS,CAAC;QACP,EAAE,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;AACL,CAAC,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
@@ -18,10 +18,13 @@ import CONFIG from "../globalConfig.js";
18
18
  import analyze from "../analyze/index.js";
19
19
  import report from "../report/index.js";
20
20
  import refactor from "../refactor/index.js";
21
+ import initGlobalReportDb from "../report/utility/initGlobalReportDb.js";
22
+ import mergeDomainIntoGlobalDb from "../report/utility/mergeDomainIntoGlobalDb.js";
21
23
  import { clearJsUrls, clearJsonUrls, getJsUrls } from "../lazyLoad/globals.js";
22
24
  import path from "path";
23
- import { installSigintHandler, removeSigintHandler, getSkipStepPromise, resetSkipStep, shouldSkipTarget, resetSkipTarget, } from "./interruptHandler.js";
25
+ import { installSigintHandler, removeSigintHandler, getSkipStepPromise, resetSkipStep, shouldSkipTarget, resetSkipTarget, waitForPendingInterrupt, } from "./interruptHandler.js";
24
26
  import { detectBundler } from "./bundler-detect.js";
27
+ import configureProxy from "../utility/configureProxy.js";
25
28
  /**
26
29
  * Determines the directory for a Content Delivery Network (CDN) if used by the target.
27
30
  *
@@ -131,7 +134,7 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
131
134
  resetSkipStep();
132
135
  // @ts-ignore
133
136
  yield Promise.race([
134
- analyze(cmd.rules || "", mappedJsonFileReact, "react", false, openapiFile, false, analyzeFile),
137
+ analyze(cmd.rules || "", mappedJsonFileReact, "react", false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck),
135
138
  getSkipStepPromise(),
136
139
  ]);
137
140
  console.log(chalk.bgGreen("[+] Analyze complete."));
@@ -150,24 +153,29 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
150
153
  console.log(chalk.bgGreen("[+] Report complete."));
151
154
  if (shouldSkipTarget())
152
155
  return;
153
- console.log(chalk.bgCyan("[*] Detecting bundler via CS-MAST-S for refactor..."));
154
- const detectedBundlerTechReact = yield detectBundler(mappedJsonFileReact, "react", Number((_a = cmd.csMastTechDetectThreshold) !== null && _a !== void 0 ? _a : 50));
155
- if (detectedBundlerTechReact) {
156
- const refactorOutputDirReact = isBatch ? `${workingDir}/refactored` : "refactored";
157
- if (fs.existsSync(refactorOutputDirReact))
158
- fs.rmSync(refactorOutputDirReact, { recursive: true });
159
- console.log(chalk.bgCyan(`[*] Running refactor (${detectedBundlerTechReact})...`));
160
- resetSkipStep();
161
- yield Promise.race([
162
- refactor(mappedJsonFileReact, refactorOutputDirReact, detectedBundlerTechReact, false),
163
- getSkipStepPromise(),
164
- ]);
165
- if (shouldSkipTarget())
166
- return;
167
- console.log(chalk.bgGreen("[+] Refactor complete."));
156
+ if (!cmd.disableRefactor) {
157
+ console.log(chalk.bgCyan("[*] Detecting bundler via CS-MAST-S for refactor..."));
158
+ const detectedBundlerTechReact = yield detectBundler(mappedJsonFileReact, "react", Number((_a = cmd.csMastTechDetectThreshold) !== null && _a !== void 0 ? _a : 50));
159
+ if (detectedBundlerTechReact) {
160
+ const refactorOutputDirReact = isBatch ? `${workingDir}/refactored` : "refactored";
161
+ if (fs.existsSync(refactorOutputDirReact))
162
+ fs.rmSync(refactorOutputDirReact, { recursive: true });
163
+ console.log(chalk.bgCyan(`[*] Running refactor (${detectedBundlerTechReact})...`));
164
+ resetSkipStep();
165
+ yield Promise.race([
166
+ refactor(mappedJsonFileReact, refactorOutputDirReact, detectedBundlerTechReact, false),
167
+ getSkipStepPromise(),
168
+ ]);
169
+ if (shouldSkipTarget())
170
+ return;
171
+ console.log(chalk.bgGreen("[+] Refactor complete."));
172
+ }
173
+ else {
174
+ console.log(chalk.yellow("[!] Bundler not detected via CS-MAST-S, skipping refactor."));
175
+ }
168
176
  }
169
177
  else {
170
- console.log(chalk.yellow("[!] Bundler not detected via CS-MAST-S, skipping refactor."));
178
+ console.log(chalk.yellow("[!] Refactor step disabled via --disable-refactor, skipping."));
171
179
  }
172
180
  console.log(chalk.bgGreenBright(`[+] Analysis complete for ${url}.`));
173
181
  return;
@@ -205,7 +213,7 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
205
213
  resetSkipStep();
206
214
  // @ts-ignore
207
215
  yield Promise.race([
208
- analyze(cmd.rules || "", mappedJsonFileVue, "vue", false, openapiFile, false, analyzeFile),
216
+ analyze(cmd.rules || "", mappedJsonFileVue, "vue", false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck),
209
217
  getSkipStepPromise(),
210
218
  ]);
211
219
  console.log(chalk.bgGreen("[+] Analyze complete."));
@@ -225,24 +233,29 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
225
233
  console.log(chalk.bgGreen("[+] Report complete."));
226
234
  if (shouldSkipTarget())
227
235
  return;
228
- console.log(chalk.bgCyan("[*] Detecting bundler via CS-MAST-S for refactor..."));
229
- const detectedBundlerTechVue = yield detectBundler(mappedJsonFileVue, "vue", Number((_b = cmd.csMastTechDetectThreshold) !== null && _b !== void 0 ? _b : 50));
230
- if (detectedBundlerTechVue) {
231
- const refactorOutputDirVue = isBatch ? `${workingDir}/refactored` : "refactored";
232
- if (fs.existsSync(refactorOutputDirVue))
233
- fs.rmSync(refactorOutputDirVue, { recursive: true });
234
- console.log(chalk.bgCyan(`[*] Running refactor (${detectedBundlerTechVue})...`));
235
- resetSkipStep();
236
- yield Promise.race([
237
- refactor(mappedJsonFileVue, refactorOutputDirVue, detectedBundlerTechVue, false),
238
- getSkipStepPromise(),
239
- ]);
240
- if (shouldSkipTarget())
241
- return;
242
- console.log(chalk.bgGreen("[+] Refactor complete."));
236
+ if (!cmd.disableRefactor) {
237
+ console.log(chalk.bgCyan("[*] Detecting bundler via CS-MAST-S for refactor..."));
238
+ const detectedBundlerTechVue = yield detectBundler(mappedJsonFileVue, "vue", Number((_b = cmd.csMastTechDetectThreshold) !== null && _b !== void 0 ? _b : 50));
239
+ if (detectedBundlerTechVue) {
240
+ const refactorOutputDirVue = isBatch ? `${workingDir}/refactored` : "refactored";
241
+ if (fs.existsSync(refactorOutputDirVue))
242
+ fs.rmSync(refactorOutputDirVue, { recursive: true });
243
+ console.log(chalk.bgCyan(`[*] Running refactor (${detectedBundlerTechVue})...`));
244
+ resetSkipStep();
245
+ yield Promise.race([
246
+ refactor(mappedJsonFileVue, refactorOutputDirVue, detectedBundlerTechVue, false),
247
+ getSkipStepPromise(),
248
+ ]);
249
+ if (shouldSkipTarget())
250
+ return;
251
+ console.log(chalk.bgGreen("[+] Refactor complete."));
252
+ }
253
+ else {
254
+ console.log(chalk.yellow("[!] Bundler not detected via CS-MAST-S, skipping refactor."));
255
+ }
243
256
  }
244
257
  else {
245
- console.log(chalk.yellow("[!] Bundler not detected via CS-MAST-S, skipping refactor."));
258
+ console.log(chalk.yellow("[!] Refactor step disabled via --disable-refactor, skipping."));
246
259
  }
247
260
  console.log(chalk.bgGreenBright(`[+] Analysis complete for ${url}.`));
248
261
  return;
@@ -278,7 +291,7 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
278
291
  resetSkipStep();
279
292
  // @ts-ignore
280
293
  yield Promise.race([
281
- analyze(cmd.rules || "", mappedJsonFileNuxt, "vue", false, openapiFile, false, analyzeFile),
294
+ analyze(cmd.rules || "", mappedJsonFileNuxt, "vue", false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck),
282
295
  getSkipStepPromise(),
283
296
  ]);
284
297
  console.log(chalk.bgGreen("[+] Analyze complete."));
@@ -297,24 +310,29 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
297
310
  console.log(chalk.bgGreen("[+] Report complete."));
298
311
  if (shouldSkipTarget())
299
312
  return;
300
- console.log(chalk.bgCyan("[*] Detecting bundler via CS-MAST-S for refactor..."));
301
- const detectedBundlerTechNuxt = yield detectBundler(mappedJsonFileNuxt, "nuxt", Number((_c = cmd.csMastTechDetectThreshold) !== null && _c !== void 0 ? _c : 50));
302
- if (detectedBundlerTechNuxt) {
303
- const refactorOutputDirNuxt = isBatch ? `${workingDir}/refactored` : "refactored";
304
- if (fs.existsSync(refactorOutputDirNuxt))
305
- fs.rmSync(refactorOutputDirNuxt, { recursive: true });
306
- console.log(chalk.bgCyan(`[*] Running refactor (${detectedBundlerTechNuxt})...`));
307
- resetSkipStep();
308
- yield Promise.race([
309
- refactor(mappedJsonFileNuxt, refactorOutputDirNuxt, detectedBundlerTechNuxt, false),
310
- getSkipStepPromise(),
311
- ]);
312
- if (shouldSkipTarget())
313
- return;
314
- console.log(chalk.bgGreen("[+] Refactor complete."));
313
+ if (!cmd.disableRefactor) {
314
+ console.log(chalk.bgCyan("[*] Detecting bundler via CS-MAST-S for refactor..."));
315
+ const detectedBundlerTechNuxt = yield detectBundler(mappedJsonFileNuxt, "nuxt", Number((_c = cmd.csMastTechDetectThreshold) !== null && _c !== void 0 ? _c : 50));
316
+ if (detectedBundlerTechNuxt) {
317
+ const refactorOutputDirNuxt = isBatch ? `${workingDir}/refactored` : "refactored";
318
+ if (fs.existsSync(refactorOutputDirNuxt))
319
+ fs.rmSync(refactorOutputDirNuxt, { recursive: true });
320
+ console.log(chalk.bgCyan(`[*] Running refactor (${detectedBundlerTechNuxt})...`));
321
+ resetSkipStep();
322
+ yield Promise.race([
323
+ refactor(mappedJsonFileNuxt, refactorOutputDirNuxt, detectedBundlerTechNuxt, false),
324
+ getSkipStepPromise(),
325
+ ]);
326
+ if (shouldSkipTarget())
327
+ return;
328
+ console.log(chalk.bgGreen("[+] Refactor complete."));
329
+ }
330
+ else {
331
+ console.log(chalk.yellow("[!] Bundler not detected via CS-MAST-S, skipping refactor."));
332
+ }
315
333
  }
316
334
  else {
317
- console.log(chalk.yellow("[!] Bundler not detected via CS-MAST-S, skipping refactor."));
335
+ console.log(chalk.yellow("[!] Refactor step disabled via --disable-refactor, skipping."));
318
336
  }
319
337
  console.log(chalk.bgGreenBright(`[+] Analysis complete for ${url}.`));
320
338
  return;
@@ -349,7 +367,7 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
349
367
  resetSkipStep();
350
368
  // @ts-ignore
351
369
  yield Promise.race([
352
- analyze(cmd.rules || "", mappedJsonFileSvelte, "svelte", false, openapiFile, false, analyzeFile),
370
+ analyze(cmd.rules || "", mappedJsonFileSvelte, "svelte", false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck),
353
371
  getSkipStepPromise(),
354
372
  ]);
355
373
  console.log(chalk.bgGreen("[+] Analyze complete."));
@@ -403,7 +421,7 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
403
421
  resetSkipStep();
404
422
  // @ts-ignore
405
423
  yield Promise.race([
406
- analyze(cmd.rules || "", mappedJsonFileAngular, "angular", false, openapiFile, false, analyzeFile),
424
+ analyze(cmd.rules || "", mappedJsonFileAngular, "angular", false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck),
407
425
  getSkipStepPromise(),
408
426
  ]);
409
427
  console.log(chalk.bgGreen("[+] Analyze complete."));
@@ -527,8 +545,7 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
527
545
  console.log(chalk.bgCyan("[7/8] Running analyze to extract endpoints..."));
528
546
  resetSkipStep();
529
547
  yield Promise.race([
530
- // @ts-ignore
531
- analyze(cmd.rules || "", mappedJsonFile, detectedTech, false, openapiFile, false, analyzeFile),
548
+ analyze(cmd.rules || "", mappedJsonFile, detectedTech, false, openapiFile, false, analyzeFile, !!cmd.disableRulesVersionCheck),
532
549
  getSkipStepPromise(),
533
550
  ]);
534
551
  console.log(chalk.bgGreen("[+] Analyze complete."));
@@ -543,24 +560,29 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
543
560
  console.log(chalk.bgGreen("[+] Report complete."));
544
561
  if (shouldSkipTarget())
545
562
  return;
546
- console.log(chalk.bgCyan("[*] Detecting bundler via CS-MAST-S for refactor..."));
547
- const detectedBundlerTechNext = yield detectBundler(mappedJsonFile, detectedTech, Number((_d = cmd.csMastTechDetectThreshold) !== null && _d !== void 0 ? _d : 50));
548
- if (detectedBundlerTechNext) {
549
- const refactorOutputDirNext = isBatch ? `${workingDir}/refactored` : "refactored";
550
- if (fs.existsSync(refactorOutputDirNext))
551
- fs.rmSync(refactorOutputDirNext, { recursive: true });
552
- console.log(chalk.bgCyan(`[*] Running refactor (${detectedBundlerTechNext})...`));
553
- resetSkipStep();
554
- yield Promise.race([
555
- refactor(mappedJsonFile, refactorOutputDirNext, detectedBundlerTechNext, false),
556
- getSkipStepPromise(),
557
- ]);
558
- if (shouldSkipTarget())
559
- return;
560
- console.log(chalk.bgGreen("[+] Refactor complete."));
563
+ if (!cmd.disableRefactor) {
564
+ console.log(chalk.bgCyan("[*] Detecting bundler via CS-MAST-S for refactor..."));
565
+ const detectedBundlerTechNext = yield detectBundler(mappedJsonFile, detectedTech, Number((_d = cmd.csMastTechDetectThreshold) !== null && _d !== void 0 ? _d : 50));
566
+ if (detectedBundlerTechNext) {
567
+ const refactorOutputDirNext = isBatch ? `${workingDir}/refactored` : "refactored";
568
+ if (fs.existsSync(refactorOutputDirNext))
569
+ fs.rmSync(refactorOutputDirNext, { recursive: true });
570
+ console.log(chalk.bgCyan(`[*] Running refactor (${detectedBundlerTechNext})...`));
571
+ resetSkipStep();
572
+ yield Promise.race([
573
+ refactor(mappedJsonFile, refactorOutputDirNext, detectedBundlerTechNext, false),
574
+ getSkipStepPromise(),
575
+ ]);
576
+ if (shouldSkipTarget())
577
+ return;
578
+ console.log(chalk.bgGreen("[+] Refactor complete."));
579
+ }
580
+ else {
581
+ console.log(chalk.yellow("[!] Bundler not detected via CS-MAST-S, skipping refactor."));
582
+ }
561
583
  }
562
584
  else {
563
- console.log(chalk.yellow("[!] Bundler not detected via CS-MAST-S, skipping refactor."));
585
+ console.log(chalk.yellow("[!] Refactor step disabled via --disable-refactor, skipping."));
564
586
  }
565
587
  console.log(chalk.bgGreenBright(`[+] Analysis complete for ${url}.`));
566
588
  });
@@ -576,8 +598,7 @@ const processUrl = (url_1, outputDir_1, workingDir_1, cmd_1, isBatch_1, ...args_
576
598
  */
577
599
  export default (cmd) => __awaiter(void 0, void 0, void 0, function* () {
578
600
  var _a, _b, _c, _d, _e;
579
- globalsUtil.setApiGatewayConfigFile(cmd.apiGatewayConfig);
580
- globalsUtil.setUseApiGateway(cmd.apiGateway);
601
+ configureProxy(cmd);
581
602
  globalsUtil.setDisableCache(cmd.disableCache);
582
603
  globalsUtil.setRespCacheFile(cmd.cacheFile);
583
604
  globalsUtil.setYes(cmd.yes);
@@ -612,6 +633,8 @@ export default (cmd) => __awaiter(void 0, void 0, void 0, function* () {
612
633
  if (!fs.existsSync(cmd.output)) {
613
634
  fs.mkdirSync(cmd.output, { recursive: true });
614
635
  }
636
+ const globalDbPath = `${cmd.output}/js-recon.db`;
637
+ yield initGlobalReportDb(globalDbPath);
615
638
  for (const url of urls) {
616
639
  resetSkipTarget();
617
640
  // Validate URL only
@@ -632,10 +655,23 @@ export default (cmd) => __awaiter(void 0, void 0, void 0, function* () {
632
655
  }
633
656
  fs.mkdirSync(thisTargetDir, { recursive: true });
634
657
  yield processUrl(url, thisTargetDir, thisTargetDir, cmd, true, (_c = cmd._includeMethods) !== null && _c !== void 0 ? _c : [], (_d = cmd._excludeMethods) !== null && _d !== void 0 ? _d : []);
658
+ const domainDbPath = `${thisTargetDir}/js-recon.db`;
659
+ if (fs.existsSync(domainDbPath)) {
660
+ try {
661
+ mergeDomainIntoGlobalDb(globalDbPath, domainDbPath, hostDir);
662
+ }
663
+ catch (error) {
664
+ console.error(chalk.yellow(`[!] Failed to merge ${hostDir} into the global js-recon.db: ${error}`));
665
+ }
666
+ }
667
+ else {
668
+ console.log(chalk.yellow(`[i] No js-recon.db found for ${hostDir}, skipping merge into the global database.`));
669
+ }
635
670
  }
636
671
  }
637
672
  }
638
673
  finally {
674
+ yield waitForPendingInterrupt();
639
675
  removeSigintHandler();
640
676
  process.exit((_e = process.exitCode) !== null && _e !== void 0 ? _e : 0);
641
677
  }