@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.
@@ -10,6 +10,7 @@ import { registerUploadSourcemapsCommand } from '../src/cli/upload-sourcemaps.js
10
10
  import { registerConfigCommand } from '../src/cli/config.js';
11
11
  import { registerInitCommand } from '../src/cli/init.js';
12
12
  import { registerBaselineCommand } from '../src/cli/baseline.js';
13
+ import { registerScanEnvironmentCommand } from '../src/cli/scan-environment.js';
13
14
  const program = new Command();
14
15
  program
15
16
  .name('shipsafe')
@@ -24,6 +25,7 @@ registerUploadSourcemapsCommand(program);
24
25
  registerConfigCommand(program);
25
26
  registerInitCommand(program);
26
27
  registerBaselineCommand(program);
28
+ registerScanEnvironmentCommand(program);
27
29
  program
28
30
  .command('mcp-server')
29
31
  .description('Start ShipSafe MCP server (stdio transport)')
@@ -1 +1 @@
1
- {"version":3,"file":"shipsafe.js","sourceRoot":"","sources":["../../bin/shipsafe.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,+BAA+B,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,yDAAyD,CAAC;KACtE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,+BAA+B,CAAC,OAAO,CAAC,CAAC;AACzC,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,uBAAuB,CAAC,OAAO,CAAC,CAAC;AAEjC,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,6CAA6C,CAAC;KAC1D,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAChE,MAAM,cAAc,EAAE,CAAC;AACzB,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"shipsafe.js","sourceRoot":"","sources":["../../bin/shipsafe.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,+BAA+B,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAC;AAEhF,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,yDAAyD,CAAC;KACtE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,+BAA+B,CAAC,OAAO,CAAC,CAAC;AACzC,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,8BAA8B,CAAC,OAAO,CAAC,CAAC;AAExC,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,6CAA6C,CAAC;KAC1D,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAChE,MAAM,cAAc,EAAE,CAAC;AACzB,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { Command } from 'commander';
2
+ export declare function handleScanEnvironmentAction(options: {
3
+ json: boolean;
4
+ }): Promise<void>;
5
+ export declare function registerScanEnvironmentCommand(program: Command): void;
6
+ //# sourceMappingURL=scan-environment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-environment.d.ts","sourceRoot":"","sources":["../../../src/cli/scan-environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqEpC,wBAAsB,2BAA2B,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB3F;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAQrE"}
@@ -0,0 +1,81 @@
1
+ import chalk from 'chalk';
2
+ import { scanEnvironment, } from '../engines/builtin/environment-scan.js';
3
+ const SEVERITY_COLORS = {
4
+ critical: chalk.red,
5
+ high: chalk.red,
6
+ medium: chalk.yellow,
7
+ low: chalk.blue,
8
+ };
9
+ const CATEGORY_LABELS = {
10
+ mcp_server: 'MCP Server',
11
+ hook: 'Hook',
12
+ prompt_injection: 'Prompt Injection',
13
+ skill: 'Skill',
14
+ };
15
+ function formatThreat(threat) {
16
+ const colorFn = SEVERITY_COLORS[threat.severity] ?? chalk.white;
17
+ const severityLabel = colorFn(threat.severity.toUpperCase().padEnd(8));
18
+ const categoryLabel = chalk.dim(`[${CATEGORY_LABELS[threat.category] ?? threat.category}]`);
19
+ console.log(` ${severityLabel} ${categoryLabel} ${threat.id}`);
20
+ console.log(` ${threat.description}`);
21
+ console.log(` ${chalk.dim('Location:')} ${threat.location}`);
22
+ if (threat.evidence) {
23
+ console.log(` ${chalk.dim('Evidence:')} ${threat.evidence}`);
24
+ }
25
+ console.log('');
26
+ }
27
+ function formatResults(result) {
28
+ console.log('');
29
+ console.log(chalk.bold(' ShipSafe Environment Scan'));
30
+ console.log(chalk.dim(' ' + '\u2500'.repeat(44)));
31
+ console.log('');
32
+ const check = chalk.green('\u2713');
33
+ // Show what was scanned
34
+ console.log(chalk.dim(' Scanned:'));
35
+ console.log(` ${check} MCP configs: ${result.scanned.mcp_configs.length > 0 ? result.scanned.mcp_configs.join(', ') : chalk.dim('none found')}`);
36
+ console.log(` ${check} Hooks file: ${result.scanned.hooks_file ?? chalk.dim('none found')}`);
37
+ console.log(` ${check} CLAUDE.md files: ${result.scanned.claude_md_files.length > 0 ? result.scanned.claude_md_files.join(', ') : chalk.dim('none found')}`);
38
+ console.log(` ${check} Skill files: ${result.scanned.skill_files.length > 0 ? String(result.scanned.skill_files.length) + ' files' : chalk.dim('none found')}`);
39
+ console.log('');
40
+ // Status
41
+ if (result.status === 'pass') {
42
+ console.log(chalk.green(' \u2713 No threats detected. Environment looks clean.'));
43
+ console.log('');
44
+ return;
45
+ }
46
+ console.log(chalk.red(` \u2717 ${result.threats_found} threat${result.threats_found === 1 ? '' : 's'} detected`));
47
+ console.log('');
48
+ console.log(chalk.dim(' ' + '\u2500'.repeat(44)));
49
+ console.log('');
50
+ for (const threat of result.threats) {
51
+ formatThreat(threat);
52
+ }
53
+ }
54
+ export async function handleScanEnvironmentAction(options) {
55
+ if (!options.json) {
56
+ console.log(chalk.dim('\n Scanning Claude Code environment...'));
57
+ }
58
+ const result = await scanEnvironment();
59
+ if (options.json) {
60
+ console.log(JSON.stringify(result, null, 2));
61
+ }
62
+ else {
63
+ formatResults(result);
64
+ }
65
+ if (result.status === 'fail') {
66
+ const hasCritical = result.threats.some((t) => t.severity === 'critical');
67
+ if (hasCritical) {
68
+ process.exit(1);
69
+ }
70
+ }
71
+ }
72
+ export function registerScanEnvironmentCommand(program) {
73
+ program
74
+ .command('scan-environment')
75
+ .description('Scan Claude Code environment for malicious MCP servers, hooks, skills, and prompt injection')
76
+ .option('--json', 'Output results as JSON', false)
77
+ .action(async (options) => {
78
+ await handleScanEnvironmentAction(options);
79
+ });
80
+ }
81
+ //# sourceMappingURL=scan-environment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-environment.js","sourceRoot":"","sources":["../../../src/cli/scan-environment.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@ export declare const CONFIG_FILE = "shipsafe.config.json";
3
3
  export declare const GLOBAL_DIR_NAME = ".shipsafe";
4
4
  export declare const CLAUDE_MD_START = "<!-- shipsafe:start -->";
5
5
  export declare const CLAUDE_MD_END = "<!-- shipsafe:end -->";
6
- export declare const VERSION = "0.1.0";
6
+ export declare const VERSION: string;
7
7
  export declare const HOOK_MARKER = "# SHIPSAFE_HOOK";
8
8
  export declare const DEFAULT_API_URL = "https://shipsafe-m9nc6.ondigitalocean.app";
9
9
  export declare const EXIT_CODES: {
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,cAAc,CAAC;AACxC,eAAO,MAAM,WAAW,yBAAyB,CAAC;AAClD,eAAO,MAAM,eAAe,cAAc,CAAC;AAC3C,eAAO,MAAM,eAAe,4BAA4B,CAAC;AACzD,eAAO,MAAM,aAAa,0BAA0B,CAAC;AACrD,eAAO,MAAM,OAAO,UAAU,CAAC;AAC/B,eAAO,MAAM,WAAW,oBAAoB,CAAC;AAC7C,eAAO,MAAM,eAAe,8CAA8C,CAAC;AAE3E,eAAO,MAAM,UAAU;;;;;CAKb,CAAC;AAEX,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMjD,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE;IAC3B,UAAU,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAC;QAAC,uBAAuB,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7F,IAAI,EAAE;QAAE,YAAY,EAAE,MAAM,EAAE,CAAC;QAAC,YAAY,EAAE,MAAM,EAAE,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAA;KAAE,CAAC;CAYtF,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,cAAc,CAAC;AACxC,eAAO,MAAM,WAAW,yBAAyB,CAAC;AAClD,eAAO,MAAM,eAAe,cAAc,CAAC;AAC3C,eAAO,MAAM,eAAe,4BAA4B,CAAC;AACzD,eAAO,MAAM,aAAa,0BAA0B,CAAC;AAmBrD,eAAO,MAAM,OAAO,QAAgB,CAAC;AACrC,eAAO,MAAM,WAAW,oBAAoB,CAAC;AAC7C,eAAO,MAAM,eAAe,8CAA8C,CAAC;AAE3E,eAAO,MAAM,UAAU;;;;;CAKb,CAAC;AAEX,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMjD,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE;IAC3B,UAAU,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAC;QAAC,uBAAuB,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7F,IAAI,EAAE;QAAE,YAAY,EAAE,MAAM,EAAE,CAAC;QAAC,YAAY,EAAE,MAAM,EAAE,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAA;KAAE,CAAC;CAYtF,CAAC"}
@@ -3,7 +3,26 @@ export const CONFIG_FILE = 'shipsafe.config.json';
3
3
  export const GLOBAL_DIR_NAME = '.shipsafe';
4
4
  export const CLAUDE_MD_START = '<!-- shipsafe:start -->';
5
5
  export const CLAUDE_MD_END = '<!-- shipsafe:end -->';
6
- export const VERSION = '0.1.0';
6
+ import { readFileSync } from 'node:fs';
7
+ import { join, dirname } from 'node:path';
8
+ import { fileURLToPath } from 'node:url';
9
+ function readVersion() {
10
+ try {
11
+ // Walk up from dist/src/ or src/ to find package.json
12
+ let dir = dirname(fileURLToPath(import.meta.url));
13
+ for (let i = 0; i < 5; i++) {
14
+ try {
15
+ const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf-8'));
16
+ return pkg.version;
17
+ }
18
+ catch { /* not found here */ }
19
+ dir = dirname(dir);
20
+ }
21
+ }
22
+ catch { /* fallback */ }
23
+ return '0.3.1';
24
+ }
25
+ export const VERSION = readVersion();
7
26
  export const HOOK_MARKER = '# SHIPSAFE_HOOK';
8
27
  export const DEFAULT_API_URL = 'https://shipsafe-m9nc6.ondigitalocean.app';
9
28
  export const EXIT_CODES = {
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAC;AACxC,MAAM,CAAC,MAAM,WAAW,GAAG,sBAAsB,CAAC;AAClD,MAAM,CAAC,MAAM,eAAe,GAAG,WAAW,CAAC;AAC3C,MAAM,CAAC,MAAM,eAAe,GAAG,yBAAyB,CAAC;AACzD,MAAM,CAAC,MAAM,aAAa,GAAG,uBAAuB,CAAC;AACrD,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAC/B,MAAM,CAAC,MAAM,WAAW,GAAG,iBAAiB,CAAC;AAC7C,MAAM,CAAC,MAAM,eAAe,GAAG,2CAA2C,CAAC;AAE3E,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,CAAC;IACZ,YAAY,EAAE,CAAC;IACf,YAAY,EAAE,CAAC;CACP,CAAC;AAEX,MAAM,CAAC,MAAM,cAAc,GAA2B;IACpD,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;CACR,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAGvB;IACF,UAAU,EAAE;QACV,OAAO,EAAE,IAAI;QACb,iBAAiB,EAAE,GAAG;QACtB,uBAAuB,EAAE,GAAG;KAC7B;IACD,IAAI,EAAE;QACJ,YAAY,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC;QAC1D,YAAY,EAAE,EAAE;QAChB,kBAAkB,EAAE,MAAM;KAC3B;CACF,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAC;AACxC,MAAM,CAAC,MAAM,WAAW,GAAG,sBAAsB,CAAC;AAClD,MAAM,CAAC,MAAM,eAAe,GAAG,WAAW,CAAC;AAC3C,MAAM,CAAC,MAAM,eAAe,GAAG,yBAAyB,CAAC;AACzD,MAAM,CAAC,MAAM,aAAa,GAAG,uBAAuB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,SAAS,WAAW;IAClB,IAAI,CAAC;QACH,sDAAsD;QACtD,IAAI,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAwB,CAAC;gBAChG,OAAO,GAAG,CAAC,OAAO,CAAC;YACrB,CAAC;YAAC,MAAM,CAAC,CAAC,oBAAoB,CAAC,CAAC;YAChC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,cAAc,CAAC,CAAC;IAC1B,OAAO,OAAO,CAAC;AACjB,CAAC;AACD,MAAM,CAAC,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;AACrC,MAAM,CAAC,MAAM,WAAW,GAAG,iBAAiB,CAAC;AAC7C,MAAM,CAAC,MAAM,eAAe,GAAG,2CAA2C,CAAC;AAE3E,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,CAAC;IACZ,YAAY,EAAE,CAAC;IACf,YAAY,EAAE,CAAC;CACP,CAAC;AAEX,MAAM,CAAC,MAAM,cAAc,GAA2B;IACpD,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;CACR,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAGvB;IACF,UAAU,EAAE;QACV,OAAO,EAAE,IAAI;QACb,iBAAiB,EAAE,GAAG;QACtB,uBAAuB,EAAE,GAAG;KAC7B;IACD,IAAI,EAAE;QACJ,YAAY,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC;QAC1D,YAAY,EAAE,EAAE;QAChB,kBAAkB,EAAE,MAAM;KAC3B;CACF,CAAC"}
@@ -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"}