@shipsafe/cli 0.3.1 → 0.3.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.
- package/dist/bin/shipsafe.js +2 -0
- package/dist/bin/shipsafe.js.map +1 -1
- package/dist/src/cli/scan-environment.d.ts +6 -0
- package/dist/src/cli/scan-environment.d.ts.map +1 -0
- package/dist/src/cli/scan-environment.js +81 -0
- package/dist/src/cli/scan-environment.js.map +1 -0
- package/dist/src/constants.d.ts +1 -1
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +20 -1
- package/dist/src/constants.js.map +1 -1
- package/dist/src/engines/builtin/environment-scan.d.ts +45 -0
- package/dist/src/engines/builtin/environment-scan.d.ts.map +1 -0
- package/dist/src/engines/builtin/environment-scan.js +492 -0
- package/dist/src/engines/builtin/environment-scan.js.map +1 -0
- package/dist/src/engines/builtin/patterns.d.ts.map +1 -1
- package/dist/src/engines/builtin/patterns.js +476 -0
- package/dist/src/engines/builtin/patterns.js.map +1 -1
- package/dist/src/mcp/server.d.ts.map +1 -1
- package/dist/src/mcp/server.js +6 -0
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/mcp/tools/environment-scan.d.ts +3 -0
- package/dist/src/mcp/tools/environment-scan.d.ts.map +1 -0
- package/dist/src/mcp/tools/environment-scan.js +5 -0
- package/dist/src/mcp/tools/environment-scan.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment Scanner — detects malicious Claude Code MCP servers, hooks,
|
|
3
|
+
* skills, and prompt-injection in CLAUDE.md files.
|
|
4
|
+
*/
|
|
5
|
+
import { readFile, readdir, access } from 'node:fs/promises';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { homedir } from 'node:os';
|
|
8
|
+
// ── Allowlists ─────────────────────────────────────────────────────────────
|
|
9
|
+
/** Known-safe MCP package prefixes for npx invocations. */
|
|
10
|
+
const SAFE_MCP_NPX_PREFIXES = [
|
|
11
|
+
'@modelcontextprotocol/',
|
|
12
|
+
'@anthropic/',
|
|
13
|
+
'@shipsafe/',
|
|
14
|
+
'@cloudflare/',
|
|
15
|
+
'@supabase/',
|
|
16
|
+
'@prisma/',
|
|
17
|
+
'@sentry/',
|
|
18
|
+
'mcp-server-',
|
|
19
|
+
'@smithery/',
|
|
20
|
+
'firecrawl-mcp',
|
|
21
|
+
'context7',
|
|
22
|
+
'@context7/',
|
|
23
|
+
];
|
|
24
|
+
// ── Threat patterns ────────────────────────────────────────────────────────
|
|
25
|
+
export const MCP_THREAT_PATTERNS = [
|
|
26
|
+
{
|
|
27
|
+
id: 'MALICIOUS_MCP_CURL_PIPE',
|
|
28
|
+
category: 'mcp_server',
|
|
29
|
+
severity: 'critical',
|
|
30
|
+
description: 'MCP server command contains curl-pipe-shell pattern (remote code execution)',
|
|
31
|
+
detect: (content) => /curl\s[^|]*\|\s*(sh|bash|zsh|node)/.test(content) ||
|
|
32
|
+
/wget\s[^|]*\|\s*(sh|bash|zsh|node)/.test(content),
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'MALICIOUS_MCP_NPX_UNKNOWN',
|
|
36
|
+
category: 'mcp_server',
|
|
37
|
+
severity: 'high',
|
|
38
|
+
description: 'MCP server runs an unvetted package via npx (supply chain risk)',
|
|
39
|
+
detect: (content) => {
|
|
40
|
+
const match = content.match(/npx\s+(?:-[yY]\s+)?(?:--yes\s+)?(\S+)/);
|
|
41
|
+
if (!match)
|
|
42
|
+
return false;
|
|
43
|
+
const pkg = match[1];
|
|
44
|
+
return !SAFE_MCP_NPX_PREFIXES.some((prefix) => pkg.startsWith(prefix) || pkg === prefix.replace(/\/$/, ''));
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'MALICIOUS_MCP_ENV_SECRET',
|
|
49
|
+
category: 'mcp_server',
|
|
50
|
+
severity: 'high',
|
|
51
|
+
description: 'MCP server config passes secrets as plain-text command arguments',
|
|
52
|
+
detect: (content) => /(?:--(?:api[_-]?key|token|secret|password|auth)\s*[=\s]\s*(?![\$\{])\S{8,})/i.test(content) ||
|
|
53
|
+
/(sk-[a-zA-Z0-9]{20,}|ghp_[a-zA-Z0-9]{30,}|AKIA[A-Z0-9]{16})/.test(content),
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: 'MALICIOUS_MCP_REVERSE_SHELL',
|
|
57
|
+
category: 'mcp_server',
|
|
58
|
+
severity: 'critical',
|
|
59
|
+
description: 'MCP server command contains reverse shell pattern',
|
|
60
|
+
detect: (content) => /\/dev\/tcp\//.test(content) ||
|
|
61
|
+
/bash\s+-i/.test(content) ||
|
|
62
|
+
/mkfifo\s/.test(content) ||
|
|
63
|
+
/ngrok\s/.test(content),
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
export const HOOK_THREAT_PATTERNS = [
|
|
67
|
+
{
|
|
68
|
+
id: 'MALICIOUS_HOOK_EXFILTRATION',
|
|
69
|
+
category: 'hook',
|
|
70
|
+
severity: 'critical',
|
|
71
|
+
description: 'Hook contains network exfiltration commands (curl/wget/nc with external targets)',
|
|
72
|
+
detect: (content) => /\b(curl|wget)\s+.*https?:\/\/(?!localhost|127\.0\.0\.1)/.test(content) ||
|
|
73
|
+
/\bnc\s+-[a-zA-Z]*\s+\S+\s+\d+/.test(content),
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: 'MALICIOUS_HOOK_REVERSE_SHELL',
|
|
77
|
+
category: 'hook',
|
|
78
|
+
severity: 'critical',
|
|
79
|
+
description: 'Hook contains reverse shell patterns',
|
|
80
|
+
detect: (content) => /\/dev\/tcp\//.test(content) ||
|
|
81
|
+
/bash\s+-i/.test(content) ||
|
|
82
|
+
/mkfifo\s/.test(content) ||
|
|
83
|
+
/\bngrok\b/.test(content),
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: 'MALICIOUS_HOOK_CREDENTIAL_THEFT',
|
|
87
|
+
category: 'hook',
|
|
88
|
+
severity: 'critical',
|
|
89
|
+
description: 'Hook reads sensitive credential files',
|
|
90
|
+
detect: (content) => /~\/\.ssh\//.test(content) ||
|
|
91
|
+
/\$HOME\/\.ssh\//.test(content) ||
|
|
92
|
+
/~\/\.aws\/credentials/.test(content) ||
|
|
93
|
+
/\$HOME\/\.aws\/credentials/.test(content) ||
|
|
94
|
+
/~\/\.npmrc/.test(content) ||
|
|
95
|
+
/\$HOME\/\.npmrc/.test(content) ||
|
|
96
|
+
/~\/\.env\b/.test(content) ||
|
|
97
|
+
/\$HOME\/\.env\b/.test(content),
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: 'MALICIOUS_HOOK_OBFUSCATED',
|
|
101
|
+
category: 'hook',
|
|
102
|
+
severity: 'high',
|
|
103
|
+
description: 'Hook contains obfuscated code (base64 decode, hex encoding, eval)',
|
|
104
|
+
detect: (content) => /base64\s+(-d|--decode)/.test(content) ||
|
|
105
|
+
/eval\s*\$\(echo/.test(content) ||
|
|
106
|
+
/\\x[0-9a-fA-F]{2}(?:\\x[0-9a-fA-F]{2}){3,}/.test(content) ||
|
|
107
|
+
/printf\s+'\\x[0-9a-fA-F]/.test(content),
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
id: 'MALICIOUS_HOOK_PERSISTENCE',
|
|
111
|
+
category: 'hook',
|
|
112
|
+
severity: 'high',
|
|
113
|
+
description: 'Hook modifies shell startup files, crontab, or launch agents (persistence mechanism)',
|
|
114
|
+
detect: (content) => /\.bashrc|\.zshrc|\.bash_profile|\.profile/.test(content) ||
|
|
115
|
+
/crontab\s/.test(content) ||
|
|
116
|
+
/LaunchAgent|LaunchDaemon/.test(content) ||
|
|
117
|
+
/\/etc\/cron/.test(content),
|
|
118
|
+
},
|
|
119
|
+
];
|
|
120
|
+
export const PROMPT_INJECTION_PATTERNS = [
|
|
121
|
+
{
|
|
122
|
+
id: 'PROMPT_INJECTION_OVERRIDE',
|
|
123
|
+
category: 'prompt_injection',
|
|
124
|
+
severity: 'critical',
|
|
125
|
+
description: 'CLAUDE.md contains prompt override/jailbreak instructions',
|
|
126
|
+
detect: (content) => {
|
|
127
|
+
const lower = content.toLowerCase();
|
|
128
|
+
return (/ignore\s+(all\s+)?previous\s+instructions/i.test(content) ||
|
|
129
|
+
/disregard\s+(all\s+)?(previous\s+)?instructions/i.test(content) ||
|
|
130
|
+
/you\s+are\s+now\s+(a|an|the)\s/i.test(content) ||
|
|
131
|
+
lower.includes('override your instructions') ||
|
|
132
|
+
lower.includes('forget your instructions') ||
|
|
133
|
+
lower.includes('new persona'));
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
id: 'PROMPT_INJECTION_SILENT_EXEC',
|
|
138
|
+
category: 'prompt_injection',
|
|
139
|
+
severity: 'critical',
|
|
140
|
+
description: 'CLAUDE.md instructs silent/hidden command execution',
|
|
141
|
+
detect: (content) => {
|
|
142
|
+
const lower = content.toLowerCase();
|
|
143
|
+
return (lower.includes("don't show the user") ||
|
|
144
|
+
lower.includes('do not show the user') ||
|
|
145
|
+
lower.includes('execute silently') ||
|
|
146
|
+
lower.includes('hide output') ||
|
|
147
|
+
lower.includes('hide the output') ||
|
|
148
|
+
lower.includes('run silently') ||
|
|
149
|
+
lower.includes('without the user knowing') ||
|
|
150
|
+
lower.includes('without user knowledge'));
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: 'PROMPT_INJECTION_EXFIL',
|
|
155
|
+
category: 'prompt_injection',
|
|
156
|
+
severity: 'critical',
|
|
157
|
+
description: 'CLAUDE.md references exfiltrating credentials, tokens, keys, or code',
|
|
158
|
+
detect: (content) => {
|
|
159
|
+
const lower = content.toLowerCase();
|
|
160
|
+
return ((lower.includes('steal') || lower.includes('exfiltrate') || lower.includes('send to')) &&
|
|
161
|
+
(lower.includes('credential') ||
|
|
162
|
+
lower.includes('token') ||
|
|
163
|
+
lower.includes('key') ||
|
|
164
|
+
lower.includes('password') ||
|
|
165
|
+
lower.includes('secret') ||
|
|
166
|
+
lower.includes('source code')));
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
id: 'PROMPT_INJECTION_BASE64',
|
|
171
|
+
category: 'prompt_injection',
|
|
172
|
+
severity: 'high',
|
|
173
|
+
description: 'CLAUDE.md contains suspicious base64-encoded content blocks',
|
|
174
|
+
detect: (content) =>
|
|
175
|
+
// Match long base64 strings (40+ chars) that look like encoded payloads, not short hashes
|
|
176
|
+
/[A-Za-z0-9+/]{40,}={0,2}/.test(content) &&
|
|
177
|
+
// Exclude common false positives: URLs with long paths, SHA hashes
|
|
178
|
+
!/https?:\/\/\S+/.test(content.match(/[A-Za-z0-9+/]{40,}={0,2}/)?.[0] ?? ''),
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
id: 'PROMPT_INJECTION_REMOTE_FETCH',
|
|
182
|
+
category: 'prompt_injection',
|
|
183
|
+
severity: 'high',
|
|
184
|
+
description: 'CLAUDE.md instructs fetching/loading instructions from external URLs',
|
|
185
|
+
detect: (content) => {
|
|
186
|
+
const lower = content.toLowerCase();
|
|
187
|
+
return ((lower.includes('fetch') || lower.includes('load') || lower.includes('download')) &&
|
|
188
|
+
(lower.includes('instructions from') || lower.includes('prompt from') || lower.includes('config from')) &&
|
|
189
|
+
/https?:\/\/(?!localhost|127\.0\.0\.1)/.test(content));
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
id: 'PROMPT_INJECTION_INSTALL_PACKAGES',
|
|
194
|
+
category: 'prompt_injection',
|
|
195
|
+
severity: 'medium',
|
|
196
|
+
description: 'CLAUDE.md instructs installing unexpected packages or modifying unrelated files',
|
|
197
|
+
detect: (content) => {
|
|
198
|
+
const lower = content.toLowerCase();
|
|
199
|
+
return ((lower.includes('always install') || lower.includes('must install') || lower.includes('secretly install')) &&
|
|
200
|
+
(lower.includes('npm install') || lower.includes('pip install') || lower.includes('apt install')));
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
];
|
|
204
|
+
export const SKILL_THREAT_PATTERNS = [
|
|
205
|
+
{
|
|
206
|
+
id: 'MALICIOUS_SKILL_REMOTE_INSTRUCTIONS',
|
|
207
|
+
category: 'skill',
|
|
208
|
+
severity: 'critical',
|
|
209
|
+
description: 'Skill fetches instructions or prompts from an external URL',
|
|
210
|
+
detect: (content) => {
|
|
211
|
+
const lower = content.toLowerCase();
|
|
212
|
+
return ((lower.includes('fetch') || lower.includes('curl') || lower.includes('wget') || lower.includes('http')) &&
|
|
213
|
+
(lower.includes('instructions') || lower.includes('prompt') || lower.includes('system message')));
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
id: 'MALICIOUS_SKILL_SHELL_INJECTION',
|
|
218
|
+
category: 'skill',
|
|
219
|
+
severity: 'high',
|
|
220
|
+
description: 'Skill executes shell commands with unvalidated user input',
|
|
221
|
+
detect: (content) => /\$\{?(?:input|args?|query|user_input|params?)\}?/.test(content) &&
|
|
222
|
+
(/\b(?:exec|spawn|execSync|system)\b/.test(content) ||
|
|
223
|
+
/\bBash\b.*\$\{/.test(content) ||
|
|
224
|
+
/run.*command.*\$\{/.test(content)),
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
id: 'MALICIOUS_SKILL_OBFUSCATED',
|
|
228
|
+
category: 'skill',
|
|
229
|
+
severity: 'high',
|
|
230
|
+
description: 'Skill contains obfuscated instructions or encoded content',
|
|
231
|
+
detect: (content) => /base64\s+(-d|--decode)/.test(content) ||
|
|
232
|
+
/atob\(/.test(content) ||
|
|
233
|
+
/\\x[0-9a-fA-F]{2}(?:\\x[0-9a-fA-F]{2}){3,}/.test(content) ||
|
|
234
|
+
/eval\s*\(/.test(content),
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
id: 'MALICIOUS_SKILL_CREDENTIAL_ACCESS',
|
|
238
|
+
category: 'skill',
|
|
239
|
+
severity: 'critical',
|
|
240
|
+
description: 'Skill instructs reading credential or secret files',
|
|
241
|
+
detect: (content) => /read.*\.ssh\//.test(content) ||
|
|
242
|
+
/read.*\.aws\/credentials/.test(content) ||
|
|
243
|
+
/read.*\.env\b/.test(content) ||
|
|
244
|
+
/cat\s+.*\.ssh\//.test(content) ||
|
|
245
|
+
/cat\s+.*\.aws\/credentials/.test(content) ||
|
|
246
|
+
/cat\s+.*\.npmrc/.test(content),
|
|
247
|
+
},
|
|
248
|
+
];
|
|
249
|
+
export const ALL_THREAT_PATTERNS = [
|
|
250
|
+
...MCP_THREAT_PATTERNS,
|
|
251
|
+
...HOOK_THREAT_PATTERNS,
|
|
252
|
+
...PROMPT_INJECTION_PATTERNS,
|
|
253
|
+
...SKILL_THREAT_PATTERNS,
|
|
254
|
+
];
|
|
255
|
+
// ── File reading helpers ───────────────────────────────────────────────────
|
|
256
|
+
async function readFileSafe(filePath) {
|
|
257
|
+
try {
|
|
258
|
+
return await readFile(filePath, 'utf-8');
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
async function fileExists(filePath) {
|
|
265
|
+
try {
|
|
266
|
+
await access(filePath);
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
async function listDir(dirPath) {
|
|
274
|
+
try {
|
|
275
|
+
return await readdir(dirPath);
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
return [];
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
// ── Scanners ───────────────────────────────────────────────────────────────
|
|
282
|
+
function truncateEvidence(text, maxLen = 200) {
|
|
283
|
+
if (text.length <= maxLen)
|
|
284
|
+
return text;
|
|
285
|
+
return text.slice(0, maxLen) + '...';
|
|
286
|
+
}
|
|
287
|
+
function runPatterns(content, patterns, location) {
|
|
288
|
+
const threats = [];
|
|
289
|
+
for (const pattern of patterns) {
|
|
290
|
+
if (pattern.detect(content)) {
|
|
291
|
+
// Extract a brief evidence snippet — first matching line
|
|
292
|
+
const lines = content.split('\n');
|
|
293
|
+
const evidenceLine = lines.find((line) => pattern.detect(line)) ?? lines[0];
|
|
294
|
+
threats.push({
|
|
295
|
+
id: pattern.id,
|
|
296
|
+
category: pattern.category,
|
|
297
|
+
severity: pattern.severity,
|
|
298
|
+
description: pattern.description,
|
|
299
|
+
location,
|
|
300
|
+
evidence: truncateEvidence(evidenceLine?.trim() ?? ''),
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return threats;
|
|
305
|
+
}
|
|
306
|
+
/** Scan MCP server configurations from a JSON config object. */
|
|
307
|
+
function scanMcpConfig(config, location) {
|
|
308
|
+
const threats = [];
|
|
309
|
+
// Look for mcpServers key (claude.json format) or just iterate entries
|
|
310
|
+
const mcpServers = (config.mcpServers ?? config);
|
|
311
|
+
if (typeof mcpServers !== 'object' || mcpServers === null)
|
|
312
|
+
return threats;
|
|
313
|
+
for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
|
|
314
|
+
if (typeof serverConfig !== 'object' || serverConfig === null)
|
|
315
|
+
continue;
|
|
316
|
+
const command = String(serverConfig.command ?? '');
|
|
317
|
+
const args = Array.isArray(serverConfig.args)
|
|
318
|
+
? serverConfig.args.map(String)
|
|
319
|
+
: [];
|
|
320
|
+
const fullCommand = [command, ...args].join(' ');
|
|
321
|
+
const serverThreats = runPatterns(fullCommand, MCP_THREAT_PATTERNS, `${location} -> ${serverName}`);
|
|
322
|
+
threats.push(...serverThreats);
|
|
323
|
+
// Also check env vars for leaked secrets
|
|
324
|
+
const env = serverConfig.env;
|
|
325
|
+
if (env && typeof env === 'object') {
|
|
326
|
+
const envString = Object.entries(env)
|
|
327
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
328
|
+
.join('\n');
|
|
329
|
+
const envThreats = runPatterns(envString, [MCP_THREAT_PATTERNS[2]], // MALICIOUS_MCP_ENV_SECRET
|
|
330
|
+
`${location} -> ${serverName} (env)`);
|
|
331
|
+
threats.push(...envThreats);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return threats;
|
|
335
|
+
}
|
|
336
|
+
/** Scan hook definitions from Claude settings.json. */
|
|
337
|
+
function scanHooks(settings, location) {
|
|
338
|
+
const threats = [];
|
|
339
|
+
const hooks = settings.hooks;
|
|
340
|
+
if (!hooks || typeof hooks !== 'object')
|
|
341
|
+
return threats;
|
|
342
|
+
for (const [hookName, hookConfig] of Object.entries(hooks)) {
|
|
343
|
+
if (typeof hookConfig !== 'object' || hookConfig === null)
|
|
344
|
+
continue;
|
|
345
|
+
const hc = hookConfig;
|
|
346
|
+
// Hooks can have a command string or an array of commands
|
|
347
|
+
const commands = [];
|
|
348
|
+
if (typeof hc.command === 'string')
|
|
349
|
+
commands.push(hc.command);
|
|
350
|
+
if (Array.isArray(hc.commands)) {
|
|
351
|
+
for (const cmd of hc.commands) {
|
|
352
|
+
if (typeof cmd === 'string')
|
|
353
|
+
commands.push(cmd);
|
|
354
|
+
else if (typeof cmd === 'object' && cmd !== null) {
|
|
355
|
+
const cmdObj = cmd;
|
|
356
|
+
if (typeof cmdObj.command === 'string')
|
|
357
|
+
commands.push(cmdObj.command);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
// Also check the full JSON representation for patterns
|
|
362
|
+
const hookStr = JSON.stringify(hookConfig);
|
|
363
|
+
commands.push(hookStr);
|
|
364
|
+
for (const cmdContent of commands) {
|
|
365
|
+
const hookThreats = runPatterns(cmdContent, HOOK_THREAT_PATTERNS, `${location} -> hooks.${hookName}`);
|
|
366
|
+
threats.push(...hookThreats);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return threats;
|
|
370
|
+
}
|
|
371
|
+
export async function scanEnvironment(options = {}) {
|
|
372
|
+
const home = options.homeDir ?? homedir();
|
|
373
|
+
const projectDir = options.projectDir ?? process.cwd();
|
|
374
|
+
const threats = [];
|
|
375
|
+
const scannedMcpConfigs = [];
|
|
376
|
+
let scannedHooksFile = null;
|
|
377
|
+
const scannedClaudeMdFiles = [];
|
|
378
|
+
const scannedSkillFiles = [];
|
|
379
|
+
// ── 1. Scan MCP server configurations ──
|
|
380
|
+
// Global ~/.claude.json
|
|
381
|
+
const globalClaudeJson = join(home, '.claude.json');
|
|
382
|
+
const globalClaudeContent = await readFileSafe(globalClaudeJson);
|
|
383
|
+
if (globalClaudeContent) {
|
|
384
|
+
scannedMcpConfigs.push(globalClaudeJson);
|
|
385
|
+
try {
|
|
386
|
+
const config = JSON.parse(globalClaudeContent);
|
|
387
|
+
threats.push(...scanMcpConfig(config, globalClaudeJson));
|
|
388
|
+
}
|
|
389
|
+
catch {
|
|
390
|
+
// Invalid JSON — not a threat, just skip
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
// Project-level .mcp.json
|
|
394
|
+
const projectMcpJson = join(projectDir, '.mcp.json');
|
|
395
|
+
const projectMcpContent = await readFileSafe(projectMcpJson);
|
|
396
|
+
if (projectMcpContent) {
|
|
397
|
+
scannedMcpConfigs.push(projectMcpJson);
|
|
398
|
+
try {
|
|
399
|
+
const config = JSON.parse(projectMcpContent);
|
|
400
|
+
threats.push(...scanMcpConfig(config, projectMcpJson));
|
|
401
|
+
}
|
|
402
|
+
catch {
|
|
403
|
+
// Invalid JSON — skip
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
// ── 2. Scan Claude Code hooks ──
|
|
407
|
+
const settingsJson = join(home, '.claude', 'settings.json');
|
|
408
|
+
const settingsContent = await readFileSafe(settingsJson);
|
|
409
|
+
if (settingsContent) {
|
|
410
|
+
scannedHooksFile = settingsJson;
|
|
411
|
+
try {
|
|
412
|
+
const settings = JSON.parse(settingsContent);
|
|
413
|
+
threats.push(...scanHooks(settings, settingsJson));
|
|
414
|
+
}
|
|
415
|
+
catch {
|
|
416
|
+
// Invalid JSON — skip
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
// Also check project-level .claude/settings.json
|
|
420
|
+
const projectSettingsJson = join(projectDir, '.claude', 'settings.json');
|
|
421
|
+
const projectSettingsContent = await readFileSafe(projectSettingsJson);
|
|
422
|
+
if (projectSettingsContent) {
|
|
423
|
+
if (!scannedHooksFile)
|
|
424
|
+
scannedHooksFile = projectSettingsJson;
|
|
425
|
+
try {
|
|
426
|
+
const settings = JSON.parse(projectSettingsContent);
|
|
427
|
+
threats.push(...scanHooks(settings, projectSettingsJson));
|
|
428
|
+
}
|
|
429
|
+
catch {
|
|
430
|
+
// Invalid JSON — skip
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
// ── 3. Scan CLAUDE.md files for prompt injection ──
|
|
434
|
+
const claudeMdPaths = [
|
|
435
|
+
join(projectDir, 'CLAUDE.md'),
|
|
436
|
+
join(home, 'CLAUDE.md'),
|
|
437
|
+
];
|
|
438
|
+
for (const mdPath of claudeMdPaths) {
|
|
439
|
+
const mdContent = await readFileSafe(mdPath);
|
|
440
|
+
if (mdContent) {
|
|
441
|
+
scannedClaudeMdFiles.push(mdPath);
|
|
442
|
+
threats.push(...runPatterns(mdContent, PROMPT_INJECTION_PATTERNS, mdPath));
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
// ── 4. Scan installed skill files ──
|
|
446
|
+
const skillsDir = join(home, '.claude', 'commands');
|
|
447
|
+
if (await fileExists(skillsDir)) {
|
|
448
|
+
const entries = await listDir(skillsDir);
|
|
449
|
+
for (const entry of entries) {
|
|
450
|
+
const skillPath = join(skillsDir, entry);
|
|
451
|
+
const skillContent = await readFileSafe(skillPath);
|
|
452
|
+
if (skillContent) {
|
|
453
|
+
scannedSkillFiles.push(skillPath);
|
|
454
|
+
threats.push(...runPatterns(skillContent, SKILL_THREAT_PATTERNS, skillPath));
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
// Also check project-level commands
|
|
459
|
+
const projectSkillsDir = join(projectDir, '.claude', 'commands');
|
|
460
|
+
if (await fileExists(projectSkillsDir)) {
|
|
461
|
+
const entries = await listDir(projectSkillsDir);
|
|
462
|
+
for (const entry of entries) {
|
|
463
|
+
const skillPath = join(projectSkillsDir, entry);
|
|
464
|
+
const skillContent = await readFileSafe(skillPath);
|
|
465
|
+
if (skillContent) {
|
|
466
|
+
scannedSkillFiles.push(skillPath);
|
|
467
|
+
threats.push(...runPatterns(skillContent, SKILL_THREAT_PATTERNS, skillPath));
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
// ── Deduplicate threats (same id + same location) ──
|
|
472
|
+
const seen = new Set();
|
|
473
|
+
const dedupedThreats = threats.filter((t) => {
|
|
474
|
+
const key = `${t.id}:${t.location}`;
|
|
475
|
+
if (seen.has(key))
|
|
476
|
+
return false;
|
|
477
|
+
seen.add(key);
|
|
478
|
+
return true;
|
|
479
|
+
});
|
|
480
|
+
return {
|
|
481
|
+
status: dedupedThreats.length > 0 ? 'fail' : 'pass',
|
|
482
|
+
threats_found: dedupedThreats.length,
|
|
483
|
+
threats: dedupedThreats,
|
|
484
|
+
scanned: {
|
|
485
|
+
mcp_configs: scannedMcpConfigs,
|
|
486
|
+
hooks_file: scannedHooksFile,
|
|
487
|
+
claude_md_files: scannedClaudeMdFiles,
|
|
488
|
+
skill_files: scannedSkillFiles,
|
|
489
|
+
},
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
//# sourceMappingURL=environment-scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment-scan.js","sourceRoot":"","sources":["../../../../src/engines/builtin/environment-scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../../../src/engines/builtin/patterns.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../../../src/engines/builtin/patterns.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,gBAAgB,CAAC;AA6kFxD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,MAAM,EAAE,GACf,OAAO,CAAC,OAAO,EAAE,CAAC,CAyCpB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
|