@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.
- package/README.md +145 -100
- package/README.zh.md +81 -36
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +3 -1
- package/dist/modules/analyzer/QualityAnalyzer.js +1 -1
- package/dist/modules/browser/BrowserDiscovery.js +2 -2
- package/dist/modules/browser/BrowserModeManager.js +3 -3
- package/dist/modules/captcha/AICaptchaDetector.d.ts +12 -16
- package/dist/modules/captcha/AICaptchaDetector.js +209 -189
- package/dist/modules/captcha/CaptchaDetector.constants.d.ts +2 -0
- package/dist/modules/captcha/CaptchaDetector.constants.js +116 -25
- package/dist/modules/captcha/CaptchaDetector.d.ts +2 -11
- package/dist/modules/captcha/CaptchaDetector.js +102 -51
- package/dist/modules/captcha/types.d.ts +46 -0
- package/dist/modules/captcha/types.js +52 -0
- package/dist/modules/deobfuscator/AdvancedDeobfuscator.d.ts +15 -20
- package/dist/modules/deobfuscator/AdvancedDeobfuscator.js +66 -234
- package/dist/modules/deobfuscator/Deobfuscator.d.ts +3 -10
- package/dist/modules/deobfuscator/Deobfuscator.js +125 -404
- package/dist/modules/deobfuscator/webcrack.d.ts +13 -0
- package/dist/modules/deobfuscator/webcrack.js +164 -0
- package/dist/modules/detector/ObfuscationDetector.d.ts +6 -0
- package/dist/modules/detector/ObfuscationDetector.js +53 -2
- package/dist/modules/hook/AIHookGenerator.js +1 -1
- package/dist/modules/process/memory/writer.js +1 -1
- package/dist/server/domains/analysis/definitions.js +223 -2
- package/dist/server/domains/analysis/handlers.impl.d.ts +2 -3
- package/dist/server/domains/analysis/handlers.impl.js +60 -15
- package/dist/server/domains/analysis/manifest.js +2 -5
- package/dist/server/domains/browser/definitions.tools.behavior.js +36 -24
- package/dist/server/domains/browser/definitions.tools.security.js +13 -10
- package/dist/server/domains/browser/handlers/camoufox-flow.js +0 -1
- package/dist/server/domains/browser/handlers/captcha-solver.d.ts +1 -1
- package/dist/server/domains/browser/handlers/captcha-solver.js +121 -54
- package/dist/server/domains/browser/handlers/page-navigation.js +0 -2
- package/dist/server/domains/browser/handlers.impl.d.ts +1 -1
- package/dist/server/domains/browser/handlers.impl.js +3 -3
- package/dist/server/domains/browser/manifest.js +1 -1
- package/dist/server/domains/shared/modules.d.ts +1 -0
- package/dist/types/deobfuscator.d.ts +43 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/utils/config.js +19 -10
- package/package.json +6 -3
- 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
|
-
|
|
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,
|
|
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
|
|
385
|
-
return
|
|
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('
|
|
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
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -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';
|
package/dist/utils/config.js
CHANGED
|
@@ -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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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": "
|
|
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);
|