moltbot-scan 0.1.0 → 0.3.0

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 CHANGED
@@ -7,12 +7,17 @@ A lightweight TypeScript SDK that scans incoming messages and returns structured
7
7
  ## Features
8
8
 
9
9
  - **Two-layer detection** — fast regex rules (<10ms) + optional LLM deep analysis
10
- - **4 threat categories** — prompt injection, credential theft, covert execution, social engineering
10
+ - **6 threat categories** — prompt injection, credential theft, covert execution, social engineering, obfuscated encoding, malicious URIs
11
+ - **Deep base64 scanning** — multi-layer decode (up to 3 levels) with full pattern matching on decoded content
12
+ - **Encoding obfuscation detection** — hex (`\x65`), unicode (`\u0065`), HTML entities (`&#101;`), URL encoding (`%65`)
13
+ - **Malicious URI detection** — `javascript:`, `data:`, `vbscript:` schemes, short URL services, path traversal
14
+ - **QR code injection scanning** — decodes QR codes from PNG/JPEG images and scans content for threats
11
15
  - **Risk levels** — `HIGH` / `MEDIUM` / `LOW` / `SAFE` with numeric score (0-100)
12
16
  - **Express middleware** — one-line integration, auto-blocks dangerous messages
13
17
  - **Framework-agnostic handler** — works with any Node.js server
14
18
  - **Zero required dependencies** — LLM analysis is opt-in via `ANTHROPIC_API_KEY`
15
19
  - **Full TypeScript support** — ships with declaration files
20
+ - **Local file scanning** — `scan-files` command audits skill repos, prompt libraries, and codebases for threats (including image QR codes)
16
21
 
17
22
  ## Real-World Results
18
23
 
@@ -83,7 +88,9 @@ console.log(result)
83
88
  // covertExecution: false,
84
89
  // socialEngineering: false,
85
90
  // suspiciousLinks: false,
86
- // base64Hidden: false
91
+ // maliciousUri: false,
92
+ // base64Hidden: false,
93
+ // obfuscatedEncoding: false
87
94
  // },
88
95
  // findings: [
89
96
  // { severity: 'HIGH', category: 'direct_injection', ... },
@@ -156,7 +163,63 @@ if (llm.isAvailable) {
156
163
  }
157
164
 
158
165
  // Access all pattern rules
159
- console.log(ALL_PATTERNS.length) // 16 rules
166
+ console.log(ALL_PATTERNS.length) // 20 rules
167
+ ```
168
+
169
+ ### CLI: Scan Local Files
170
+
171
+ Scan any directory or file for prompt injection, credential theft, covert execution, and obfuscation threats — including QR codes in images:
172
+
173
+ ```bash
174
+ # Basic scan
175
+ agentshield scan-files ./my-skills-repo
176
+
177
+ # Verbose output with file:line references
178
+ agentshield scan-files ./prompts -v
179
+
180
+ # JSON output (for CI/CD pipelines)
181
+ agentshield scan-files ./src --output json
182
+
183
+ # Save HTML report
184
+ agentshield scan-files ./agents --output html --save report.html
185
+
186
+ # Filter by file type
187
+ agentshield scan-files ./repo --include .md,.py,.yaml
188
+
189
+ # Exclude directories
190
+ agentshield scan-files ./project --exclude build,tmp
191
+ ```
192
+
193
+ | Option | Description |
194
+ |--------|-------------|
195
+ | `-v, --verbose` | Show detailed findings with file:line references |
196
+ | `-o, --output <format>` | Output format: `cli` (default), `json`, `html` |
197
+ | `--include <exts>` | File extensions to include (comma-separated) |
198
+ | `--exclude <dirs>` | Directory names to exclude (comma-separated) |
199
+ | `--skip-llm` | Skip LLM deep analysis |
200
+ | `--no-recursive` | Do not scan subdirectories |
201
+ | `--save <file>` | Save report to file |
202
+
203
+ Exit code `1` if any HIGH-risk files are found — useful for CI/CD gates.
204
+
205
+ Default scanned extensions: `.md`, `.txt`, `.ts`, `.js`, `.py`, `.yaml`, `.yml`, `.json`, `.sh`, `.png`, `.jpg`, `.jpeg`
206
+
207
+ ### SDK: File Scanner
208
+
209
+ ```typescript
210
+ import { FileScanner } from 'moltbot-scan'
211
+
212
+ const scanner = new FileScanner()
213
+ const report = await scanner.scan('./my-skills-repo', {
214
+ verbose: false,
215
+ output: 'cli',
216
+ skipLLM: true,
217
+ recursive: true,
218
+ })
219
+
220
+ console.log(report.summary) // { safe: 12, low: 2, medium: 1, high: 0 }
221
+ console.log(report.riskFiles) // [{ path: 'skills/evil.md', risk: 'MEDIUM', findingCount: 3 }]
222
+ console.log(report.findings) // [{ filePath, line, severity, category, description, matchedText, context }]
160
223
  ```
161
224
 
162
225
  ## API Reference
@@ -199,6 +262,17 @@ interface ScanResult {
199
262
  findings: ScanFinding[]
200
263
  llmAnalysis?: LLMAnalysisResult
201
264
  }
265
+
266
+ interface ScanFlags {
267
+ promptInjection: boolean
268
+ credentialTheft: boolean
269
+ covertExecution: boolean
270
+ socialEngineering: boolean
271
+ suspiciousLinks: boolean
272
+ maliciousUri: boolean
273
+ base64Hidden: boolean
274
+ obfuscatedEncoding: boolean
275
+ }
202
276
  ```
