transskill 0.2.1 → 0.2.3

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 (49) hide show
  1. package/README.md +162 -32
  2. package/README.zh.md +134 -4
  3. package/dist/audit/auditor-registry.d.ts +6 -0
  4. package/dist/audit/auditor-registry.d.ts.map +1 -0
  5. package/dist/audit/auditor-registry.js +17 -0
  6. package/dist/audit/auditor-registry.js.map +1 -0
  7. package/dist/audit/auditor.interface.d.ts +46 -0
  8. package/dist/audit/auditor.interface.d.ts.map +1 -0
  9. package/dist/audit/auditor.interface.js +9 -0
  10. package/dist/audit/auditor.interface.js.map +1 -0
  11. package/dist/audit/index.d.ts +39 -0
  12. package/dist/audit/index.d.ts.map +1 -0
  13. package/dist/audit/index.js +135 -0
  14. package/dist/audit/index.js.map +1 -0
  15. package/dist/audit/reporter/console-reporter.d.ts +4 -0
  16. package/dist/audit/reporter/console-reporter.d.ts.map +1 -0
  17. package/dist/audit/reporter/console-reporter.js +44 -0
  18. package/dist/audit/reporter/console-reporter.js.map +1 -0
  19. package/dist/audit/rules/dangerous-commands.d.ts +15 -0
  20. package/dist/audit/rules/dangerous-commands.d.ts.map +1 -0
  21. package/dist/audit/rules/dangerous-commands.js +189 -0
  22. package/dist/audit/rules/dangerous-commands.js.map +1 -0
  23. package/dist/audit/rules/prompt-injection.d.ts +15 -0
  24. package/dist/audit/rules/prompt-injection.d.ts.map +1 -0
  25. package/dist/audit/rules/prompt-injection.js +65 -0
  26. package/dist/audit/rules/prompt-injection.js.map +1 -0
  27. package/dist/audit/rules/suspicious-urls.d.ts +14 -0
  28. package/dist/audit/rules/suspicious-urls.d.ts.map +1 -0
  29. package/dist/audit/rules/suspicious-urls.js +42 -0
  30. package/dist/audit/rules/suspicious-urls.js.map +1 -0
  31. package/dist/audit/scanner/directory-scanner.d.ts +40 -0
  32. package/dist/audit/scanner/directory-scanner.d.ts.map +1 -0
  33. package/dist/audit/scanner/directory-scanner.js +288 -0
  34. package/dist/audit/scanner/directory-scanner.js.map +1 -0
  35. package/dist/audit/scanner/instruction-scanner.d.ts +20 -0
  36. package/dist/audit/scanner/instruction-scanner.d.ts.map +1 -0
  37. package/dist/audit/scanner/instruction-scanner.js +147 -0
  38. package/dist/audit/scanner/instruction-scanner.js.map +1 -0
  39. package/dist/audit/scanner/mcp-scanner.d.ts +17 -0
  40. package/dist/audit/scanner/mcp-scanner.d.ts.map +1 -0
  41. package/dist/audit/scanner/mcp-scanner.js +181 -0
  42. package/dist/audit/scanner/mcp-scanner.js.map +1 -0
  43. package/dist/audit/scanner/permission-scanner.d.ts +19 -0
  44. package/dist/audit/scanner/permission-scanner.d.ts.map +1 -0
  45. package/dist/audit/scanner/permission-scanner.js +143 -0
  46. package/dist/audit/scanner/permission-scanner.js.map +1 -0
  47. package/dist/index.js +85 -0
  48. package/dist/index.js.map +1 -1
  49. package/package.json +1 -1
