monomind 1.17.0 → 1.17.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 (94) hide show
  1. package/.claude/agents/engineering/engineering-security-engineer.md +1 -1
  2. package/.claude/commands/mastermind/_repeat.md +4 -0
  3. package/.claude/commands/mastermind/master.md +52 -1
  4. package/.claude/scheduled_tasks.lock +1 -1
  5. package/.claude/skills/mastermind/_repeat.md +2 -0
  6. package/package.json +1 -1
  7. package/packages/@monomind/cli/.claude/agents/engineering/engineering-security-engineer.md +1 -1
  8. package/packages/@monomind/cli/.claude/commands/mastermind/_repeat.md +4 -0
  9. package/packages/@monomind/cli/.claude/commands/mastermind/master.md +52 -1
  10. package/packages/@monomind/cli/.claude/skills/mastermind/_repeat.md +2 -0
  11. package/packages/@monomind/cli/dist/src/__tests__/browse-analyzer.test.js +42 -59
  12. package/packages/@monomind/cli/dist/src/agents/registry-builder.d.ts +8 -0
  13. package/packages/@monomind/cli/dist/src/agents/registry-builder.js +22 -0
  14. package/packages/@monomind/cli/dist/src/browser/dashboard/server.js +18 -0
  15. package/packages/@monomind/cli/dist/src/browser/dashboard/ui.html +37 -125
  16. package/packages/@monomind/cli/dist/src/commands/agent-lifecycle.d.ts +17 -0
  17. package/packages/@monomind/cli/dist/src/commands/agent-lifecycle.js +320 -0
  18. package/packages/@monomind/cli/dist/src/commands/agent-ops.d.ts +9 -0
  19. package/packages/@monomind/cli/dist/src/commands/agent-ops.js +329 -0
  20. package/packages/@monomind/cli/dist/src/commands/agent.js +5 -907
  21. package/packages/@monomind/cli/dist/src/commands/analyze-ast.d.ts +26 -0
  22. package/packages/@monomind/cli/dist/src/commands/analyze-ast.js +284 -0
  23. package/packages/@monomind/cli/dist/src/commands/analyze-boundaries.d.ts +14 -0
  24. package/packages/@monomind/cli/dist/src/commands/analyze-boundaries.js +295 -0
  25. package/packages/@monomind/cli/dist/src/commands/analyze-diff.d.ts +8 -0
  26. package/packages/@monomind/cli/dist/src/commands/analyze-diff.js +395 -0
  27. package/packages/@monomind/cli/dist/src/commands/analyze-graph.d.ts +14 -0
  28. package/packages/@monomind/cli/dist/src/commands/analyze-graph.js +304 -0
  29. package/packages/@monomind/cli/dist/src/commands/analyze-imports.d.ts +11 -0
  30. package/packages/@monomind/cli/dist/src/commands/analyze-imports.js +287 -0
  31. package/packages/@monomind/cli/dist/src/commands/analyze-symbols.d.ts +14 -0
  32. package/packages/@monomind/cli/dist/src/commands/analyze-symbols.js +302 -0
  33. package/packages/@monomind/cli/dist/src/commands/analyze.d.ts +38 -0
  34. package/packages/@monomind/cli/dist/src/commands/analyze.js +12 -1827
  35. package/packages/@monomind/cli/dist/src/commands/doctor-env-checks.d.ts +26 -0
  36. package/packages/@monomind/cli/dist/src/commands/doctor-env-checks.js +189 -0
  37. package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.d.ts +20 -0
  38. package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.js +432 -0
  39. package/packages/@monomind/cli/dist/src/commands/doctor.js +54 -943
  40. package/packages/@monomind/cli/dist/src/commands/hive-mind-comms.d.ts +11 -0
  41. package/packages/@monomind/cli/dist/src/commands/hive-mind-comms.js +242 -0
  42. package/packages/@monomind/cli/dist/src/commands/hive-mind-helpers.d.ts +35 -0
  43. package/packages/@monomind/cli/dist/src/commands/hive-mind-helpers.js +203 -0
  44. package/packages/@monomind/cli/dist/src/commands/hive-mind-ops.d.ts +8 -0
  45. package/packages/@monomind/cli/dist/src/commands/hive-mind-ops.js +233 -0
  46. package/packages/@monomind/cli/dist/src/commands/hive-mind-spawn.d.ts +12 -0
  47. package/packages/@monomind/cli/dist/src/commands/hive-mind-spawn.js +274 -0
  48. package/packages/@monomind/cli/dist/src/commands/hive-mind.js +10 -1129
  49. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.d.ts +4 -4
  50. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.js +19 -819
  51. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-gaps.d.ts +7 -0
  52. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-gaps.js +334 -0
  53. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-routing.d.ts +7 -0
  54. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-routing.js +399 -0
  55. package/packages/@monomind/cli/dist/src/commands/init-subcommands.d.ts +8 -0
  56. package/packages/@monomind/cli/dist/src/commands/init-subcommands.js +156 -0
  57. package/packages/@monomind/cli/dist/src/commands/init-upgrade.d.ts +6 -0
  58. package/packages/@monomind/cli/dist/src/commands/init-upgrade.js +203 -0
  59. package/packages/@monomind/cli/dist/src/commands/init-wizard.d.ts +6 -0
  60. package/packages/@monomind/cli/dist/src/commands/init-wizard.js +246 -0
  61. package/packages/@monomind/cli/dist/src/commands/init.js +6 -623
  62. package/packages/@monomind/cli/dist/src/commands/memory-admin.d.ts +10 -0
  63. package/packages/@monomind/cli/dist/src/commands/memory-admin.js +433 -0
  64. package/packages/@monomind/cli/dist/src/commands/memory-crud.d.ts +9 -0
  65. package/packages/@monomind/cli/dist/src/commands/memory-crud.js +342 -0
  66. package/packages/@monomind/cli/dist/src/commands/memory-list.d.ts +10 -0
  67. package/packages/@monomind/cli/dist/src/commands/memory-list.js +321 -0
  68. package/packages/@monomind/cli/dist/src/commands/memory-transfer.d.ts +9 -0
  69. package/packages/@monomind/cli/dist/src/commands/memory-transfer.js +372 -0
  70. package/packages/@monomind/cli/dist/src/commands/memory.d.ts +6 -0
  71. package/packages/@monomind/cli/dist/src/commands/memory.js +10 -1441
  72. package/packages/@monomind/cli/dist/src/commands/neural-core.d.ts +8 -0
  73. package/packages/@monomind/cli/dist/src/commands/neural-core.js +274 -0
  74. package/packages/@monomind/cli/dist/src/commands/neural-optimize.d.ts +7 -0
  75. package/packages/@monomind/cli/dist/src/commands/neural-optimize.js +332 -0
  76. package/packages/@monomind/cli/dist/src/commands/neural-registry.d.ts +7 -0
  77. package/packages/@monomind/cli/dist/src/commands/neural-registry.js +290 -0
  78. package/packages/@monomind/cli/dist/src/commands/neural.js +3 -974
  79. package/packages/@monomind/cli/dist/src/commands/platforms.js +327 -7
  80. package/packages/@monomind/cli/dist/src/commands/security-cve.d.ts +6 -0
  81. package/packages/@monomind/cli/dist/src/commands/security-cve.js +310 -0
  82. package/packages/@monomind/cli/dist/src/commands/security-misc.d.ts +9 -0
  83. package/packages/@monomind/cli/dist/src/commands/security-misc.js +293 -0
  84. package/packages/@monomind/cli/dist/src/commands/security-scan.d.ts +18 -0
  85. package/packages/@monomind/cli/dist/src/commands/security-scan.js +328 -0
  86. package/packages/@monomind/cli/dist/src/commands/security.js +3 -958
  87. package/packages/@monomind/cli/dist/src/commands/session.js +1 -1
  88. package/packages/@monomind/cli/dist/src/commands/swarm.js +23 -17
  89. package/packages/@monomind/cli/dist/src/index.js +8 -37
  90. package/packages/@monomind/cli/dist/src/mcp-tools/swarm-tools.js +77 -0
  91. package/packages/@monomind/cli/dist/src/parser.js +11 -6
  92. package/packages/@monomind/cli/dist/src/routing/llm-caller.js +1 -2
  93. package/packages/@monomind/cli/package.json +2 -3
  94. package/packages/@monomind/cli/scripts/understand-analyze.mjs +1 -1
