@shipsafe/cli 0.3.0 → 0.3.2

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 (34) hide show
  1. package/README.md +125 -87
  2. package/dist/bin/shipsafe.js +2 -0
  3. package/dist/bin/shipsafe.js.map +1 -1
  4. package/dist/src/cli/scan-environment.d.ts +6 -0
  5. package/dist/src/cli/scan-environment.d.ts.map +1 -0
  6. package/dist/src/cli/scan-environment.js +81 -0
  7. package/dist/src/cli/scan-environment.js.map +1 -0
  8. package/dist/src/cli/scan.d.ts.map +1 -1
  9. package/dist/src/cli/scan.js +5 -2
  10. package/dist/src/cli/scan.js.map +1 -1
  11. package/dist/src/constants.d.ts +1 -1
  12. package/dist/src/constants.d.ts.map +1 -1
  13. package/dist/src/constants.js +20 -1
  14. package/dist/src/constants.js.map +1 -1
  15. package/dist/src/engines/builtin/dependencies.d.ts.map +1 -1
  16. package/dist/src/engines/builtin/dependencies.js +7 -1
  17. package/dist/src/engines/builtin/dependencies.js.map +1 -1
  18. package/dist/src/engines/builtin/environment-scan.d.ts +45 -0
  19. package/dist/src/engines/builtin/environment-scan.d.ts.map +1 -0
  20. package/dist/src/engines/builtin/environment-scan.js +492 -0
  21. package/dist/src/engines/builtin/environment-scan.js.map +1 -0
  22. package/dist/src/engines/builtin/patterns.d.ts.map +1 -1
  23. package/dist/src/engines/builtin/patterns.js +3 -0
  24. package/dist/src/engines/builtin/patterns.js.map +1 -1
  25. package/dist/src/engines/pattern/gitleaks.js +1 -1
  26. package/dist/src/engines/pattern/gitleaks.js.map +1 -1
  27. package/dist/src/mcp/server.d.ts.map +1 -1
  28. package/dist/src/mcp/server.js +6 -0
  29. package/dist/src/mcp/server.js.map +1 -1
  30. package/dist/src/mcp/tools/environment-scan.d.ts +3 -0
  31. package/dist/src/mcp/tools/environment-scan.d.ts.map +1 -0
  32. package/dist/src/mcp/tools/environment-scan.js +5 -0
  33. package/dist/src/mcp/tools/environment-scan.js.map +1 -0
  34. package/package.json +1 -1
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Environment Scanner — detects malicious Claude Code MCP servers, hooks,
3
+ * skills, and prompt-injection in CLAUDE.md files.
4
+ */
5
+ export type ThreatCategory = 'mcp_server' | 'hook' | 'prompt_injection' | 'skill';
6
+ export type ThreatSeverity = 'critical' | 'high' | 'medium' | 'low';
7
+ export interface ThreatPattern {
8
+ id: string;
9
+ category: ThreatCategory;
10
+ severity: ThreatSeverity;
11
+ description: string;
12
+ detect: (content: string) => boolean;
13
+ }
14
+ export interface EnvironmentThreat {
15
+ id: string;
16
+ category: string;
17
+ severity: string;
18
+ description: string;
19
+ location: string;
20
+ evidence: string;
21
+ }
22
+ export interface EnvironmentScanResult {
23
+ status: 'pass' | 'fail';
24
+ threats_found: number;
25
+ threats: EnvironmentThreat[];
26
+ scanned: {
27
+ mcp_configs: string[];
28
+ hooks_file: string | null;
29
+ claude_md_files: string[];
30
+ skill_files: string[];
31
+ };
32
+ }
33
+ export declare const MCP_THREAT_PATTERNS: ThreatPattern[];
34
+ export declare const HOOK_THREAT_PATTERNS: ThreatPattern[];
35
+ export declare const PROMPT_INJECTION_PATTERNS: ThreatPattern[];
36
+ export declare const SKILL_THREAT_PATTERNS: ThreatPattern[];
37
+ export declare const ALL_THREAT_PATTERNS: ThreatPattern[];
38
+ export interface EnvironmentScanOptions {
39
+ /** Override home directory (for testing). */
40
+ homeDir?: string;
41
+ /** Override project directory (for testing). */
42
+ projectDir?: string;
43
+ }
44
+ export declare function scanEnvironment(options?: EnvironmentScanOptions): Promise<EnvironmentScanResult>;
45
+ //# sourceMappingURL=environment-scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment-scan.d.ts","sourceRoot":"","sources":["../../../../src/engines/builtin/environment-scan.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,MAAM,GAAG,kBAAkB,GAAG,OAAO,CAAC;AAClF,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEpE,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,cAAc,CAAC;IACzB,QAAQ,EAAE,cAAc,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;CACtC;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,OAAO,EAAE;QACP,WAAW,EAAE,MAAM,EAAE,CAAC;QACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,WAAW,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;CACH;AAsBD,eAAO,MAAM,mBAAmB,EAAE,aAAa,EA4C9C,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,aAAa,EA0D/C,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,aAAa,EA6FpD,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,aAAa,EAiDhD,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,aAAa,EAK9C,CAAC;AA0JF,MAAM,WAAW,sBAAsB;IACrC,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,eAAe,CACnC,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC,CAiIhC"}
@@ -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;AA+kExD;;;;;;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"}
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;AAilExD;;;;;;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"}
@@ -1122,6 +1122,9 @@ const RULES = [
1122
1122
  detect: (line) => {
1123
1123
  if (/process\s*\.\s*env\b/.test(line) || /os\s*\.\s*(?:environ|getenv)\b/.test(line))
1124
1124
  return false;
1125
+ // Skip localhost/dev connection strings — not production credentials
1126
+ if (/@(?:localhost|127\.0\.0\.1|0\.0\.0\.0|::1)(?:[:/]|$)/i.test(line))
1127
+ return false;
1125
1128
  // Match hardcoded connection strings: mongodb://, postgres://, mysql://, redis:// with credentials
1126
1129
  return /['"](?:mongodb(?:\+srv)?|postgres(?:ql)?|mysql|redis|amqp|mssql):\/\/[^'"]*:[^'"]*@[^'"]+['"]/.test(line);
1127
1130
  },