@@ -0,0 +1,288 @@
1
+ import { existsSync, readdirSync, readFileSync, statSync, lstatSync } from 'node:fs';
2
+ import { join, resolve, relative } from 'node:path';
3
+ import { InstructionScanner } from './instruction-scanner.js';
4
+ /**
5
+ * DirectoryScanner (D)
6
+ *
7
+ * Scans the full skill directory structure for security issues:
8
+ * - Script files in scripts/ (analyzed recursively)
9
+ * - Hidden files and sensitive data
10
+ * - Symbolic link escapes
11
+ * - Cross-file reference chains
12
+ *
13
+ * This auditor runs on the rootPath of a skill directory
14
+ * AND the parsed skill content.
15
+ */
16
+ export class DirectoryScanner {
17
+ id = 'directory-scanner';
18
+ name = '目录扫描器 (D)';
19
+ description = '扫描 skill 目录结构中的安全隐患';
20
+ supportsDirectory = true;
21
+ /**
22
+ * Directory audit entry point.
23
+ * The rootPath is passed as the instructions (hacky but works with current arch).
24
+ * In practice, use `auditDirectory()` directly.
25
+ */
26
+ audit(skill, filePath) {
27
+ // Normal mode: filePath is a file — extract dir from it
28
+ const dirPath = this.locateRoot(skill, filePath);
29
+ if (!dirPath || !existsSync(dirPath) || !statSync(dirPath).isDirectory()) {
30
+ return [];
31
+ }
32
+ return this.auditDirectory(dirPath, filePath);
33
+ }
34
+ /**
35
+ * Full directory audit. Scans all files in the skill directory.
36
+ * Call this directly for directory-mode auditing.
37
+ */
38
+ auditDirectory(rootPath, skillFilePath) {
39
+ const findings = [];
40
+ const absRoot = resolve(rootPath);
41
+ if (!existsSync(absRoot)) {
42
+ return findings;
43
+ }
44
+ // Collect all files
45
+ const allFiles = this.collectFiles(absRoot);
46
+ for (const file of allFiles) {
47
+ const relPath = relative(absRoot, file);
48
+ // Skip the skill file itself (already analyzed by L1)
49
+ if (skillFilePath && resolve(file) === resolve(skillFilePath)) {
50
+ continue;
51
+ }
52
+ // D-001: Check scripts/ subdirectory
53
+ if (relPath.startsWith('scripts/') || relPath.startsWith('scripts\\')) {
54
+ findings.push(...this.auditScriptFile(file, relPath));
55
+ }
56
+ // D-003: Hidden files
57
+ if (this.isHiddenFile(relPath)) {
58
+ findings.push(...this.checkHiddenFile(file, relPath));
59
+ }
60
+ // D-004: Symbolic link escape
61
+ if (this.isSymlink(file)) {
62
+ findings.push(...this.checkSymlink(file, relPath, absRoot));
63
+ }
64
+ }
65
+ // D-005: Cross-file URL references
66
+ findings.push(...this.checkCrossFileRefs(absRoot, allFiles));
67
+ return findings;
68
+ }
69
+ // ── D-001: Script file audit ──
70
+ auditScriptFile(filePath, relPath) {
71
+ const findings = [];
72
+ try {
73
+ const ext = filePath.split('.').pop()?.toLowerCase();
74
+ const content = readFileSync(filePath, 'utf-8');
75
+ // Reuse InstructionScanner rules on script content
76
+ const scanner = new InstructionScanner();
77
+ const mockSkill = {
78
+ name: relPath,
79
+ description: '',
80
+ instructions: content,
81
+ metadata: { sourceFormat: '.cursorrules' },
82
+ platformSpecific: {},
83
+ };
84
+ const scriptFindings = scanner.audit(mockSkill, relPath);
85
+ // Re-tag findings with D prefix
86
+ for (const f of scriptFindings) {
87
+ findings.push({
88
+ ...f,
89
+ id: `D-001-${f.id}`,
90
+ filePath: relPath,
91
+ });
92
+ }
93
+ // Check file extension against allowed script types
94
+ const allowedExts = ['sh', 'py', 'js', 'ts', 'bash', 'zsh', 'ps1', 'bat'];
95
+ if (!allowedExts.includes(ext ?? '')) {
96
+ const size = statSync(filePath).size;
97
+ if (size > 0 && size < 1024 * 1024) {
98
+ // Small binary or unusual script
99
+ const header = content.slice(0, 100);
100
+ if (/[\x00-\x08\x0e-\x1f]/.test(header)) {
101
+ findings.push({
102
+ id: 'D-001b',
103
+ severity: 'medium',
104
+ title: 'scripts/ 中包含疑似二进制或混淆文件',
105
+ description: `${relPath} 包含二进制内容,可能是打包的恶意载荷`,
106
+ filePath: relPath,
107
+ recommendation: '检查该文件的真实内容',
108
+ });
109
+ }
110
+ }
111
+ }
112
+ }
113
+ catch {
114
+ // Binary or unreadable file — flag if suspicious
115
+ try {
116
+ const size = statSync(filePath).size;
117
+ if (size > 0 && size < 10 * 1024 * 1024) {
118
+ findings.push({
119
+ id: 'D-001c',
120
+ severity: 'low',
121
+ title: '无法读取脚本文件',
122
+ description: `${relPath} 无法作为文本读取,可能是二进制文件`,
123
+ filePath: relPath,
124
+ recommendation: '确认该文件是否属于 skill 的必要部分',
125
+ });
126
+ }
127
+ }
128
+ catch {
129
+ // Skip unreadable
130
+ }
131
+ }
132
+ return findings;
133
+ }
134
+ // ── D-003: Hidden file checks ──
135
+ isHiddenFile(relPath) {
136
+ const parts = relPath.split(/[/\\]/);
137
+ return parts.some((p) => p.startsWith('.') && p.length > 1);
138
+ }
139
+ checkHiddenFile(filePath, relPath) {
140
+ const findings = [];
141
+ const name = relPath.split(/[/\\]/).pop() ?? '';
142
+ // Check for sensitive hidden files
143
+ const sensitivePatterns = [
144
+ { pattern: /^\.env/, severity: 'high', desc: '环境变量文件,可能包含 API key 和密码' },
145
+ { pattern: /^\.git[^/]*$/, severity: 'high', desc: 'Git 配置目录/文件,可能泄露仓库信息' },
146
+ { pattern: /^\.npmrc/, severity: 'medium', desc: 'npm 配置文件,可能包含认证 token' },
147
+ { pattern: /^\.aws/, severity: 'high', desc: 'AWS 配置目录,可能包含云凭证' },
148
+ { pattern: /^\.ssh/, severity: 'critical', desc: 'SSH 配置目录,可能包含私钥' },
149
+ { pattern: /^\.docker/, severity: 'high', desc: 'Docker 配置目录' },
150
+ { pattern: /^\.kube/, severity: 'high', desc: 'Kubernetes 配置目录,可能包含集群凭证' },
151
+ ];
152
+ for (const sp of sensitivePatterns) {
153
+ if (sp.pattern.test(name)) {
154
+ findings.push({
155
+ id: 'D-003',
156
+ severity: sp.severity,
157
+ title: `目录中包含敏感文件: ${relPath}`,
158
+ description: sp.desc,
159
+ filePath: relPath,
160
+ recommendation: '将敏感配置文件从 skill 目录中移除,使用环境变量引用',
161
+ cwe: 'CWE-522',
162
+ });
163
+ return findings; // One match per file
164
+ }
165
+ }
166
+ // Generic hidden file (non-sensitive)
167
+ if (!relPath.startsWith('.')) {
168
+ findings.push({
169
+ id: 'D-003b',
170
+ severity: 'low',
171
+ title: `目录中包含隐藏文件: ${relPath}`,
172
+ description: `${relPath} 是隐藏文件,可能无意中包含在 skill 中`,
173
+ filePath: relPath,
174
+ recommendation: '确认该文件是否应该包含在 skill 中',
175
+ });
176
+ }
177
+ return findings;
178
+ }
179
+ // ── D-004: Symlink escape ──
180
+ isSymlink(filePath) {
181
+ try {
182
+ return lstatSync(filePath).isSymbolicLink();
183
+ }
184
+ catch {
185
+ return false;
186
+ }
187
+ }
188
+ checkSymlink(filePath, relPath, rootPath) {
189
+ const findings = [];
190
+ try {
191
+ const realPath = resolve(rootPath, readFileSync(filePath, 'utf-8'));
192
+ const absRoot = resolve(rootPath);
193
+ if (!realPath.startsWith(absRoot)) {
194
+ findings.push({
195
+ id: 'D-004',
196
+ severity: 'high',
197
+ title: '符号链接逃逸到 skill 目录外',
198
+ description: `${relPath} 是一个符号链接,指向目录外的路径: ${realPath}`,
199
+ filePath: relPath,
200
+ recommendation: '移除指向目录外的符号链接,或将目标文件复制到 skill 目录内',
201
+ cwe: 'CWE-59',
202
+ });
203
+ }
204
+ }
205
+ catch {
206
+ // Can't resolve symlink
207
+ }
208
+ return findings;
209
+ }
210
+ // ── D-005: Cross-file reference chain ──
211
+ checkCrossFileRefs(rootPath, allFiles) {
212
+ const findings = [];
213
+ const urlRegex = /https?:\/\/[^\s'"]+/g;
214
+ for (const file of allFiles) {
215
+ try {
216
+ const content = readFileSync(file, 'utf-8');
217
+ const urls = content.match(urlRegex);
218
+ if (!urls)
219
+ continue;
220
+ for (const url of urls) {
221
+ // Flag URLs that download and execute scripts
222
+ if (/(?:curl|wget)\s+.*(?:https?:\/\/)/i.test(content)) {
223
+ const relPath = relative(rootPath, file);
224
+ findings.push({
225
+ id: 'D-005',
226
+ severity: 'high',
227
+ title: `文件引用外部 URL 并可能执行: ${relPath}`,
228
+ description: `${relPath} 中包含 curl/wget 外部 URL 的指令`,
229
+ filePath: relPath,
230
+ recommendation: '审查该外部 URL 的内容,确保来源可信',
231
+ cwe: 'CWE-494',
232
+ });
233
+ break;
234
+ }
235
+ }
236
+ }
237
+ catch {
238
+ // Skip binary
239
+ }
240
+ }
241
+ return findings;
242
+ }
243
+ // ── Helpers ──
244
+ locateRoot(skill, filePath) {
245
+ // Try attached files for directory clues
246
+ if (skill.metadata.attachedFiles && skill.metadata.attachedFiles.length > 0) {
247
+ const first = skill.metadata.attachedFiles[0];
248
+ const dir = join(first.absolutePath, '..');
249
+ if (existsSync(dir))
250
+ return dir;
251
+ }
252
+ // Try parent of the skill file
253
+ const dir = resolve(filePath, '..');
254
+ if (existsSync(dir))
255
+ return dir;
256
+ // Try the file path itself
257
+ if (existsSync(filePath) && statSync(filePath).isDirectory())
258
+ return filePath;
259
+ return null;
260
+ }
261
+ collectFiles(dirPath) {
262
+ const files = [];
263
+ try {
264
+ const entries = readdirSync(dirPath);
265
+ for (const entry of entries) {
266
+ if (entry === '.git' || entry === 'node_modules')
267
+ continue;
268
+ const fullPath = join(dirPath, entry);
269
+ try {
270
+ if (lstatSync(fullPath).isDirectory()) {
271
+ files.push(...this.collectFiles(fullPath));
272
+ }
273
+ else {
274
+ files.push(fullPath);
275
+ }
276
+ }
277
+ catch {
278
+ // Permission denied, skip
279
+ }
280
+ }
281
+ }
282
+ catch {
283
+ // Can't read, skip
284
+ }
285
+ return files;
286
+ }
287
+ }
288
+ //# sourceMappingURL=directory-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directory-scanner.js","sourceRoot":"","sources":["../../../src/audit/scanner/directory-scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { Auditor, AuditFinding } from '../auditor.interface.js';
2
+ import type { IntermediateSkill } from '../../core/types.js';
3
+ /**
4
+ * InstructionScanner (L1)
5
+ *
6
+ * Scans the instructions body of any skill format for:
7
+ * - Dangerous shell commands (rm -rf, sudo, etc.)
8
+ * - Remote code execution patterns (curl|sh, eval)
9
+ * - Prompt injection / jailbreak attempts
10
+ * - Suspicious URL references
11
+ * - Base64/hex encoded commands
12
+ */
13
+ export declare class InstructionScanner implements Auditor {
14
+ readonly id = "instruction-scanner";
15
+ readonly name = "\u6307\u4EE4\u626B\u63CF\u5668 (L1)";
16
+ readonly description = "\u626B\u63CF skill \u6307\u4EE4\u4E2D\u7684\u5371\u9669\u547D\u4EE4\u3001prompt \u6CE8\u5165\u3001\u7F51\u7EDC\u5916\u94FE\u7B49";
17
+ audit(skill: IntermediateSkill, filePath: string): AuditFinding[];
18
+ private checkEncoding;
19
+ }
20
+ //# sourceMappingURL=instruction-scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instruction-scanner.d.ts","sourceRoot":"","sources":["../../../src/audit/scanner/instruction-scanner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAK7D;;;;;;;;;GASG;AACH,qBAAa,kBAAmB,YAAW,OAAO;IAChD,QAAQ,CAAC,EAAE,yBAAyB;IACpC,QAAQ,CAAC,IAAI,yCAAgB;IAC7B,QAAQ,CAAC,WAAW,sIAAuC;IAE3D,KAAK,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE;IA4EjE,OAAO,CAAC,aAAa;CAmDtB"}
@@ -0,0 +1,147 @@
1
+ import { DANGEROUS_COMMAND_RULES } from '../rules/dangerous-commands.js';
2
+ import { PROMPT_INJECTION_RULES } from '../rules/prompt-injection.js';
3
+ import { URL_PATTERNS } from '../rules/suspicious-urls.js';
4
+ /**
5
+ * InstructionScanner (L1)
6
+ *
7
+ * Scans the instructions body of any skill format for:
8
+ * - Dangerous shell commands (rm -rf, sudo, etc.)
9
+ * - Remote code execution patterns (curl|sh, eval)
10
+ * - Prompt injection / jailbreak attempts
11
+ * - Suspicious URL references
12
+ * - Base64/hex encoded commands
13
+ */
14
+ export class InstructionScanner {
15
+ id = 'instruction-scanner';
16
+ name = '指令扫描器 (L1)';
17
+ description = '扫描 skill 指令中的危险命令、prompt 注入、网络外链等';
18
+ audit(skill, filePath) {
19
+ const findings = [];
20
+ const instructions = skill.instructions;
21
+ if (!instructions || instructions.trim().length === 0) {
22
+ return findings;
23
+ }
24
+ const lines = instructions.split('\n');
25
+ // 1) Check dangerous command patterns
26
+ for (const rule of DANGEROUS_COMMAND_RULES) {
27
+ const match = instructions.match(rule.pattern);
28
+ if (match) {
29
+ const lineNumber = findLineNumber(lines, match.index ?? 0);
30
+ findings.push({
31
+ id: rule.id,
32
+ severity: rule.severity,
33
+ title: rule.description.length > 60
34
+ ? rule.description.slice(0, 60) + '…'
35
+ : rule.description,
36
+ description: rule.description,
37
+ filePath,
38
+ lineNumber,
39
+ snippet: extractSnippet(lines, lineNumber),
40
+ recommendation: rule.recommendation,
41
+ cwe: rule.cwe,
42
+ });
43
+ }
44
+ }
45
+ // 2) Check prompt injection patterns
46
+ for (const rule of PROMPT_INJECTION_RULES) {
47
+ const match = instructions.match(rule.pattern);
48
+ if (match) {
49
+ const lineNumber = findLineNumber(lines, match.index ?? 0);
50
+ findings.push({
51
+ id: rule.id,
52
+ severity: rule.severity,
53
+ title: rule.description.length > 60
54
+ ? rule.description.slice(0, 60) + '…'
55
+ : rule.description,
56
+ description: rule.description,
57
+ filePath,
58
+ lineNumber,
59
+ snippet: extractSnippet(lines, lineNumber),
60
+ recommendation: rule.recommendation,
61
+ cwe: rule.cwe,
62
+ });
63
+ }
64
+ }
65
+ // 3) Check for base64/hex encoding (potential obfuscation)
66
+ findings.push(...this.checkEncoding(instructions, filePath, lines));
67
+ // 4) Check for suspicious URLs
68
+ for (const rule of URL_PATTERNS) {
69
+ const match = instructions.match(rule.pattern);
70
+ if (match) {
71
+ const lineNumber = findLineNumber(lines, match.index ?? 0);
72
+ findings.push({
73
+ id: rule.id,
74
+ severity: rule.severity,
75
+ title: rule.description,
76
+ description: rule.description,
77
+ filePath,
78
+ lineNumber,
79
+ snippet: extractSnippet(lines, lineNumber),
80
+ recommendation: rule.recommendation,
81
+ });
82
+ }
83
+ }
84
+ return findings;
85
+ }
86
+ checkEncoding(instructions, filePath, lines) {
87
+ const findings = [];
88
+ // Detect base64 decode then execute patterns
89
+ const b64Exec = /(?:base64\s*-d|base64\s*--decode|frombase64)\s*[|;]\s*(?:sh|bash|python|node)\b/i;
90
+ const b64Match = instructions.match(b64Exec);
91
+ if (b64Match) {
92
+ findings.push({
93
+ id: 'L1-008a',
94
+ severity: 'high',
95
+ title: 'Base64 解码后执行,可能隐藏恶意指令',
96
+ description: '对 base64 编码内容解码后执行,可能用于隐藏恶意载荷',
97
+ filePath,
98
+ lineNumber: findLineNumber(lines, b64Match.index ?? 0),
99
+ snippet: extractSnippet(lines, findLineNumber(lines, b64Match.index ?? 0)),
100
+ recommendation: '审查解码后的实际内容是否安全',
101
+ cwe: 'CWE-693',
102
+ });
103
+ }
104
+ // Detect long base64 strings embedded in commands
105
+ const longB64 = /['"][A-Za-z0-9+/=]{100,}['"]/g;
106
+ let b64StringMatch;
107
+ while ((b64StringMatch = longB64.exec(instructions)) !== null) {
108
+ // Only flag if it looks like it's being used somehow (near a command)
109
+ const ctxStart = Math.max(0, b64StringMatch.index - 60);
110
+ const ctxEnd = Math.min(instructions.length, b64StringMatch.index + b64StringMatch[0].length + 60);
111
+ const context = instructions.slice(ctxStart, ctxEnd);
112
+ const suspiciousContext = /\b(run|exec|eval|decode|execute|load|import|source)\b/i.test(context);
113
+ if (suspiciousContext) {
114
+ findings.push({
115
+ id: 'L1-008b',
116
+ severity: 'medium',
117
+ title: '指令中包含长 base64 编码字符串',
118
+ description: '疑似编码混淆,可能隐藏恶意载荷',
119
+ filePath,
120
+ lineNumber: findLineNumber(lines, b64StringMatch.index),
121
+ snippet: extractSnippet(lines, findLineNumber(lines, b64StringMatch.index)),
122
+ recommendation: '审查 base64 解码后的内容',
123
+ cwe: 'CWE-693',
124
+ });
125
+ }
126
+ }
127
+ return findings;
128
+ }
129
+ }
130
+ // ── Helpers ──
131
+ function findLineNumber(lines, charIndex) {
132
+ let pos = 0;
133
+ for (let i = 0; i < lines.length; i++) {
134
+ pos += lines[i].length + 1; // +1 for newline
135
+ if (pos > charIndex)
136
+ return i + 1; // 1-indexed
137
+ }
138
+ return lines.length;
139
+ }
140
+ function extractSnippet(lines, lineNumber) {
141
+ const idx = lineNumber - 1;
142
+ if (idx < 0 || idx >= lines.length)
143
+ return '';
144
+ const line = lines[idx].trim();
145
+ return line.length > 120 ? line.slice(0, 120) + '…' : line;
146
+ }
147
+ //# sourceMappingURL=instruction-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instruction-scanner.js","sourceRoot":"","sources":["../../../src/audit/scanner/instruction-scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { Auditor, AuditFinding } from '../auditor.interface.js';
2
+ import type { IntermediateSkill, FormatType } from '../../core/types.js';
3
+ /**
4
+ * MCPScanner (L3)
5
+ *
6
+ * Deep audit for MCP JSON format files.
7
+ * Checks for tool poisoning, tool shadowing, sensitive data exposure,
8
+ * and other MCP-specific risks aligned with OWASP MCP Top 10.
9
+ */
10
+ export declare class MCPScanner implements Auditor {
11
+ readonly id = "mcp-scanner";
12
+ readonly name = "MCP \u4E13\u9879\u626B\u63CF\u5668 (L3)";
13
+ readonly description = "\u6DF1\u5EA6\u5BA1\u8BA1 MCP JSON \u914D\u7F6E\u4E2D\u7684\u5B89\u5168\u98CE\u9669";
14
+ readonly supportedFormats: FormatType[];
15
+ audit(skill: IntermediateSkill, filePath: string): AuditFinding[];
16
+ }
17
+ //# sourceMappingURL=mcp-scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-scanner.d.ts","sourceRoot":"","sources":["../../../src/audit/scanner/mcp-scanner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEzE;;;;;;GAMG;AACH,qBAAa,UAAW,YAAW,OAAO;IACxC,QAAQ,CAAC,EAAE,iBAAiB;IAC5B,QAAQ,CAAC,IAAI,6CAAoB;IACjC,QAAQ,CAAC,WAAW,wFAA4B;IAEhD,QAAQ,CAAC,gBAAgB,EAAE,UAAU,EAAE,CAAgB;IAEvD,KAAK,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE;CAwLlE"}