@jshookmcp/jshook 0.1.7 → 0.1.8

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 (44) hide show
  1. package/README.md +145 -100
  2. package/README.zh.md +81 -36
  3. package/dist/constants.d.ts +1 -1
  4. package/dist/constants.js +3 -1
  5. package/dist/modules/analyzer/QualityAnalyzer.js +1 -1
  6. package/dist/modules/browser/BrowserDiscovery.js +2 -2
  7. package/dist/modules/browser/BrowserModeManager.js +3 -3
  8. package/dist/modules/captcha/AICaptchaDetector.d.ts +12 -16
  9. package/dist/modules/captcha/AICaptchaDetector.js +209 -189
  10. package/dist/modules/captcha/CaptchaDetector.constants.d.ts +2 -0
  11. package/dist/modules/captcha/CaptchaDetector.constants.js +116 -25
  12. package/dist/modules/captcha/CaptchaDetector.d.ts +2 -11
  13. package/dist/modules/captcha/CaptchaDetector.js +102 -51
  14. package/dist/modules/captcha/types.d.ts +46 -0
  15. package/dist/modules/captcha/types.js +52 -0
  16. package/dist/modules/deobfuscator/AdvancedDeobfuscator.d.ts +15 -20
  17. package/dist/modules/deobfuscator/AdvancedDeobfuscator.js +66 -234
  18. package/dist/modules/deobfuscator/Deobfuscator.d.ts +3 -10
  19. package/dist/modules/deobfuscator/Deobfuscator.js +125 -404
  20. package/dist/modules/deobfuscator/webcrack.d.ts +13 -0
  21. package/dist/modules/deobfuscator/webcrack.js +164 -0
  22. package/dist/modules/detector/ObfuscationDetector.d.ts +6 -0
  23. package/dist/modules/detector/ObfuscationDetector.js +53 -2
  24. package/dist/modules/hook/AIHookGenerator.js +1 -1
  25. package/dist/modules/process/memory/writer.js +1 -1
  26. package/dist/server/domains/analysis/definitions.js +223 -2
  27. package/dist/server/domains/analysis/handlers.impl.d.ts +2 -3
  28. package/dist/server/domains/analysis/handlers.impl.js +60 -15
  29. package/dist/server/domains/analysis/manifest.js +2 -5
  30. package/dist/server/domains/browser/definitions.tools.behavior.js +36 -24
  31. package/dist/server/domains/browser/definitions.tools.security.js +13 -10
  32. package/dist/server/domains/browser/handlers/camoufox-flow.js +0 -1
  33. package/dist/server/domains/browser/handlers/captcha-solver.d.ts +1 -1
  34. package/dist/server/domains/browser/handlers/captcha-solver.js +121 -54
  35. package/dist/server/domains/browser/handlers/page-navigation.js +0 -2
  36. package/dist/server/domains/browser/handlers.impl.d.ts +1 -1
  37. package/dist/server/domains/browser/handlers.impl.js +3 -3
  38. package/dist/server/domains/browser/manifest.js +1 -1
  39. package/dist/server/domains/shared/modules.d.ts +1 -0
  40. package/dist/types/deobfuscator.d.ts +43 -1
  41. package/dist/types/index.d.ts +1 -1
  42. package/dist/utils/config.js +19 -10
  43. package/package.json +6 -3
  44. package/scripts/postinstall.cjs +37 -0
