hackmyagent 0.8.0 → 0.9.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.
Files changed (86) hide show
  1. package/README.md +168 -295
  2. package/dist/abgr/controls.d.ts +35 -0
  3. package/dist/abgr/controls.d.ts.map +1 -0
  4. package/dist/abgr/controls.js +1058 -0
  5. package/dist/abgr/controls.js.map +1 -0
  6. package/dist/abgr/detector.d.ts +45 -0
  7. package/dist/abgr/detector.d.ts.map +1 -0
  8. package/dist/abgr/detector.js +175 -0
  9. package/dist/abgr/detector.js.map +1 -0
  10. package/dist/abgr/index.d.ts +24 -0
  11. package/dist/abgr/index.d.ts.map +1 -0
  12. package/dist/abgr/index.js +50 -0
  13. package/dist/abgr/index.js.map +1 -0
  14. package/dist/abgr/scorer.d.ts +36 -0
  15. package/dist/abgr/scorer.d.ts.map +1 -0
  16. package/dist/abgr/scorer.js +205 -0
  17. package/dist/abgr/scorer.js.map +1 -0
  18. package/dist/abgr/templates.d.ts +35 -0
  19. package/dist/abgr/templates.d.ts.map +1 -0
  20. package/dist/abgr/templates.js +668 -0
  21. package/dist/abgr/templates.js.map +1 -0
  22. package/dist/abgr/tier.d.ts +27 -0
  23. package/dist/abgr/tier.d.ts.map +1 -0
  24. package/dist/abgr/tier.js +115 -0
  25. package/dist/abgr/tier.js.map +1 -0
  26. package/dist/abgr/types.d.ts +59 -0
  27. package/dist/abgr/types.d.ts.map +1 -0
  28. package/dist/abgr/types.js +10 -0
  29. package/dist/abgr/types.js.map +1 -0
  30. package/dist/agent-scan/checks.d.ts +6 -0
  31. package/dist/agent-scan/checks.d.ts.map +1 -0
  32. package/dist/agent-scan/checks.js +93 -0
  33. package/dist/agent-scan/checks.js.map +1 -0
  34. package/dist/agent-scan/index.d.ts +10 -0
  35. package/dist/agent-scan/index.d.ts.map +1 -0
  36. package/dist/agent-scan/index.js +16 -0
  37. package/dist/agent-scan/index.js.map +1 -0
  38. package/dist/agent-scan/scanner.d.ts +31 -0
  39. package/dist/agent-scan/scanner.d.ts.map +1 -0
  40. package/dist/agent-scan/scanner.js +484 -0
  41. package/dist/agent-scan/scanner.js.map +1 -0
  42. package/dist/agent-scan/types.d.ts +63 -0
  43. package/dist/agent-scan/types.d.ts.map +1 -0
  44. package/dist/agent-scan/types.js +10 -0
  45. package/dist/agent-scan/types.js.map +1 -0
  46. package/dist/arp/cli/index.js +6 -0
  47. package/dist/arp/cli/index.js.map +1 -1
  48. package/dist/cli.js +219 -0
  49. package/dist/cli.js.map +1 -1
  50. package/dist/hardening/llm-checks.d.ts +18 -0
  51. package/dist/hardening/llm-checks.d.ts.map +1 -0
  52. package/dist/hardening/llm-checks.js +434 -0
  53. package/dist/hardening/llm-checks.js.map +1 -0
  54. package/dist/hardening/mcp-tool-enum.d.ts +45 -0
  55. package/dist/hardening/mcp-tool-enum.d.ts.map +1 -0
  56. package/dist/hardening/mcp-tool-enum.js +315 -0
  57. package/dist/hardening/mcp-tool-enum.js.map +1 -0
  58. package/dist/hardening/scanner.js +3 -3
  59. package/dist/hardening/scanner.js.map +1 -1
  60. package/dist/hardening/shell-checks.d.ts +21 -0
  61. package/dist/hardening/shell-checks.d.ts.map +1 -0
  62. package/dist/hardening/shell-checks.js +236 -0
  63. package/dist/hardening/shell-checks.js.map +1 -0
  64. package/dist/index.d.ts +4 -0
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +9 -1
  67. package/dist/index.js.map +1 -1
  68. package/dist/registry/client.js +2 -2
  69. package/dist/registry/client.js.map +1 -1
  70. package/dist/registry/contribution.d.ts +178 -0
  71. package/dist/registry/contribution.d.ts.map +1 -0
  72. package/dist/registry/contribution.js +272 -0
  73. package/dist/registry/contribution.js.map +1 -0
  74. package/dist/soul/index.d.ts +8 -0
  75. package/dist/soul/index.d.ts.map +1 -0
  76. package/dist/soul/index.js +14 -0
  77. package/dist/soul/index.js.map +1 -0
  78. package/dist/soul/scanner.d.ts +95 -0
  79. package/dist/soul/scanner.d.ts.map +1 -0
  80. package/dist/soul/scanner.js +411 -0
  81. package/dist/soul/scanner.js.map +1 -0
  82. package/dist/soul/templates.d.ts +12 -0
  83. package/dist/soul/templates.d.ts.map +1 -0
  84. package/dist/soul/templates.js +211 -0
  85. package/dist/soul/templates.js.map +1 -0
  86. package/package.json +1 -1