@@ -0,0 +1,310 @@
1
+ /**
2
+ * Security CVE command — NVD/OSV lookups and npm audit vulnerability listing
3
+ */
4
+ import { output } from '../output.js';
5
+ import { statSync, readFileSync, mkdirSync, writeFileSync, renameSync } from 'fs';
6
+ import { join } from 'path';
7
+ import { execFile } from 'child_process';
8
+ import { promisify } from 'util';
9
+ import * as https from 'https';
10
+ // ─── CVE helpers ─────────────────────────────────────────────────────────────
11
+ const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
12
+ function getCveCache(cveId, cacheDir) {
13
+ const filePath = join(cacheDir, `${cveId.toUpperCase()}.json`);
14
+ try {
15
+ const stat = statSync(filePath);
16
+ if (Date.now() - stat.mtimeMs > CACHE_TTL_MS)
17
+ return null;
18
+ return JSON.parse(readFileSync(filePath, 'utf8'));
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ }
24
+ const CVE_ID_RE = /^CVE-\d{4}-\d{4,}$/i;
25
+ function saveCveCache(cveId, cacheDir, data) {
26
+ if (!CVE_ID_RE.test(cveId))
27
+ throw new Error('Invalid CVE ID');
28
+ mkdirSync(cacheDir, { recursive: true });
29
+ const dest = join(cacheDir, `${cveId.toUpperCase()}.json`);
30
+ const tmp = dest + '.tmp';
31
+ writeFileSync(tmp, JSON.stringify(data));
32
+ renameSync(tmp, dest);
33
+ }
34
+ function httpsGet(url, timeoutMs = 10_000) {
35
+ return new Promise((resolve, reject) => {
36
+ const req = https.get(url, { headers: { 'User-Agent': 'monomind-cli/1.0' }, timeout: timeoutMs }, (res) => {
37
+ if (res.statusCode !== 200) {
38
+ req.destroy();
39
+ reject(new Error(`HTTP ${res.statusCode}`));
40
+ return;
41
+ }
42
+ let data = '';
43
+ res.on('data', (chunk) => { data += chunk; });
44
+ res.on('end', () => resolve(data));
45
+ });
46
+ req.on('timeout', () => req.destroy(new Error(`Request timed out after ${timeoutMs}ms`)));
47
+ req.on('error', reject);
48
+ });
49
+ }
50
+ function severityColor(severity, score) {
51
+ const s = (severity || '').toUpperCase();
52
+ const label = s + (score !== undefined ? ` (${score})` : '');
53
+ if (s === 'CRITICAL')
54
+ return output.error(label);
55
+ if (s === 'HIGH')
56
+ return output.warning(label);
57
+ if (s === 'MEDIUM')
58
+ return output.info(label);
59
+ return output.dim(label || 'UNKNOWN');
60
+ }
61
+ const execFileAsync = promisify(execFile);
62
+ // ─── cve subcommand ──────────────────────────────────────────────────────────
63
+ export const cveCommand = {
64
+ name: 'cve',
65
+ description: 'Check CVEs via NVD/OSV or list project vulnerabilities via npm audit',
66
+ options: [
67
+ { name: 'check', short: 'c', type: 'string', description: 'Check specific CVE ID (e.g. CVE-2024-1234)' },
68
+ { name: 'list', short: 'l', type: 'boolean', description: 'List all vulnerabilities via npm audit' },
69
+ { name: 'severity', short: 's', type: 'string', description: 'Filter by severity: critical, high, medium, low' },
70
+ { name: 'json', type: 'boolean', description: 'Output as JSON' },
71
+ { name: 'no-cache', type: 'boolean', description: 'Skip cache and fetch fresh data' },
72
+ ],
73
+ examples: [
74
+ { command: 'monomind security cve --list', description: 'List vulnerabilities from npm audit' },
75
+ { command: 'monomind security cve -c CVE-2024-1234', description: 'Check specific CVE via NVD/OSV' },
76
+ { command: 'monomind security cve --list --severity high', description: 'Show only high-severity issues' },
77
+ ],
78
+ action: async (ctx) => {
79
+ const checkCve = ctx.flags.check;
80
+ const doList = ctx.flags.list;
81
+ const severityFilter = ctx.flags.severity?.toLowerCase();
82
+ const jsonOutput = ctx.flags.json;
83
+ const noCache = ctx.flags['no-cache'];
84
+ output.writeln();
85
+ output.writeln(output.bold('CVE / Vulnerability Scanner'));
86
+ output.writeln(output.dim('─'.repeat(50)));
87
+ // ── --check CVE-XXXX-YYYY ──────────────────────────────────────────────
88
+ if (checkCve) {
89
+ const CVE_PATTERN = /^CVE-\d{4}-\d{4,}$/i;
90
+ if (!CVE_PATTERN.test(checkCve)) {
91
+ output.writeln(output.error(`Invalid CVE ID format: "${checkCve}"`));
92
+ output.writeln(output.dim('Expected format: CVE-YYYY-NNNN (e.g. CVE-2024-12345)'));
93
+ return { success: false };
94
+ }
95
+ const cveId = checkCve.toUpperCase();
96
+ const cacheDir = join(ctx.cwd, '.monomind', 'cache', 'cve');
97
+ let cveData = noCache ? null : getCveCache(cveId, cacheDir);
98
+ let source = 'cache';
99
+ if (!cveData) {
100
+ const spinner = output.createSpinner({ text: `Fetching ${cveId} from NVD...`, spinner: 'dots' });
101
+ spinner.start();
102
+ try {
103
+ const nvdUrl = `https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=${cveId}`;
104
+ const nvdRaw = await httpsGet(nvdUrl);
105
+ cveData = { _source: 'nvd', ...JSON.parse(nvdRaw) };
106
+ source = 'NVD';
107
+ spinner.succeed(`Fetched from NVD`);
108
+ }
109
+ catch {
110
+ spinner.setText(`NVD unavailable — trying OSV...`);
111
+ try {
112
+ const osvUrl = `https://api.osv.dev/v1/vulns/${cveId}`;
113
+ const osvRaw = await httpsGet(osvUrl);
114
+ cveData = { _source: 'osv', ...JSON.parse(osvRaw) };
115
+ source = 'OSV';
116
+ spinner.succeed(`Fetched from OSV`);
117
+ }
118
+ catch {
119
+ spinner.fail('Could not fetch CVE data');
120
+ output.writeln(output.error('Could not fetch CVE data — check your network connection'));
121
+ return { success: false };
122
+ }
123
+ }
124
+ const nvdVulns = cveData.vulnerabilities;
125
+ if (!Array.isArray(nvdVulns) || nvdVulns.length > 0) {
126
+ saveCveCache(cveId, cacheDir, cveData);
127
+ }
128
+ }
129
+ const raw = cveData;
130
+ if (jsonOutput) {
131
+ output.writeln(JSON.stringify(raw, null, 2));
132
+ return { success: true };
133
+ }
134
+ if (raw._source === 'nvd') {
135
+ const vulns = raw.vulnerabilities;
136
+ if (!vulns || vulns.length === 0) {
137
+ output.writeln(output.warning(`No data found for ${cveId}`));
138
+ return { success: true };
139
+ }
140
+ const cve = vulns[0].cve;
141
+ const published = (cve.published || '').split('T')[0];
142
+ const lastMod = (cve.lastModified || '').split('T')[0];
143
+ const descriptions = cve.descriptions;
144
+ const desc = descriptions?.find(d => d.lang === 'en')?.value || 'No description available';
145
+ const metrics = cve.metrics;
146
+ const cvssV31 = metrics?.cvssMetricV31;
147
+ const cvssData = cvssV31?.[0]?.cvssData;
148
+ const score = cvssData?.baseScore;
149
+ const severity = cvssData?.baseSeverity || 'N/A';
150
+ const references = cve.references;
151
+ output.writeln();
152
+ output.printBox([
153
+ `CVE ID: ${cveId}`,
154
+ `Source: ${source}`,
155
+ `Published: ${published}`,
156
+ `Last Modified: ${lastMod}`,
157
+ `Severity: ${severityColor(severity, score)}`,
158
+ ``,
159
+ `Description:`,
160
+ ` ${desc}`,
161
+ ``,
162
+ `References:`,
163
+ ...(references || []).slice(0, 3).map(r => ` - ${r.url}`),
164
+ ].join('\n'), 'CVE Details');
165
+ }
166
+ else {
167
+ const osv = raw;
168
+ const osvId = osv.id || cveId;
169
+ const summary = osv.summary || osv.details || 'No description available';
170
+ const affected = osv.affected;
171
+ const references = osv.references;
172
+ output.writeln();
173
+ const affectedLines = [];
174
+ if (affected && affected.length > 0) {
175
+ for (const a of affected.slice(0, 5)) {
176
+ const pkgName = a.package?.name || 'unknown';
177
+ const ecosystem = a.package?.ecosystem || '';
178
+ affectedLines.push(` - ${pkgName}${ecosystem ? ` (${ecosystem})` : ''}`);
179
+ }
180
+ }
181
+ output.printBox([
182
+ `CVE ID: ${osvId}`,
183
+ `Source: OSV (CVSS score: N/A)`,
184
+ `Severity: N/A`,
185
+ ``,
186
+ `Description:`,
187
+ ` ${summary}`,
188
+ ...(affectedLines.length > 0 ? ['', 'Affected packages:', ...affectedLines] : []),
189
+ ``,
190
+ `References:`,
191
+ ...(references || []).slice(0, 3).map(r => ` - ${r.url}`),
192
+ ].join('\n'), 'CVE Details');
193
+ }
194
+ return { success: true };
195
+ }
196
+ // ── --list ─────────────────────────────────────────────────────────────
197
+ if (doList) {
198
+ const spinner = output.createSpinner({ text: 'Running npm audit...', spinner: 'dots' });
199
+ spinner.start();
200
+ let auditOutput = '';
201
+ try {
202
+ const { stdout } = await execFileAsync('npm', ['audit', '--json'], {
203
+ cwd: ctx.cwd,
204
+ timeout: 30000,
205
+ });
206
+ auditOutput = stdout;
207
+ }
208
+ catch (err) {
209
+ const execErr = err;
210
+ auditOutput = execErr.stdout || '';
211
+ if (!auditOutput) {
212
+ spinner.fail('npm audit failed');
213
+ output.writeln(output.warning('npm audit failed: ' + (execErr.message || 'unknown error')));
214
+ output.writeln(output.dim('Make sure package-lock.json exists (run `npm install` first).'));
215
+ return { success: false };
216
+ }
217
+ }
218
+ spinner.succeed('npm audit complete');
219
+ let auditJson;
220
+ try {
221
+ auditJson = JSON.parse(auditOutput);
222
+ }
223
+ catch {
224
+ output.writeln(output.error('Could not parse npm audit output'));
225
+ return { success: false };
226
+ }
227
+ if (jsonOutput) {
228
+ output.writeln(JSON.stringify(auditJson, null, 2));
229
+ return { success: true };
230
+ }
231
+ const vulnerabilities = auditJson.vulnerabilities;
232
+ const metadata = auditJson.metadata;
233
+ const counts = metadata?.vulnerabilities || {};
234
+ const rows = [];
235
+ if (vulnerabilities) {
236
+ for (const [pkgName, vuln] of Object.entries(vulnerabilities)) {
237
+ const sev = vuln.severity || 'unknown';
238
+ if (severityFilter) {
239
+ const normalizedSev = sev === 'moderate' ? 'medium' : sev;
240
+ if (normalizedSev !== severityFilter && sev !== severityFilter)
241
+ continue;
242
+ }
243
+ const viaObj = vuln.via.find(v => typeof v === 'object');
244
+ let advisoryId = '—';
245
+ if (viaObj?.url) {
246
+ const cveMatch = viaObj.url.match(/CVE-\d{4}-\d+/i);
247
+ const ghsaMatch = viaObj.url.match(/GHSA-[a-z0-9-]+/i);
248
+ if (cveMatch)
249
+ advisoryId = cveMatch[0].toUpperCase();
250
+ else if (ghsaMatch)
251
+ advisoryId = ghsaMatch[0].toUpperCase();
252
+ else
253
+ advisoryId = viaObj.url.split('/').pop() || advisoryId;
254
+ }
255
+ const sevColored = sev === 'critical' ? output.error('CRITICAL') :
256
+ sev === 'high' ? output.warning('HIGH') :
257
+ sev === 'moderate' || sev === 'medium' ? output.info('MEDIUM') :
258
+ output.dim(sev.toUpperCase());
259
+ const fixAvail = vuln.fixAvailable === true ? output.success('Yes') :
260
+ vuln.fixAvailable && typeof vuln.fixAvailable === 'object' ?
261
+ output.success(`${vuln.fixAvailable.version}`) :
262
+ output.dim('No');
263
+ rows.push({ id: advisoryId, severity: sevColored, package: pkgName, range: vuln.range || '—', fix: fixAvail });
264
+ }
265
+ }
266
+ output.writeln();
267
+ if (rows.length === 0) {
268
+ output.writeln(output.success('No vulnerabilities found' + (severityFilter ? ` matching severity: ${severityFilter}` : '') + '.'));
269
+ }
270
+ else {
271
+ output.printTable({
272
+ columns: [
273
+ { key: 'id', header: 'CVE / Advisory', width: 22 },
274
+ { key: 'severity', header: 'Severity', width: 12 },
275
+ { key: 'package', header: 'Package', width: 22 },
276
+ { key: 'range', header: 'Affected Range', width: 20 },
277
+ { key: 'fix', header: 'Fix Available', width: 16 },
278
+ ],
279
+ data: rows,
280
+ });
281
+ }
282
+ const critical = counts['critical'] || 0;
283
+ const high = counts['high'] || 0;
284
+ const moderate = counts['moderate'] || 0;
285
+ const low = counts['low'] || 0;
286
+ output.writeln();
287
+ output.writeln(output.bold('Summary: ') +
288
+ output.error(`${critical} critical`) + ' ' +
289
+ output.warning(`${high} high`) + ' ' +
290
+ output.info(`${moderate} medium`) + ' ' +
291
+ output.dim(`${low} low`));
292
+ return { success: critical === 0 && high === 0 };
293
+ }
294
+ // No subcommand — show usage
295
+ output.writeln('Usage:');
296
+ output.printList([
297
+ '--check CVE-XXXX-YYYY Look up a specific CVE via NVD/OSV',
298
+ '--list List project vulnerabilities (npm audit)',
299
+ '--severity <level> Filter --list by: critical, high, medium, low',
300
+ '--json Output raw JSON',
301
+ '--no-cache Skip local cache (forces fresh fetch)',
302
+ ]);
303
+ output.writeln();
304
+ output.writeln(output.dim('Examples:'));
305
+ output.writeln(output.dim(' monomind security cve --check CVE-2021-44228'));
306
+ output.writeln(output.dim(' monomind security cve --list --severity critical'));
307
+ return { success: true };
308
+ },
309
+ };
310
+ //# sourceMappingURL=security-cve.js.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Security misc commands — threats, audit, defend, redteam
3
+ */
4
+ import type { Command } from '../types.js';
5
+ export declare const threatsCommand: Command;
6
+ export declare const auditCommand: Command;
7
+ export declare const defendCommand: Command;
8
+ export declare const redteamCommand: Command;
9
+ //# sourceMappingURL=security-misc.d.ts.map
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Security misc commands — threats, audit, defend, redteam
3
+ */
4
+ import { output } from '../output.js';
5
+ import { realpathSync } from 'fs';
6
+ import { resolve, sep } from 'path';
7
+ // ─── threats subcommand ──────────────────────────────────────────────────────
8
+ export const threatsCommand = {
9
+ name: 'threats',
10
+ description: 'Threat modeling and analysis',
11
+ options: [
12
+ { name: 'model', short: 'm', type: 'string', description: 'Threat model: stride, dread, pasta', default: 'stride' },
13
+ { name: 'scope', short: 's', type: 'string', description: 'Analysis scope', default: '.' },
14
+ { name: 'export', short: 'e', type: 'string', description: 'Export format: json, md, html' },
15
+ ],
16
+ examples: [
17
+ { command: 'monomind security threats --model stride', description: 'Run STRIDE analysis' },
18
+ { command: 'monomind security threats -e md', description: 'Export as markdown' },
19
+ ],
20
+ action: async (ctx) => {
21
+ const model = ctx.flags.model || 'stride';
22
+ output.writeln();
23
+ output.writeln(output.bold(`Threat Model: ${model.toUpperCase()}`));
24
+ output.writeln(output.dim('─'.repeat(50)));
25
+ output.printTable({
26
+ columns: [
27
+ { key: 'category', header: 'Category', width: 20 },
28
+ { key: 'threat', header: 'Threat', width: 30 },
29
+ { key: 'risk', header: 'Risk', width: 10 },
30
+ { key: 'mitigation', header: 'Mitigation', width: 30 },
31
+ ],
32
+ data: [
33
+ { category: 'Spoofing', threat: 'API key theft', risk: output.error('High'), mitigation: 'Use secure key storage' },
34
+ { category: 'Tampering', threat: 'Data manipulation', risk: output.warning('Medium'), mitigation: 'Input validation' },
35
+ { category: 'Repudiation', threat: 'Action denial', risk: output.info('Low'), mitigation: 'Audit logging' },
36
+ { category: 'Info Disclosure', threat: 'Data leakage', risk: output.error('High'), mitigation: 'Encryption at rest' },
37
+ { category: 'DoS', threat: 'Resource exhaustion', risk: output.warning('Medium'), mitigation: 'Rate limiting' },
38
+ { category: 'Elevation', threat: 'Privilege escalation', risk: output.error('High'), mitigation: 'RBAC implementation' },
39
+ ],
40
+ });
41
+ return { success: true };
42
+ },
43
+ };
44
+ // ─── audit subcommand ────────────────────────────────────────────────────────
45
+ export const auditCommand = {
46
+ name: 'audit',
47
+ description: 'Security audit logging and compliance',
48
+ options: [
49
+ { name: 'action', short: 'a', type: 'string', description: 'Action: log, list, export, clear', default: 'list' },
50
+ { name: 'limit', short: 'l', type: 'number', description: 'Number of entries to show', default: '20' },
51
+ { name: 'filter', short: 'f', type: 'string', description: 'Filter by event type' },
52
+ ],
53
+ examples: [
54
+ { command: 'monomind security audit --action list', description: 'List audit logs' },
55
+ { command: 'monomind security audit -a export', description: 'Export audit trail' },
56
+ ],
57
+ action: async (ctx) => {
58
+ output.writeln();
59
+ output.writeln(output.bold('Security Audit Log'));
60
+ output.writeln(output.dim('─'.repeat(60)));
61
+ const { existsSync, readFileSync, readdirSync, statSync } = await import('fs');
62
+ const { join } = await import('path');
63
+ const auditEntries = [];
64
+ const swarmDir = join(process.cwd(), '.swarm');
65
+ if (existsSync(swarmDir)) {
66
+ try {
67
+ const files = readdirSync(swarmDir).filter(f => f.endsWith('.json'));
68
+ for (const file of files.slice(-10)) {
69
+ try {
70
+ const stat = statSync(join(swarmDir, file));
71
+ const ts = stat.mtime.toISOString().replace('T', ' ').substring(0, 19);
72
+ auditEntries.push({
73
+ timestamp: ts,
74
+ event: file.includes('session') ? 'SESSION_UPDATE' :
75
+ file.includes('swarm') ? 'SWARM_ACTIVITY' :
76
+ file.includes('memory') ? 'MEMORY_WRITE' : 'CONFIG_CHANGE',
77
+ user: 'system',
78
+ status: output.success('Success'),
79
+ });
80
+ }
81
+ catch { /* skip */ }
82
+ }
83
+ }
84
+ catch { /* ignore */ }
85
+ }
86
+ const now = new Date().toISOString().replace('T', ' ').substring(0, 19);
87
+ auditEntries.push({ timestamp: now, event: 'AUDIT_RUN', user: 'cli', status: output.success('Success') });
88
+ auditEntries.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
89
+ if (auditEntries.length === 0) {
90
+ output.writeln(output.dim('No audit events found. Initialize a project first: monomind init'));
91
+ }
92
+ else {
93
+ output.printTable({
94
+ columns: [
95
+ { key: 'timestamp', header: 'Timestamp', width: 22 },
96
+ { key: 'event', header: 'Event', width: 20 },
97
+ { key: 'user', header: 'User', width: 15 },
98
+ { key: 'status', header: 'Status', width: 12 },
99
+ ],
100
+ data: auditEntries.slice(0, parseInt(ctx.flags.limit || '20', 10)),
101
+ });
102
+ }
103
+ return { success: true };
104
+ },
105
+ };
106
+ // ─── defend subcommand ───────────────────────────────────────────────────────
107
+ export const defendCommand = {
108
+ name: 'defend',
109
+ description: 'AI manipulation defense - detect prompt injection, jailbreaks, and PII',
110
+ options: [
111
+ { name: 'input', short: 'i', type: 'string', description: 'Input text to scan for threats' },
112
+ { name: 'file', short: 'f', type: 'string', description: 'File to scan for threats' },
113
+ { name: 'quick', short: 'Q', type: 'boolean', description: 'Quick scan (faster, less detailed)' },
114
+ { name: 'learn', short: 'l', type: 'boolean', description: 'Enable learning mode', default: 'true' },
115
+ { name: 'stats', short: 's', type: 'boolean', description: 'Show detection statistics' },
116
+ { name: 'output', short: 'o', type: 'string', description: 'Output format: text, json', default: 'text' },
117
+ ],
118
+ examples: [
119
+ { command: 'monomind security defend -i "ignore previous instructions"', description: 'Scan text for threats' },
120
+ { command: 'monomind security defend -f ./prompts.txt', description: 'Scan file for threats' },
121
+ { command: 'monomind security defend --stats', description: 'Show detection statistics' },
122
+ ],
123
+ action: async (ctx) => {
124
+ const inputText = ctx.flags.input;
125
+ const filePath = ctx.flags.file;
126
+ const quickMode = ctx.flags.quick;
127
+ const showStats = ctx.flags.stats;
128
+ const outputFormat = ctx.flags.output || 'text';
129
+ const enableLearning = ctx.flags.learn !== false;
130
+ output.writeln();
131
+ output.writeln(output.bold('🛡️ MonoFence - AI Manipulation Defense System'));
132
+ output.writeln(output.dim('─'.repeat(55)));
133
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
134
+ let createMonoDefence;
135
+ try {
136
+ // @ts-expect-error — optional peer dep resolved at runtime
137
+ const aidefence = await import('monofence-ai');
138
+ createMonoDefence = aidefence.createMonoDefence;
139
+ }
140
+ catch {
141
+ output.printError('MonoFence package not installed. Run: npm install monofence-ai');
142
+ return { success: false, message: 'MonoFence not available' };
143
+ }
144
+ const defender = createMonoDefence({ enableLearning });
145
+ if (showStats) {
146
+ const stats = await defender.getStats();
147
+ output.writeln();
148
+ output.printBox([
149
+ `Detection Count: ${stats.detectionCount}`,
150
+ `Avg Detection Time: ${stats.avgDetectionTimeMs.toFixed(3)}ms`,
151
+ `Learned Patterns: ${stats.learnedPatterns}`,
152
+ `Mitigation Strategies: ${stats.mitigationStrategies}`,
153
+ `Avg Mitigation Effectiveness: ${(stats.avgMitigationEffectiveness * 100).toFixed(1)}%`,
154
+ ].join('\n'), 'Detection Statistics');
155
+ return { success: true };
156
+ }
157
+ let textToScan = inputText;
158
+ if (filePath) {
159
+ try {
160
+ const resolvedFile = realpathSync(resolve(filePath));
161
+ const cwd = realpathSync(process.cwd());
162
+ if (!resolvedFile.startsWith(cwd + sep) && resolvedFile !== cwd) {
163
+ output.printError('--file must be within the current working directory');
164
+ return { success: false };
165
+ }
166
+ }
167
+ catch {
168
+ output.printError(`File not found: ${filePath}`);
169
+ return { success: false, message: 'File not found' };
170
+ }
171
+ try {
172
+ const fs = await import('fs/promises');
173
+ const MAX_DEFEND_FILE_BYTES = 10 * 1024 * 1024;
174
+ const { size } = await fs.stat(filePath);
175
+ if (size > MAX_DEFEND_FILE_BYTES) {
176
+ output.printError(`File too large (${(size / 1024 / 1024).toFixed(1)} MB). Maximum is 10 MB.`);
177
+ return { success: false, message: 'File too large' };
178
+ }
179
+ textToScan = await fs.readFile(filePath, 'utf-8');
180
+ output.writeln(output.dim(`Reading file: ${filePath}`));
181
+ }
182
+ catch {
183
+ output.printError(`Failed to read file: ${filePath}`);
184
+ return { success: false, message: 'File not found' };
185
+ }
186
+ }
187
+ if (!textToScan) {
188
+ output.writeln('Usage: monomind security defend -i "<text>" or -f <file>');
189
+ output.writeln();
190
+ output.writeln('Options:');
191
+ output.printList([
192
+ '-i, --input Text to scan for AI manipulation attempts',
193
+ '-f, --file File path to scan',
194
+ '-q, --quick Quick scan mode (faster)',
195
+ '-s, --stats Show detection statistics',
196
+ '--learn Enable pattern learning (default: true)',
197
+ ]);
198
+ return { success: true };
199
+ }
200
+ const spinner = output.createSpinner({ text: 'Scanning for threats...', spinner: 'dots' });
201
+ spinner.start();
202
+ const startTime = performance.now();
203
+ const qr = quickMode ? defender.quickScan(textToScan) : null;
204
+ const result = quickMode
205
+ ? { ...qr, threats: [], piiFound: false, detectionTimeMs: 0, inputHash: '', safe: !qr.threat }
206
+ : await defender.detect(textToScan);
207
+ const scanTime = performance.now() - startTime;
208
+ spinner.stop();
209
+ if (outputFormat === 'json') {
210
+ output.writeln(JSON.stringify({
211
+ safe: result.safe,
212
+ threats: result.threats || [],
213
+ piiFound: result.piiFound,
214
+ detectionTimeMs: scanTime,
215
+ }, null, 2));
216
+ return { success: true };
217
+ }
218
+ output.writeln();
219
+ if (result.safe && !result.piiFound) {
220
+ output.writeln(output.success('✅ No threats detected'));
221
+ }
222
+ else {
223
+ if (!result.safe && result.threats) {
224
+ output.writeln(output.error(`⚠️ ${result.threats.length} threat(s) detected:`));
225
+ output.writeln();
226
+ for (const threat of result.threats) {
227
+ const sc = {
228
+ critical: output.error,
229
+ high: output.warning,
230
+ medium: output.info,
231
+ low: output.dim,
232
+ }[threat.severity] || output.dim;
233
+ output.writeln(` ${sc(`[${threat.severity.toUpperCase()}]`)} ${threat.type}`);
234
+ output.writeln(` ${output.dim(threat.description)}`);
235
+ output.writeln(` Confidence: ${(threat.confidence * 100).toFixed(1)}%`);
236
+ output.writeln();
237
+ }
238
+ const criticalThreats = result.threats.filter((t) => t.severity === 'critical');
239
+ if (criticalThreats.length > 0 && enableLearning) {
240
+ output.writeln(output.bold('Recommended Mitigations:'));
241
+ for (const threat of criticalThreats) {
242
+ const mitigation = await defender.getBestMitigation(threat.type);
243
+ if (mitigation) {
244
+ output.writeln(` ${threat.type}: ${output.bold(mitigation.strategy)} (${(mitigation.effectiveness * 100).toFixed(0)}% effective)`);
245
+ }
246
+ }
247
+ output.writeln();
248
+ }
249
+ }
250
+ if (result.piiFound) {
251
+ output.writeln(output.warning('⚠️ PII detected (emails, SSNs, API keys, etc.)'));
252
+ output.writeln();
253
+ }
254
+ }
255
+ output.writeln(output.dim(`Detection time: ${scanTime.toFixed(3)}ms`));
256
+ return { success: result.safe };
257
+ },
258
+ };
259
+ // ─── redteam subcommand ──────────────────────────────────────────────────────
260
+ // Source: https://github.com/Azure/PyRIT
261
+ export const redteamCommand = {
262
+ name: 'redteam',
263
+ description: 'Adversarial red-team testing — prompt injection, jailbreak, and manipulation scenarios (PyRIT-style)',
264
+ options: [
265
+ { name: 'target', short: 't', type: 'string', description: 'Target agent ID or endpoint to test' },
266
+ { name: 'scenarios', short: 's', type: 'string', description: 'Comma-separated attack categories: injection,jailbreak,adversarial,pii,all', default: 'all' },
267
+ { name: 'iterations', short: 'n', type: 'number', description: 'Number of attack iterations per scenario', default: '5' },
268
+ { name: 'dry-run', type: 'boolean', description: 'Print attack prompts without executing them' },
269
+ { name: 'output', short: 'o', type: 'string', description: 'Output format: text, json', default: 'text' },
270
+ { name: 'threshold', type: 'number', description: 'Failure threshold 0-1 — report when success rate exceeds this', default: '0.1' },
271
+ ],
272
+ examples: [
273
+ { command: 'monomind security redteam --target my-agent', description: 'Run all red-team scenarios against an agent' },
274
+ { command: 'monomind security redteam --target my-agent --scenarios injection,jailbreak', description: 'Test specific attack categories' },
275
+ { command: 'monomind security redteam --target my-agent --dry-run', description: 'Preview attack prompts without executing' },
276
+ { command: 'monomind security redteam --target my-agent --output json', description: 'JSON output for CI integration' },
277
+ ],
278
+ action: async (ctx) => {
279
+ const target = ctx.flags.target;
280
+ output.writeln();
281
+ output.writeln(output.warning('⚠ Red-team simulation not yet implemented.'));
282
+ output.writeln(output.dim('This command will contact the target agent and evaluate its real responses once implemented.'));
283
+ if (target)
284
+ output.writeln(output.dim(`Target specified: ${target}`));
285
+ output.writeln();
286
+ output.writeln('To test prompt injection resistance manually:');
287
+ output.writeln(output.dim(' 1. Run the target agent'));
288
+ output.writeln(output.dim(' 2. Send adversarial prompts and evaluate responses'));
289
+ output.writeln(output.dim(' 3. Check agent logs for unexpected tool calls'));
290
+ return { success: false, exitCode: 1 };
291
+ },
292
+ };
293
+ //# sourceMappingURL=security-misc.js.map
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Security scan commands — code/dep/container scanning and secret detection
3
+ */
4
+ import type { Command } from '../types.js';
5
+ export declare const SECRET_PATTERNS: Array<{
6
+ pattern: RegExp;
7
+ type: string;
8
+ }>;
9
+ export type SecretFinding = {
10
+ severity: string;
11
+ type: string;
12
+ location: string;
13
+ description: string;
14
+ };
15
+ export declare function findSecretsInDir(dir: string, depthLimit: number, baseDir: string, findings: SecretFinding[]): void;
16
+ export declare const scanCommand: Command;
17
+ export declare const secretsCommand: Command;
18
+ //# sourceMappingURL=security-scan.d.ts.map