@@ -23,7 +23,6 @@ export class PageNavigationHandlers {
23
23
  text: JSON.stringify({
24
24
  success: true,
25
25
  driver: 'camoufox',
26
- captcha_detected: false,
27
26
  url: page.url(),
28
27
  title: await page.title(),
29
28
  network_monitoring: {
@@ -51,7 +50,6 @@ export class PageNavigationHandlers {
51
50
  type: 'text',
52
51
  text: JSON.stringify({
53
52
  success: true,
54
- captcha_detected: false,
55
53
  url: currentUrl,
56
54
  title,
57
55
  network_monitoring: {
@@ -394,6 +394,6 @@ export declare class BrowserToolHandlers {
394
394
  handleHumanScroll(args: Record<string, unknown>): Promise<unknown>;
395
395
  handleHumanTyping(args: Record<string, unknown>): Promise<unknown>;
396
396
  handleCaptchaVisionSolve(args: Record<string, unknown>): Promise<unknown>;
397
- handleTurnstileSolve(args: Record<string, unknown>): Promise<unknown>;
397
+ handleWidgetChallengeSolve(args: Record<string, unknown>): Promise<unknown>;
398
398
  }
399
399
  export { BrowserControlHandlers, CamoufoxBrowserHandlers, PageNavigationHandlers, PageInteractionHandlers, PageEvaluationHandlers, PageDataHandlers, DOMQueryHandlers, DOMStyleHandlers, DOMSearchHandlers, ConsoleHandlers, ScriptManagementHandlers, CaptchaHandlers, StealthInjectionHandlers, FrameworkStateHandlers, IndexedDBDumpHandlers, DetailedDataHandlers };
@@ -20,7 +20,7 @@ import { IndexedDBDumpHandlers } from '../../domains/browser/handlers/indexeddb-
20
20
  import { DetailedDataHandlers } from '../../domains/browser/handlers/detailed-data.js';
21
21
  import { initializeBrowserHandlerModules } from '../../domains/browser/handlers/facade-initializer.js';
22
22
  import { handleHumanMouse, handleHumanScroll, handleHumanTyping, } from '../../domains/browser/handlers/human-behavior.js';
23
- import { handleCaptchaVisionSolve, handleTurnstileSolve, } from '../../domains/browser/handlers/captcha-solver.js';
23
+ import { handleCaptchaVisionSolve, handleWidgetChallengeSolve, } from '../../domains/browser/handlers/captcha-solver.js';
24
24
  import { handleCamoufoxLaunchFlow, handleCamoufoxNavigateFlow, } from '../../domains/browser/handlers/camoufox-flow.js';
25
25
  export class BrowserToolHandlers {
26
26
  collector;
@@ -381,8 +381,8 @@ export class BrowserToolHandlers {
381
381
  async handleCaptchaVisionSolve(args) {
382
382
  return handleCaptchaVisionSolve(args, this.collector);
383
383
  }
384
- async handleTurnstileSolve(args) {
385
- return handleTurnstileSolve(args, this.collector);
384
+ async handleWidgetChallengeSolve(args) {
385
+ return handleWidgetChallengeSolve(args, this.collector);
386
386
  }
387
387
  }
388
388
  export { BrowserControlHandlers, CamoufoxBrowserHandlers, PageNavigationHandlers, PageInteractionHandlers, PageEvaluationHandlers, PageDataHandlers, DOMQueryHandlers, DOMStyleHandlers, DOMSearchHandlers, ConsoleHandlers, ScriptManagementHandlers, CaptchaHandlers, StealthInjectionHandlers, FrameworkStateHandlers, IndexedDBDumpHandlers, DetailedDataHandlers };
@@ -79,7 +79,7 @@ const manifest = {
79
79
  { tool: t('human_scroll'), domain: DOMAIN, bind: b((h, a) => h.handleHumanScroll(a)) },
80
80
  { tool: t('human_typing'), domain: DOMAIN, bind: b((h, a) => h.handleHumanTyping(a)) },
81
81
  { tool: t('captcha_vision_solve'), domain: DOMAIN, bind: b((h, a) => h.handleCaptchaVisionSolve(a)) },
82
- { tool: t('turnstile_solve'), domain: DOMAIN, bind: b((h, a) => h.handleTurnstileSolve(a)) },
82
+ { tool: t('widget_challenge_solve'), domain: DOMAIN, bind: b((h, a) => h.handleWidgetChallengeSolve(a)) },
83
83
  ],
84
84
  };
85
85
  export default manifest;
@@ -1,6 +1,7 @@
1
1
  export { CodeAnalyzer } from '../../../modules/analyzer/CodeAnalyzer.js';
2
2
  export { CamoufoxBrowserManager } from '../../../modules/browser/CamoufoxBrowserManager.js';
3
3
  export { AICaptchaDetector } from '../../../modules/captcha/AICaptchaDetector.js';
4
+ export type { CaptchaType, CaptchaProviderHint, CaptchaDetectionResult, AICaptchaDetectionResult, CaptchaDetectionConfig, } from '../../../modules/captcha/types.js';
4
5
  export { CodeCollector } from '../../../modules/collector/CodeCollector.js';
5
6
  export { DOMInspector } from '../../../modules/collector/DOMInspector.js';
6
7
  export { PageController } from '../../../modules/collector/PageController.js';
@@ -1,4 +1,4 @@
1
- export type ObfuscationType = 'javascript-obfuscator' | 'webpack' | 'uglify' | 'vm-protection' | 'self-modifying' | 'invisible-unicode' | 'control-flow-flattening' | 'string-array-rotation' | 'dead-code-injection' | 'opaque-predicates' | 'jsfuck' | 'aaencode' | 'jjencode' | 'packer' | 'eval-obfuscation' | 'base64-encoding' | 'hex-encoding' | 'jscrambler' | 'urlencoded' | 'custom' | 'unknown';
1
+ export type ObfuscationType = 'javascript-obfuscator' | 'webpack' | 'uglify' | 'vm-protection' | 'self-modifying' | 'invisible-unicode' | 'control-flow-flattening' | 'string-array-rotation' | 'dead-code-injection' | 'opaque-predicates' | 'jsfuck' | 'aaencode' | 'jjencode' | 'packer' | 'eval-obfuscation' | 'base64-encoding' | 'hex-encoding' | 'jscrambler' | 'urlencoded' | 'custom' | 'unknown' | 'bundle-unpack' | 'unminify' | 'jsx-decompile' | 'mangle' | 'webcrack';
2
2
  export interface Transformation {
3
3
  type: string;
4
4
  description: string;
@@ -11,6 +11,42 @@ export interface DeobfuscateOptions {
11
11
  preserveLogic?: boolean;
12
12
  renameVariables?: boolean;
13
13
  inlineFunctions?: boolean;
14
+ unpack?: boolean;
15
+ unminify?: boolean;
16
+ jsx?: boolean;
17
+ mangle?: boolean;
18
+ outputDir?: string;
19
+ forceOutput?: boolean;
20
+ includeModuleCode?: boolean;
21
+ maxBundleModules?: number;
22
+ mappings?: DeobfuscateMappingRule[];
23
+ }
24
+ export interface DeobfuscateMappingRule {
25
+ path: string;
26
+ pattern: string;
27
+ matchType?: 'includes' | 'regex' | 'exact';
28
+ target?: 'code' | 'path';
29
+ }
30
+ export interface DeobfuscateSavedArtifact {
31
+ path: string;
32
+ size: number;
33
+ type: 'file';
34
+ }
35
+ export interface DeobfuscateBundleModuleSummary {
36
+ id: string;
37
+ path: string;
38
+ isEntry: boolean;
39
+ size: number;
40
+ code?: string;
41
+ mappedPathFrom?: string;
42
+ }
43
+ export interface DeobfuscateBundleSummary {
44
+ type: 'webpack' | 'browserify';
45
+ entryId: string;
46
+ moduleCount: number;
47
+ truncated: boolean;
48
+ mappingsApplied?: number;
49
+ modules: DeobfuscateBundleModuleSummary[];
14
50
  }
15
51
  export interface DeobfuscateResult {
16
52
  code: string;
@@ -19,4 +55,10 @@ export interface DeobfuscateResult {
19
55
  obfuscationType: ObfuscationType[];
20
56
  transformations: Transformation[];
21
57
  analysis: string;
58
+ bundle?: DeobfuscateBundleSummary;
59
+ savedTo?: string;
60
+ savedArtifacts?: DeobfuscateSavedArtifact[];
61
+ warnings?: string[];
62
+ engine?: 'legacy' | 'webcrack' | 'hybrid';
63
+ webcrackApplied?: boolean;
22
64
  }
@@ -2,7 +2,7 @@ export type { CodeLocation, Result } from './common.js';
2
2
  export type { Config, LLMConfig, PuppeteerConfig, MCPConfig, CacheConfig, PerformanceConfig, } from './config.js';
3
3
  export type { BrowserContext } from './browser.js';
4
4
  export type { CollectCodeOptions, CodeFile, CollectCodeResult, DependencyGraph, DependencyNode, DependencyEdge, } from './collector.js';
5
- export type { ObfuscationType, Transformation, DeobfuscateOptions, DeobfuscateResult, } from './deobfuscator.js';
5
+ export type { ObfuscationType, Transformation, DeobfuscateOptions, DeobfuscateResult, DeobfuscateMappingRule, DeobfuscateSavedArtifact, DeobfuscateBundleModuleSummary, DeobfuscateBundleSummary, } from './deobfuscator.js';
6
6
  export type { UnderstandCodeOptions, UnderstandCodeResult, CodeStructure, TechStack, BusinessLogic, DataFlow, DataFlowGraph, DataFlowNode, DataFlowEdge, DataSource, DataSink, TaintPath, SecurityRisk, FunctionInfo, ClassInfo, PropertyInfo, ModuleInfo, CallGraph, CallGraphNode, CallGraphEdge, } from './analysis.js';
7
7
  export type { DetectCryptoOptions, DetectCryptoResult, CryptoAlgorithm, CryptoParameters, CryptoLibrary, } from './crypto.js';
8
8
  export type { HookOptions, HookCondition, HookHandler, HookContext, CallStackFrame, HookResult, HookRecord, } from './hook.js';
@@ -6,14 +6,22 @@ const currentFilename = fileURLToPath(import.meta.url);
6
6
  const currentDirname = dirname(currentFilename);
7
7
  export const projectRoot = join(currentDirname, '..', '..');
8
8
  const envPath = join(projectRoot, '.env');
9
- const result = dotenvConfig({ path: envPath, quiet: true });
10
- if (result.error) {
11
- console.error('[Config] Warning: Failed to load .env file from configured path');
12
- console.error(`[Config] Error: ${result.error.message}`);
13
- console.error('[Config] Will use environment variables or defaults');
14
- }
15
- else if (process.env.DEBUG === 'true') {
16
- console.info('[Config] .env file loaded (debug mode)');
9
+ let envLoaded = false;
10
+ function loadEnvIfNeeded() {
11
+ if (envLoaded) {
12
+ return;
13
+ }
14
+ envLoaded = true;
15
+ const result = dotenvConfig({ path: envPath, quiet: true });
16
+ const errorCode = result.error?.code;
17
+ if (result.error && errorCode !== 'ENOENT') {
18
+ console.error('[Config] Warning: Failed to load .env file from configured path');
19
+ console.error(`[Config] Error: ${result.error.message}`);
20
+ console.error('[Config] Will use environment variables or defaults');
21
+ }
22
+ else if (!result.error && process.env.DEBUG === 'true') {
23
+ console.info('[Config] .env file loaded (debug mode)');
24
+ }
17
25
  }
18
26
  const envInt = (fallback) => z.string().optional()
19
27
  .transform((v) => (v ? parseInt(v, 10) : fallback))
@@ -34,7 +42,7 @@ const ConfigSchema = z.object({
34
42
  CHROME_PATH: z.string().optional(),
35
43
  BROWSER_EXECUTABLE_PATH: z.string().optional(),
36
44
  MCP_SERVER_NAME: z.string().optional().default('jshookmcp'),
37
- MCP_SERVER_VERSION: z.string().optional().default('0.1.0'),
45
+ MCP_SERVER_VERSION: z.string().optional().default('0.1.8'),
38
46
  ENABLE_CACHE: envBool(false),
39
47
  CACHE_DIR: z.string().optional().default('.cache'),
40
48
  CACHE_TTL: envInt(3600).pipe(z.number().min(0)),
@@ -42,6 +50,7 @@ const ConfigSchema = z.object({
42
50
  MAX_CODE_SIZE_MB: envInt(10).pipe(z.number().min(1).max(500)),
43
51
  });
44
52
  export function getConfig() {
53
+ loadEnvIfNeeded();
45
54
  const parsed = ConfigSchema.safeParse(process.env);
46
55
  if (!parsed.success) {
47
56
  const issues = parsed.error.issues.map((i) => ` ${i.path.join('.')}: ${i.message}`);
@@ -77,7 +86,7 @@ export function getConfig() {
77
86
  },
78
87
  mcp: {
79
88
  name: env.MCP_SERVER_NAME || 'jshookmcp',
80
- version: env.MCP_SERVER_VERSION || '0.1.0',
89
+ version: env.MCP_SERVER_VERSION || '0.1.8',
81
90
  },
82
91
  cache: {
83
92
  enabled: parsed.success ? env.ENABLE_CACHE : process.env.ENABLE_CACHE === 'true',
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@jshookmcp/jshook",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "MCP server with 244 built-in tools (236 domain tools across 16 domains) for AI-assisted JavaScript analysis and security analysis — browser automation, CDP debugging, network monitoring, JS hooks, code analysis, and workflow orchestration",
5
5
  "mcpName": "io.github.vmoranv/jshookmcp",
6
6
  "main": "dist/index.js",
7
7
  "type": "module",
8
8
  "files": [
9
9
  "dist",
10
- "src/native/scripts"
10
+ "src/native/scripts",
11
+ "scripts/postinstall.cjs"
11
12
  ],
12
13
  "bin": {
13
14
  "jshook": "dist/index.js",
@@ -68,6 +69,7 @@
68
69
  "openai": "^6.25.0",
69
70
  "ora": "^9.3.0",
70
71
  "rebrowser-puppeteer-core": "^24.8.1",
72
+ "webcrack": "^2.15.1",
71
73
  "zod": "^4.3.6"
72
74
  },
73
75
  "optionalDependencies": {
@@ -113,10 +115,11 @@
113
115
  "test": "vitest run",
114
116
  "test:coverage": "cross-env ENABLE_INJECTION_TOOLS=true vitest run --coverage",
115
117
  "package:verify-bin": "node scripts/verify-packed-bin.mjs",
118
+ "package:verify-install": "node scripts/verify-packed-install.mjs",
116
119
  "audit:tools": "node scripts/audit-tools.mjs",
117
120
  "check": "pnpm run lint && pnpm run typecheck && pnpm run test",
118
121
  "package": "pnpm pack",
119
- "postinstall": "lefthook install",
122
+ "postinstall": "node scripts/postinstall.cjs",
120
123
  "install:full": "pnpm install && pnpm exec camoufox-js fetch"
121
124
  }
122
125
  }
@@ -0,0 +1,37 @@
1
+ const fs = require('node:fs');
2
+ const path = require('node:path');
3
+ const { spawnSync } = require('node:child_process');
4
+
5
+ const repoGitDir = path.join(process.cwd(), '.git');
6
+ const localBin = path.join(
7
+ process.cwd(),
8
+ 'node_modules',
9
+ '.bin',
10
+ process.platform === 'win32' ? 'lefthook.cmd' : 'lefthook'
11
+ );
12
+
13
+ if (!fs.existsSync(repoGitDir)) {
14
+ process.exit(0);
15
+ }
16
+
17
+ if (!fs.existsSync(localBin)) {
18
+ console.warn('[postinstall] lefthook not found locally; skipping git hook installation.');
19
+ process.exit(0);
20
+ }
21
+
22
+ const result = spawnSync(localBin, ['install'], {
23
+ stdio: 'inherit',
24
+ shell: process.platform === 'win32',
25
+ });
26
+
27
+ if (result.error) {
28
+ console.warn(
29
+ `[postinstall] lefthook install failed to spawn: ${result.error.message}; skipping git hook installation.`
30
+ );
31
+ } else if (result.status !== 0) {
32
+ console.warn(
33
+ `[postinstall] lefthook install exited with status ${result.status}; skipping git hook installation.`
34
+ );
35
+ }
36
+
37
+ process.exit(0);