@@ -0,0 +1,315 @@
1
+ "use strict";
2
+ /**
3
+ * MCP Tool Enumeration (MCPTOOL-001 to MCPTOOL-005)
4
+ *
5
+ * Connects to configured MCP servers, discovers their tools via JSON-RPC,
6
+ * and classifies dangerous capabilities. Only runs with --deep or --live-mcp flag.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.discoverMcpConfigs = discoverMcpConfigs;
43
+ exports.enumerateStdioTools = enumerateStdioTools;
44
+ exports.classifyTools = classifyTools;
45
+ exports.checkMcpToolEnumeration = checkMcpToolEnumeration;
46
+ const child_process_1 = require("child_process");
47
+ const fs = __importStar(require("fs/promises"));
48
+ const path = __importStar(require("path"));
49
+ const os = __importStar(require("os"));
50
+ // Dangerous capability classification
51
+ const EXECUTION_TOOLS = new Set([
52
+ 'execute_command', 'bash', 'shell', 'run_command', 'exec',
53
+ 'run_script', 'terminal', 'execute', 'run', 'system',
54
+ 'execute_shell', 'run_shell', 'subprocess',
55
+ ]);
56
+ const FILESYSTEM_WRITE_TOOLS = new Set([
57
+ 'write_file', 'create_file', 'delete_file', 'edit_file',
58
+ 'write', 'remove_file', 'mkdir', 'rename_file', 'move_file',
59
+ 'append_file', 'overwrite_file', 'file_write',
60
+ ]);
61
+ const NETWORK_TOOLS = new Set([
62
+ 'fetch', 'http_request', 'curl', 'wget', 'request',
63
+ 'http_get', 'http_post', 'web_request', 'send_request',
64
+ 'make_request', 'api_call',
65
+ ]);
66
+ const CREDENTIAL_TOOLS = new Set([
67
+ 'get_secret', 'read_env', 'get_credential', 'get_password',
68
+ 'read_secret', 'fetch_secret', 'env_var', 'get_token',
69
+ 'read_keychain', 'get_api_key',
70
+ ]);
71
+ const SPAWN_TIMEOUT_MS = 5000;
72
+ const JSON_RPC_VERSION = '2.0';
73
+ /**
74
+ * Discover MCP server configurations from known config file locations.
75
+ */
76
+ async function discoverMcpConfigs(targetDir) {
77
+ const configs = new Map();
78
+ const configPaths = [
79
+ path.join(targetDir, 'mcp.json'),
80
+ path.join(targetDir, '.cursor', 'mcp.json'),
81
+ path.join(targetDir, '.vscode', 'mcp.json'),
82
+ path.join(os.homedir(), '.claude', 'settings.json'),
83
+ ];
84
+ for (const configPath of configPaths) {
85
+ try {
86
+ const content = await fs.readFile(configPath, 'utf-8');
87
+ const parsed = JSON.parse(content);
88
+ // Handle different config formats
89
+ const servers = parsed.mcpServers || parsed.servers || {};
90
+ for (const [name, serverConfig] of Object.entries(servers)) {
91
+ const config = serverConfig;
92
+ if (config.command || config.url) {
93
+ configs.set(name, {
94
+ config: {
95
+ command: config.command,
96
+ args: config.args,
97
+ env: config.env,
98
+ url: config.url,
99
+ },
100
+ configPath,
101
+ });
102
+ }
103
+ }
104
+ }
105
+ catch {
106
+ // Config file doesn't exist or is invalid, skip
107
+ }
108
+ }
109
+ return configs;
110
+ }
111
+ /**
112
+ * Connect to a stdio MCP server and enumerate its tools.
113
+ */
114
+ async function enumerateStdioTools(serverName, config) {
115
+ return new Promise((resolve) => {
116
+ let child = null;
117
+ let buffer = '';
118
+ let resolved = false;
119
+ const cleanup = () => {
120
+ if (child && !child.killed) {
121
+ child.kill('SIGTERM');
122
+ }
123
+ };
124
+ const finish = (result) => {
125
+ if (!resolved) {
126
+ resolved = true;
127
+ cleanup();
128
+ resolve(result);
129
+ }
130
+ };
131
+ // Timeout
132
+ const timer = setTimeout(() => {
133
+ finish({ serverName, configPath: '', tools: [], error: 'Timeout after 5s' });
134
+ }, SPAWN_TIMEOUT_MS);
135
+ try {
136
+ child = (0, child_process_1.spawn)(config.command, config.args || [], {
137
+ stdio: ['pipe', 'pipe', 'pipe'],
138
+ env: { ...process.env, ...config.env },
139
+ });
140
+ child.on('error', (err) => {
141
+ clearTimeout(timer);
142
+ finish({ serverName, configPath: '', tools: [], error: err.message });
143
+ });
144
+ child.stdout?.on('data', (data) => {
145
+ buffer += data.toString();
146
+ // Try to parse JSON-RPC responses
147
+ const lines = buffer.split('\n');
148
+ for (const line of lines) {
149
+ const trimmed = line.trim();
150
+ if (!trimmed)
151
+ continue;
152
+ try {
153
+ const msg = JSON.parse(trimmed);
154
+ // Response to initialize
155
+ if (msg.id === 1 && msg.result) {
156
+ // Send tools/list
157
+ const toolsRequest = JSON.stringify({
158
+ jsonrpc: JSON_RPC_VERSION,
159
+ id: 2,
160
+ method: 'tools/list',
161
+ params: {},
162
+ }) + '\n';
163
+ child?.stdin?.write(toolsRequest);
164
+ }
165
+ // Response to tools/list
166
+ if (msg.id === 2 && msg.result) {
167
+ clearTimeout(timer);
168
+ const tools = (msg.result.tools || []).map((t) => ({
169
+ name: t.name,
170
+ description: t.description,
171
+ inputSchema: t.inputSchema,
172
+ }));
173
+ finish({ serverName, configPath: '', tools });
174
+ }
175
+ }
176
+ catch {
177
+ // Not valid JSON, skip
178
+ }
179
+ }
180
+ // Keep only the last incomplete line in buffer
181
+ buffer = lines[lines.length - 1] || '';
182
+ });
183
+ // Send initialize request
184
+ const initRequest = JSON.stringify({
185
+ jsonrpc: JSON_RPC_VERSION,
186
+ id: 1,
187
+ method: 'initialize',
188
+ params: {
189
+ protocolVersion: '2024-11-05',
190
+ capabilities: {},
191
+ clientInfo: { name: 'hackmyagent-scanner', version: '0.8.0' },
192
+ },
193
+ }) + '\n';
194
+ child.stdin?.write(initRequest);
195
+ }
196
+ catch (err) {
197
+ clearTimeout(timer);
198
+ finish({ serverName, configPath: '', tools: [], error: err.message });
199
+ }
200
+ });
201
+ }
202
+ /**
203
+ * Classify tool capabilities and generate security findings.
204
+ */
205
+ function classifyTools(serverName, configPath, tools) {
206
+ const findings = [];
207
+ // MCPTOOL-001: Execution tools
208
+ const execTools = tools.filter((t) => EXECUTION_TOOLS.has(t.name.toLowerCase()));
209
+ if (execTools.length > 0) {
210
+ findings.push({
211
+ checkId: 'MCPTOOL-001',
212
+ name: 'MCP server exposes command execution',
213
+ description: `MCP server "${serverName}" provides tools that can execute arbitrary commands: ${execTools.map((t) => t.name).join(', ')}. This allows the AI to run any system command.`,
214
+ category: 'mcp-capability',
215
+ severity: 'critical',
216
+ passed: false,
217
+ message: `${serverName}: ${execTools.length} execution tool(s) exposed`,
218
+ fixable: false,
219
+ file: configPath,
220
+ fix: 'Restrict command execution tools or add an allowlist of permitted commands.',
221
+ });
222
+ }
223
+ // MCPTOOL-002: Filesystem write tools
224
+ const fsWriteTools = tools.filter((t) => FILESYSTEM_WRITE_TOOLS.has(t.name.toLowerCase()));
225
+ if (fsWriteTools.length > 0) {
226
+ findings.push({
227
+ checkId: 'MCPTOOL-002',
228
+ name: 'MCP server exposes filesystem write',
229
+ description: `MCP server "${serverName}" provides tools that can write/delete files: ${fsWriteTools.map((t) => t.name).join(', ')}. This allows modifying system files.`,
230
+ category: 'mcp-capability',
231
+ severity: 'high',
232
+ passed: false,
233
+ message: `${serverName}: ${fsWriteTools.length} filesystem write tool(s) exposed`,
234
+ fixable: false,
235
+ file: configPath,
236
+ fix: 'Add path restrictions to filesystem write tools.',
237
+ });
238
+ }
239
+ // MCPTOOL-003: Unrestricted network tools
240
+ const netTools = tools.filter((t) => NETWORK_TOOLS.has(t.name.toLowerCase()));
241
+ if (netTools.length > 0) {
242
+ findings.push({
243
+ checkId: 'MCPTOOL-003',
244
+ name: 'MCP server exposes unrestricted network access',
245
+ description: `MCP server "${serverName}" provides tools for network requests: ${netTools.map((t) => t.name).join(', ')}. This allows data exfiltration.`,
246
+ category: 'mcp-capability',
247
+ severity: 'high',
248
+ passed: false,
249
+ message: `${serverName}: ${netTools.length} network tool(s) exposed`,
250
+ fixable: false,
251
+ file: configPath,
252
+ fix: 'Restrict network access to specific domains or add an allowlist.',
253
+ });
254
+ }
255
+ // MCPTOOL-004: Credential-accessing tools
256
+ const credTools = tools.filter((t) => CREDENTIAL_TOOLS.has(t.name.toLowerCase()));
257
+ if (credTools.length > 0) {
258
+ findings.push({
259
+ checkId: 'MCPTOOL-004',
260
+ name: 'MCP server exposes credential access',
261
+ description: `MCP server "${serverName}" provides tools that access credentials: ${credTools.map((t) => t.name).join(', ')}.`,
262
+ category: 'mcp-capability',
263
+ severity: 'critical',
264
+ passed: false,
265
+ message: `${serverName}: ${credTools.length} credential-accessing tool(s) exposed`,
266
+ fixable: false,
267
+ file: configPath,
268
+ fix: 'Remove credential access tools or use secretless-ai broker for credential isolation.',
269
+ });
270
+ }
271
+ // MCPTOOL-005: Server with 10+ tools and no apparent access control
272
+ if (tools.length >= 10) {
273
+ findings.push({
274
+ checkId: 'MCPTOOL-005',
275
+ name: 'MCP server exposes excessive tools',
276
+ description: `MCP server "${serverName}" exposes ${tools.length} tools. Large tool surfaces increase the attack area for prompt injection.`,
277
+ category: 'mcp-capability',
278
+ severity: 'medium',
279
+ passed: false,
280
+ message: `${serverName}: ${tools.length} tools exposed (threshold: 10)`,
281
+ fixable: false,
282
+ file: configPath,
283
+ fix: 'Reduce the number of exposed tools or implement per-tool access controls.',
284
+ });
285
+ }
286
+ return findings;
287
+ }
288
+ /**
289
+ * Run full MCP tool enumeration scan.
290
+ * Discovers MCP configs, connects to each server, enumerates tools, classifies dangers.
291
+ */
292
+ async function checkMcpToolEnumeration(targetDir, onProgress) {
293
+ const findings = [];
294
+ const configs = await discoverMcpConfigs(targetDir);
295
+ if (configs.size === 0)
296
+ return findings;
297
+ onProgress?.(`Found ${configs.size} MCP server(s), enumerating tools...`);
298
+ for (const [serverName, { config, configPath }] of configs) {
299
+ onProgress?.(`Scanning ${serverName}...`);
300
+ if (config.command) {
301
+ const result = await enumerateStdioTools(serverName, config);
302
+ if (result.error) {
303
+ // Non-fatal: server couldn't be reached
304
+ onProgress?.(` ${serverName}: ${result.error}`);
305
+ continue;
306
+ }
307
+ const serverFindings = classifyTools(serverName, configPath, result.tools);
308
+ findings.push(...serverFindings);
309
+ onProgress?.(` ${serverName}: ${result.tools.length} tools, ${serverFindings.length} findings`);
310
+ }
311
+ // SSE servers would go here (future)
312
+ }
313
+ return findings;
314
+ }
315
+ //# sourceMappingURL=mcp-tool-enum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-tool-enum.js","sourceRoot":"","sources":["../../src/hardening/mcp-tool-enum.ts"],"names":[],"mappings":"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"}
@@ -3689,7 +3689,7 @@ dist/
3689
3689
  await fs.access(backupBaseDir);