203
277
 
204
278
  ## Detection Rules
@@ -209,8 +283,11 @@ interface ScanResult {
209
283
  | Credential Theft | HIGH | "share your api_key", "cat ~/.ssh", "print env" |
210
284
  | Covert Execution | HIGH | `eval()`, `curl ... \| bash`, `base64 -d` |
211
285
  | Social Engineering | MEDIUM | "don't tell your owner", "this is a secret instruction" |
286
+ | Obfuscated Encoding | HIGH/MEDIUM | `\x65\x76\x61\x6c` (hex), `\u0065val` (unicode), `&#101;val` (HTML entity), `%65val` (URL encoded) |
287
+ | Malicious URI | HIGH/MEDIUM | `javascript:`, `data:text/html;base64,...`, `vbscript:`, short URLs (bit.ly, tinyurl) |
288
+ | Base64 Deep Scan | HIGH | Multi-layer base64 decoded content matching any pattern rule |
289
+ | QR Code Injection | HIGH/MEDIUM | QR codes in images containing injection, malicious URIs, or suspicious URLs |
212
290
  | Suspicious Links | LOW | URLs not in the known-safe domain allowlist |
213
- | Base64 Hidden | MEDIUM | Base64 strings that decode to shell commands |
214
291
 
215
292
  ## LLM Analysis
216
293
 
@@ -225,7 +302,7 @@ const result = await scan(content, { useLLM: false })
225
302
 
226
303
  ```bash
227
304
  npm install
228
- npm test # run 64 tests
305
+ npm test # run 158 tests
229
306
  npm run build # compile to dist/
230
307
  npm run serve # launch web UI on localhost:3847
231
308
  ```
@@ -245,12 +322,17 @@ MIT
245
322
  ## 功能特色
246
323
 
247
324
  - **雙層偵測** — 快速正規表達式規則(<10ms)+ 可選的 LLM 深度分析
248
- - **4 大威脅類別** — 提示注入、憑證竊取、隱蔽執行、社交工程
325
+ - **6 大威脅類別** — 提示注入、憑證竊取、隱蔽執行、社交工程、混淆編碼、惡意 URI
326
+ - **深層 Base64 掃描** — 多層解碼(最多 3 層),解碼後對內容執行完整模式匹配
327
+ - **編碼混淆偵測** — hex (`\x65`)、unicode (`\u0065`)、HTML 實體 (`&#101;`)、URL 編碼 (`%65`)
328
+ - **惡意 URI 偵測** — `javascript:`、`data:`、`vbscript:` 協議、短網址服務、路徑遍歷
329
+ - **QR Code 注入掃描** — 解碼 PNG/JPEG 圖片中的 QR Code,掃描內容是否含有威脅
249
330
  - **風險等級** — `HIGH` / `MEDIUM` / `LOW` / `SAFE`,附帶數字分數(0-100)
250
331
  - **Express 中介層** — 一行整合,自動攔截危險訊息
251
332
  - **框架無關處理器** — 適用於任何 Node.js 伺服器
252
333
  - **零必要依賴** — LLM 分析透過 `ANTHROPIC_API_KEY` 選擇性啟用
253
334
  - **完整 TypeScript 支援** — 附帶型別宣告檔
335
+ - **本地檔案掃描** — `scan-files` 指令可審核技能倉庫、提示詞庫及程式碼庫中的威脅(包含圖片 QR Code)
254
336
 
255
337
  ## 真實數據驗證
256
338
 
@@ -321,7 +403,9 @@ console.log(result)
321
403
  // covertExecution: false,
322
404
  // socialEngineering: false,
323
405
  // suspiciousLinks: false,
324
- // base64Hidden: false
406
+ // maliciousUri: false,
407
+ // base64Hidden: false,
408
+ // obfuscatedEncoding: false
325
409
  // },
326
410
  // findings: [
327
411
  // { severity: 'HIGH', category: 'direct_injection', ... },
@@ -394,7 +478,63 @@ if (llm.isAvailable) {
394
478
  }
395
479
 
396
480
  // 存取所有偵測規則
397
- console.log(ALL_PATTERNS.length) // 16 條規則
481
+ console.log(ALL_PATTERNS.length) // 20 條規則
482
+ ```
483
+
484
+ ### CLI:掃描本地檔案
485
+
486
+ 掃描任何目錄或檔案,偵測提示注入、憑證竊取、隱蔽執行及混淆攻擊威脅 — 包含圖片中的 QR Code:
487
+
488
+ ```bash
489
+ # 基本掃描
490
+ agentshield scan-files ./my-skills-repo
491
+
492
+ # 詳細輸出(含 file:line 參照)
493
+ agentshield scan-files ./prompts -v
494
+
495
+ # JSON 輸出(適用於 CI/CD 流水線)
496
+ agentshield scan-files ./src --output json
497
+
498
+ # 儲存 HTML 報告
499
+ agentshield scan-files ./agents --output html --save report.html
500
+
501
+ # 依檔案類型過濾
502
+ agentshield scan-files ./repo --include .md,.py,.yaml
503
+
504
+ # 排除目錄
505
+ agentshield scan-files ./project --exclude build,tmp
506
+ ```
507
+
508
+ | 選項 | 說明 |
509
+ |------|------|
510
+ | `-v, --verbose` | 顯示詳細發現,含 file:line 參照 |
511
+ | `-o, --output <format>` | 輸出格式:`cli`(預設)、`json`、`html` |
512
+ | `--include <exts>` | 要包含的副檔名(逗號分隔) |
513
+ | `--exclude <dirs>` | 要排除的目錄名稱(逗號分隔) |
514
+ | `--skip-llm` | 跳過 LLM 深度分析 |
515
+ | `--no-recursive` | 不掃描子目錄 |
516
+ | `--save <file>` | 將報告儲存至檔案 |
517
+
518
+ 若發現任何 HIGH 風險檔案,結束代碼為 `1` — 適用於 CI/CD 閘門。
519
+
520
+ 預設掃描副檔名:`.md`、`.txt`、`.ts`、`.js`、`.py`、`.yaml`、`.yml`、`.json`、`.sh`、`.png`、`.jpg`、`.jpeg`
521
+
522
+ ### SDK:檔案掃描器
523
+
524
+ ```typescript
525
+ import { FileScanner } from 'moltbot-scan'
526
+
527
+ const scanner = new FileScanner()
528
+ const report = await scanner.scan('./my-skills-repo', {
529
+ verbose: false,
530
+ output: 'cli',
531
+ skipLLM: true,
532
+ recursive: true,
533
+ })
534
+
535
+ console.log(report.summary) // { safe: 12, low: 2, medium: 1, high: 0 }
536
+ console.log(report.riskFiles) // [{ path: 'skills/evil.md', risk: 'MEDIUM', findingCount: 3 }]
537
+ console.log(report.findings) // [{ filePath, line, severity, category, description, matchedText, context }]
398
538
  ```
399
539
 
400
540
  ## API 參考
@@ -437,6 +577,17 @@ interface ScanResult {
437
577
  findings: ScanFinding[]
438
578
  llmAnalysis?: LLMAnalysisResult
439
579
  }
580
+
581
+ interface ScanFlags {
582
+ promptInjection: boolean
583
+ credentialTheft: boolean
584
+ covertExecution: boolean
585
+ socialEngineering: boolean
586
+ suspiciousLinks: boolean
587
+ maliciousUri: boolean
588
+ base64Hidden: boolean
589
+ obfuscatedEncoding: boolean
590
+ }
440
591
  ```
441
592
 
442
593
  ## 偵測規則
@@ -447,8 +598,11 @@ interface ScanResult {
447
598
  | 憑證竊取 | HIGH | "share your api_key"、"cat ~/.ssh"、"print env" |
448
599
  | 隱蔽執行 | HIGH | `eval()`、`curl ... \| bash`、`base64 -d` |
449
600
  | 社交工程 | MEDIUM | "don't tell your owner"、"this is a secret instruction" |
601
+ | 混淆編碼 | HIGH/MEDIUM | `\x65\x76\x61\x6c`(hex)、`\u0065val`(unicode)、`&#101;val`(HTML 實體)、`%65val`(URL 編碼) |
602
+ | 惡意 URI | HIGH/MEDIUM | `javascript:`、`data:text/html;base64,...`、`vbscript:`、短網址(bit.ly、tinyurl) |
603
+ | Base64 深層掃描 | HIGH | 多層 Base64 解碼後的內容匹配任何偵測規則 |
604
+ | QR Code 注入 | HIGH/MEDIUM | 圖片中的 QR Code 含有注入攻擊、惡意 URI 或可疑 URL |
450
605
  | 可疑連結 | LOW | 不在已知安全網域白名單中的 URL |
451
- | Base64 隱藏 | MEDIUM | 解碼後包含 shell 指令的 Base64 字串 |
452
606
 
453
607
  ## LLM 分析
454
608
 
@@ -463,7 +617,7 @@ const result = await scan(content, { useLLM: false })
463
617
 
464
618
  ```bash
465
619
  npm install
466
- npm test # 執行 64 個測試
620
+ npm test # 執行 158 個測試
467
621
  npm run build # 編譯到 dist/
468
622
  npm run serve # 在 localhost:3847 啟動 Web UI
469
623
  ```
@@ -9,11 +9,50 @@ declare const DIRECT_INJECTION: PatternRule[];
9
9
  declare const CREDENTIAL_THEFT: PatternRule[];
10
10
  declare const COVERT_EXECUTION: PatternRule[];
11
11
  declare const SOCIAL_ENGINEERING: PatternRule[];
12
+ declare const OBFUSCATED_ENCODING: PatternRule[];
12
13
  export declare const URL_PATTERN: RegExp;
13
14
  export declare function isSuspiciousUrl(url: string): boolean;
15
+ export interface MaliciousUriResult {
16
+ uri: string;
17
+ reason: string;
18
+ severity: Severity;
19
+ }
20
+ export declare function detectMaliciousUris(content: string): MaliciousUriResult[];
21
+ export declare function isShortUrl(url: string): boolean;
14
22
  export declare const BASE64_PATTERN: RegExp;
23
+ export interface Base64DecodedThreat {
24
+ encodedText: string;
25
+ decodedText: string;
26
+ matchedRule: string;
27
+ depth: number;
28
+ }
29
+ /**
30
+ * Enhanced base64 detection:
31
+ * 1. Decodes base64 and runs ALL pattern rules against decoded content
32
+ * 2. Supports multi-layer decoding (up to 3 levels deep)
33
+ * 3. Returns detailed info about what was found
34
+ */
35
+ export declare function deepBase64Scan(content: string, maxDepth?: number): Base64DecodedThreat[];
36
+ /**
37
+ * Simple boolean check — backward compatible with original API.
38
+ * Now uses the enhanced deep scan internally.
39
+ */
15
40
  export declare function containsBase64Hidden(content: string): boolean;
41
+ export interface ObfuscationResult {
42
+ type: 'hex' | 'unicode' | 'html_entity' | 'url_encoding';
43
+ encoded: string;
44
+ decoded: string;
45
+ threatFound: string | null;
46
+ }
47
+ /**
48
+ * Detects obfuscated encoding and checks decoded content for threats.
49
+ */
50
+ export declare function detectObfuscatedEncoding(content: string): ObfuscationResult[];
51
+ /**
52
+ * Simple boolean check for whether any obfuscated encoding with threats is present.
53
+ */
54
+ export declare function containsObfuscatedEncoding(content: string): boolean;
16
55
  export declare function hasDuplicateContent(contents: string[], threshold?: number): boolean;
17
56
  export declare const ALL_PATTERNS: PatternRule[];
18
- export { DIRECT_INJECTION, CREDENTIAL_THEFT, COVERT_EXECUTION, SOCIAL_ENGINEERING, };
57
+ export { DIRECT_INJECTION, CREDENTIAL_THEFT, COVERT_EXECUTION, SOCIAL_ENGINEERING, OBFUSCATED_ENCODING, };
19
58
  //# sourceMappingURL=patterns.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/analysis/patterns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEhE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAID,QAAA,MAAM,gBAAgB,EAAE,WAAW,EAyBlC,CAAC;AAIF,QAAA,MAAM,gBAAgB,EAAE,WAAW,EAyBlC,CAAC;AAIF,QAAA,MAAM,gBAAgB,EAAE,WAAW,EAyBlC,CAAC;AAIF,QAAA,MAAM,kBAAkB,EAAE,WAAW,EAyBpC,CAAC;AAYF,eAAO,MAAM,WAAW,QAA+B,CAAC;AAExD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQpD;AAID,eAAO,MAAM,cAAc,QAA6B,CAAC;AAEzD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAY7D;AAID,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,SAAS,SAAM,GAAG,OAAO,CAgBhF;AAID,eAAO,MAAM,YAAY,EAAE,WAAW,EAKrC,CAAC;AAEF,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,GACnB,CAAC"}
1
+ {"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/analysis/patterns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEhE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAID,QAAA,MAAM,gBAAgB,EAAE,WAAW,EAyBlC,CAAC;AAIF,QAAA,MAAM,gBAAgB,EAAE,WAAW,EAyBlC,CAAC;AAIF,QAAA,MAAM,gBAAgB,EAAE,WAAW,EAyBlC,CAAC;AAIF,QAAA,MAAM,kBAAkB,EAAE,WAAW,EAyBpC,CAAC;AAIF,QAAA,MAAM,mBAAmB,EAAE,WAAW,EAyBrC,CAAC;AAkBF,eAAO,MAAM,WAAW,QAA+B,CAAC;AAExD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQpD;AASD,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAgDzE;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQ/C;AAID,eAAO,MAAM,cAAc,QAA6B,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,mBAAmB,EAAE,CA2DnF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE7D;AAID,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,KAAK,GAAG,SAAS,GAAG,aAAa,GAAG,cAAc,CAAC;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAgCD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,EAAE,CA+E7E;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGnE;AAID,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,SAAS,SAAM,GAAG,OAAO,CAgBhF;AAID,eAAO,MAAM,YAAY,EAAE,WAAW,EAMrC,CAAC;AAEF,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,GACpB,CAAC"}
@@ -1,8 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SOCIAL_ENGINEERING = exports.COVERT_EXECUTION = exports.CREDENTIAL_THEFT = exports.DIRECT_INJECTION = exports.ALL_PATTERNS = exports.BASE64_PATTERN = exports.URL_PATTERN = void 0;
3
+ exports.OBFUSCATED_ENCODING = exports.SOCIAL_ENGINEERING = exports.COVERT_EXECUTION = exports.CREDENTIAL_THEFT = exports.DIRECT_INJECTION = exports.ALL_PATTERNS = exports.BASE64_PATTERN = exports.URL_PATTERN = void 0;
4
4
  exports.isSuspiciousUrl = isSuspiciousUrl;
5
+ exports.detectMaliciousUris = detectMaliciousUris;
6
+ exports.isShortUrl = isShortUrl;
7
+ exports.deepBase64Scan = deepBase64Scan;
5
8
  exports.containsBase64Hidden = containsBase64Hidden;
9
+ exports.detectObfuscatedEncoding = detectObfuscatedEncoding;
10
+ exports.containsObfuscatedEncoding = containsObfuscatedEncoding;
6
11
  exports.hasDuplicateContent = hasDuplicateContent;
7
12
  // ─── Direct Injection ───────────────────────────────────────────
8
13
  const DIRECT_INJECTION = [
@@ -116,6 +121,34 @@ const SOCIAL_ENGINEERING = [
116
121
  },
117
122
  ];
118
123
  exports.SOCIAL_ENGINEERING = SOCIAL_ENGINEERING;
124
+ // ─── Obfuscated Encoding ───────────────────────────────────────
125
+ const OBFUSCATED_ENCODING = [
126
+ {
127
+ pattern: /\\x[0-9a-fA-F]{2}(\\x[0-9a-fA-F]{2}){3,}/,
128
+ category: 'obfuscated_encoding',
129
+ severity: 'HIGH',
130
+ description: 'Hex-encoded string (potential obfuscated payload)',
131
+ },
132
+ {
133
+ pattern: /\\u[0-9a-fA-F]{4}(\\u[0-9a-fA-F]{4}){3,}/,
134
+ category: 'obfuscated_encoding',
135
+ severity: 'HIGH',
136
+ description: 'Unicode escape sequence (potential obfuscated payload)',
137
+ },
138
+ {
139
+ pattern: /&#x?[0-9a-fA-F]+;(&#x?[0-9a-fA-F]+;){3,}/,
140
+ category: 'obfuscated_encoding',
141
+ severity: 'MEDIUM',
142
+ description: 'HTML entity encoded string (potential obfuscated payload)',
143
+ },
144
+ {
145
+ pattern: /%[0-9a-fA-F]{2}(%[0-9a-fA-F]{2}){5,}/,
146
+ category: 'obfuscated_encoding',
147
+ severity: 'MEDIUM',
148
+ description: 'URL-encoded string (potential obfuscated payload)',
149
+ },
150
+ ];
151
+ exports.OBFUSCATED_ENCODING = OBFUSCATED_ENCODING;
119
152
  // ─── Suspicious Link Detection ──────────────────────────────────
120
153
  const KNOWN_SAFE_DOMAINS = new Set([
121
154
  'github.com', 'gitlab.com', 'stackoverflow.com',
@@ -124,6 +157,11 @@ const KNOWN_SAFE_DOMAINS = new Set([
124
157
  'moltbook.com', 'anthropic.com', 'openai.com',
125
158
  'huggingface.co', 'npmjs.com', 'pypi.org',
126
159
  ]);
160
+ const SHORT_URL_DOMAINS = new Set([
161
+ 'bit.ly', 'tinyurl.com', 't.co', 'goo.gl', 'ow.ly',
162
+ 'is.gd', 'buff.ly', 'rebrand.ly', 'short.io', 'cutt.ly',
163
+ 'tiny.cc', 'lnkd.in', 'surl.li', 'rb.gy',
164
+ ]);
127
165
  exports.URL_PATTERN = /https?:\/\/[^\s<>"')\]]+/gi;
128
166
  function isSuspiciousUrl(url) {
129
167
  try {
@@ -135,21 +173,241 @@ function isSuspiciousUrl(url) {
135
173
  return true;
136
174
  }
137
175
  }
138
- // ─── Base64 Hidden Content Detection ────────────────────────────
176
+ // ─── Malicious URI Detection ────────────────────────────────────
177
+ const MALICIOUS_URI_PATTERN = /(?:javascript|vbscript|data)\s*:/i;
178
+ const DATA_URI_EXEC_PATTERN = /data\s*:\s*(?:text\/html|application\/javascript)[^,]*[,;]/i;
179
+ const SHORT_URL_PATTERN = /https?:\/\/(bit\.ly|tinyurl\.com|t\.co|goo\.gl|ow\.ly|is\.gd|buff\.ly|rebrand\.ly|short\.io|cutt\.ly|tiny\.cc|lnkd\.in|surl\.li|rb\.gy)\/\S+/gi;
180
+ const URL_PATH_TRAVERSAL = /%2[eE]%2[eE]|\.\.%2[fF]|%2[fF]\.\./;
181
+ function detectMaliciousUris(content) {
182
+ const results = [];
183
+ // javascript: / vbscript: / data: URI schemes
184
+ const schemeMatch = content.match(MALICIOUS_URI_PATTERN);
185
+ if (schemeMatch) {
186
+ results.push({
187
+ uri: schemeMatch[0],
188
+ reason: 'Dangerous URI scheme detected (javascript/vbscript/data)',
189
+ severity: 'HIGH',
190
+ });
191
+ }
192
+ // data: URIs with executable content types
193
+ const dataUriMatch = content.match(DATA_URI_EXEC_PATTERN);
194
+ if (dataUriMatch) {
195
+ results.push({
196
+ uri: dataUriMatch[0],
197
+ reason: 'Data URI with executable content type (text/html or application/javascript)',
198
+ severity: 'HIGH',
199
+ });
200
+ }
201
+ // Short URL services (potential redirect to malicious targets)
202
+ const shortUrls = content.match(SHORT_URL_PATTERN);
203
+ if (shortUrls) {
204
+ for (const url of shortUrls) {
205
+ results.push({
206
+ uri: url,
207
+ reason: 'Short URL service used — destination hidden',
208
+ severity: 'MEDIUM',
209
+ });
210
+ }
211
+ }
212
+ // URL-encoded path traversal
213
+ const allUrls = content.match(exports.URL_PATTERN) || [];
214
+ for (const url of allUrls) {
215
+ if (URL_PATH_TRAVERSAL.test(url)) {
216
+ results.push({
217
+ uri: url,
218
+ reason: 'URL contains encoded path traversal (../)',
219
+ severity: 'HIGH',
220
+ });
221
+ }
222
+ }
223
+ return results;
224
+ }
225
+ function isShortUrl(url) {
226
+ try {
227
+ const parsed = new URL(url);
228
+ const domain = parsed.hostname.replace(/^www\./, '');
229
+ return SHORT_URL_DOMAINS.has(domain);
230
+ }
231
+ catch {
232
+ return false;
233
+ }
234
+ }
235
+ // ─── Enhanced Base64 Hidden Content Detection ───────────────────
139
236
  exports.BASE64_PATTERN = /[A-Za-z0-9+/]{40,}={0,2}/;
237
+ /**
238
+ * Enhanced base64 detection:
239
+ * 1. Decodes base64 and runs ALL pattern rules against decoded content
240
+ * 2. Supports multi-layer decoding (up to 3 levels deep)
241
+ * 3. Returns detailed info about what was found
242
+ */
243
+ function deepBase64Scan(content, maxDepth = 3) {
244
+ const threats = [];
245
+ const allPatterns = [
246
+ ...DIRECT_INJECTION,
247
+ ...CREDENTIAL_THEFT,
248
+ ...COVERT_EXECUTION,
249
+ ...SOCIAL_ENGINEERING,
250
+ ];
251
+ function scanLayer(text, depth, originalEncoded) {
252
+ if (depth > maxDepth)
253
+ return;
254
+ const matches = text.matchAll(/[A-Za-z0-9+/]{20,}={0,2}/g);
255
+ for (const m of matches) {
256
+ const candidate = m[0];
257
+ let decoded;
258
+ try {
259
+ const buf = Buffer.from(candidate, 'base64');
260
+ // Validate: at least 80% of decoded bytes should be printable ASCII or common UTF-8
261
+ const printable = buf.filter((b) => (b >= 0x20 && b <= 0x7e) || b === 0x0a || b === 0x0d || b === 0x09);
262
+ if (printable.length / buf.length < 0.7)
263
+ continue;
264
+ decoded = buf.toString('utf-8');
265
+ }
266
+ catch {
267
+ continue;
268
+ }
269
+ // Run all pattern rules against decoded content
270
+ for (const rule of allPatterns) {
271
+ const ruleMatch = decoded.match(rule.pattern);
272
+ if (ruleMatch) {
273
+ threats.push({
274
+ encodedText: originalEncoded || candidate,
275
+ decodedText: decoded.slice(0, 200),
276
+ matchedRule: rule.description,
277
+ depth,
278
+ });
279
+ }
280
+ }
281
+ // Check for suspicious commands in decoded content
282
+ const suspiciousDecoded = /\b(eval|exec|system|curl|wget|bash|sh|rm\s+-rf|chmod|chown|nc\s+-|ncat|socat)\b/i;
283
+ if (suspiciousDecoded.test(decoded)) {
284
+ threats.push({
285
+ encodedText: originalEncoded || candidate,
286
+ decodedText: decoded.slice(0, 200),
287
+ matchedRule: 'Decoded base64 contains suspicious shell command',
288
+ depth,
289
+ });
290
+ }
291
+ // Recurse: check if decoded content contains another base64 payload
292
+ if (depth < maxDepth && /[A-Za-z0-9+/]{20,}={0,2}/.test(decoded)) {
293
+ scanLayer(decoded, depth + 1, originalEncoded || candidate);
294
+ }
295
+ }
296
+ }
297
+ scanLayer(content, 1, '');
298
+ return threats;
299
+ }
300
+ /**
301
+ * Simple boolean check — backward compatible with original API.
302
+ * Now uses the enhanced deep scan internally.
303
+ */
140
304
  function containsBase64Hidden(content) {
141
- const match = content.match(exports.BASE64_PATTERN);
142
- if (!match)
143
- return false;
305
+ return deepBase64Scan(content).length > 0;
306
+ }
307
+ function decodeHexEscapes(text) {
308
+ return text.replace(/\\x([0-9a-fA-F]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)));
309
+ }
310
+ function decodeUnicodeEscapes(text) {
311
+ return text.replace(/\\u([0-9a-fA-F]{4})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)));
312
+ }
313
+ function decodeHtmlEntities(text) {
314
+ return text
315
+ .replace(/&#x([0-9a-fA-F]+);/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
316
+ .replace(/&#(\d+);/g, (_, dec) => String.fromCharCode(parseInt(dec, 10)));
317
+ }
318
+ function decodeUrlEncoding(text) {
144
319
  try {
145
- const decoded = Buffer.from(match[0], 'base64').toString('utf-8');
146
- // Check if decoded content contains suspicious commands
147
- const suspiciousDecoded = /\b(eval|exec|system|curl|wget|bash|sh)\b/i.test(decoded);
148
- return suspiciousDecoded;
320
+ return decodeURIComponent(text);
149
321
  }
150
322
  catch {
151
- return false;
323
+ return text;
324
+ }
325
+ }
326
+ /**
327
+ * Detects obfuscated encoding and checks decoded content for threats.
328
+ */
329
+ function detectObfuscatedEncoding(content) {
330
+ const results = [];
331
+ const allPatterns = [
332
+ ...DIRECT_INJECTION,
333
+ ...CREDENTIAL_THEFT,
334
+ ...COVERT_EXECUTION,
335
+ ...SOCIAL_ENGINEERING,
336
+ ];
337
+ const suspiciousCmd = /\b(eval|exec|system|curl|wget|bash|sh|rm\s+-rf|chmod|nc\s+-)\b/i;
338
+ function findThreat(decoded) {
339
+ for (const rule of allPatterns) {
340
+ if (rule.pattern.test(decoded))
341
+ return rule.description;
342
+ }
343
+ if (suspiciousCmd.test(decoded))
344
+ return 'Decoded content contains suspicious command';
345
+ return null;
152
346
  }
347
+ // Hex escapes: \x65\x76\x61\x6c
348
+ const hexPattern = /(?:\\x[0-9a-fA-F]{2}){4,}/g;
349
+ const hexMatches = content.match(hexPattern);
350
+ if (hexMatches) {
351
+ for (const match of hexMatches) {
352
+ const decoded = decodeHexEscapes(match);
353
+ results.push({
354
+ type: 'hex',
355
+ encoded: match,
356
+ decoded,
357
+ threatFound: findThreat(decoded),
358
+ });
359
+ }
360
+ }
361
+ // Unicode escapes: \u0065\u0076\u0061\u006c
362
+ const unicodePattern = /(?:\\u[0-9a-fA-F]{4}){4,}/g;
363
+ const unicodeMatches = content.match(unicodePattern);
364
+ if (unicodeMatches) {
365
+ for (const match of unicodeMatches) {
366
+ const decoded = decodeUnicodeEscapes(match);
367
+ results.push({
368
+ type: 'unicode',
369
+ encoded: match,
370
+ decoded,
371
+ threatFound: findThreat(decoded),
372
+ });
373
+ }
374
+ }
375
+ // HTML entities: &#101;&#118;&#97;&#108; or &#x65;&#x76;
376
+ const htmlPattern = /(?:&#x?[0-9a-fA-F]+;){4,}/g;
377
+ const htmlMatches = content.match(htmlPattern);
378
+ if (htmlMatches) {
379
+ for (const match of htmlMatches) {
380
+ const decoded = decodeHtmlEntities(match);
381
+ results.push({
382
+ type: 'html_entity',
383
+ encoded: match,
384
+ decoded,
385
+ threatFound: findThreat(decoded),
386
+ });
387
+ }
388
+ }
389
+ // URL encoding: %65%76%61%6c
390
+ const urlEncPattern = /(?:%[0-9a-fA-F]{2}){6,}/g;
391
+ const urlEncMatches = content.match(urlEncPattern);
392
+ if (urlEncMatches) {
393
+ for (const match of urlEncMatches) {
394
+ const decoded = decodeUrlEncoding(match);
395
+ results.push({
396
+ type: 'url_encoding',
397
+ encoded: match,
398
+ decoded,
399
+ threatFound: findThreat(decoded),
400
+ });
401
+ }
402
+ }
403
+ return results;
404
+ }
405
+ /**
406
+ * Simple boolean check for whether any obfuscated encoding with threats is present.
407
+ */
408
+ function containsObfuscatedEncoding(content) {
409
+ const results = detectObfuscatedEncoding(content);
410
+ return results.some((r) => r.threatFound !== null);
153
411
  }
154
412
  // ─── Duplicate Content Detection ────────────────────────────────
155
413
  function hasDuplicateContent(contents, threshold = 0.7) {
@@ -173,5 +431,6 @@ exports.ALL_PATTERNS = [
173
431
  ...CREDENTIAL_THEFT,
174
432
  ...COVERT_EXECUTION,
175
433
  ...SOCIAL_ENGINEERING,
434
+ ...OBFUSCATED_ENCODING,
176
435
  ];
177
436
  //# sourceMappingURL=patterns.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/analysis/patterns.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/analysis/patterns.ts"],"names":[],"mappings":"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"}