3690
3690
  }
3691
3691
  catch {
3692
- throw new Error('No backup found. Cannot rollback.');
3692
+ throw new Error('No backup found. Run hackmyagent harden --fix <dir> first to create a backup.');
3693
3693
  }
3694
3694
  // Find the most recent backup
3695
3695
  const backups = await fs.readdir(backupBaseDir);
@@ -3698,7 +3698,7 @@ dist/
3698
3698
  .sort()
3699
3699
  .reverse();
3700
3700
  if (sortedBackups.length === 0) {
3701
- throw new Error('No backup found. Cannot rollback.');
3701
+ throw new Error('No backup found. Run hackmyagent harden --fix <dir> first to create a backup.');
3702
3702
  }
3703
3703
  const latestBackup = sortedBackups[0];
3704
3704
  const backupDir = path.join(backupBaseDir, latestBackup);
@@ -3709,7 +3709,7 @@ dist/
3709
3709
  manifest = JSON.parse(manifestContent);
3710
3710
  }
3711
3711
  catch {
3712
- throw new Error('Backup manifest is corrupted. Cannot rollback.');
3712
+ throw new Error('Backup manifest is corrupted. Delete ~/.hackmyagent/backups/ and re-run hackmyagent harden --fix.');
3713
3713
  }
3714
3714
  // Restore existing files from backup
3715
3715
  for (const file of manifest.existingFiles) {