bashbros 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +734 -271
- package/dist/adapters-JAZGGNVP.js +9 -0
- package/dist/chunk-25TREQ6V.js +465 -0
- package/dist/chunk-25TREQ6V.js.map +1 -0
- package/dist/{chunk-A535VV7N.js → chunk-2CI2MRKI.js} +23 -6
- package/dist/chunk-2CI2MRKI.js.map +1 -0
- package/dist/chunk-4XZ64P4V.js +47 -0
- package/dist/chunk-4XZ64P4V.js.map +1 -0
- package/dist/chunk-5BBPRDWL.js +186 -0
- package/dist/chunk-5BBPRDWL.js.map +1 -0
- package/dist/{chunk-2RPTM6EQ.js → chunk-6QVMBCSX.js} +719 -902
- package/dist/chunk-6QVMBCSX.js.map +1 -0
- package/dist/{chunk-JYWQT2B4.js → chunk-6SLR5WPD.js} +657 -14
- package/dist/chunk-6SLR5WPD.js.map +1 -0
- package/dist/{chunk-EYO44OMN.js → chunk-AZVT6AZY.js} +78 -17
- package/dist/chunk-AZVT6AZY.js.map +1 -0
- package/dist/{chunk-WPJJZLT6.js → chunk-C4GZNBFF.js} +3 -2
- package/dist/chunk-C4GZNBFF.js.map +1 -0
- package/dist/chunk-IUUBCPMV.js +166 -0
- package/dist/chunk-IUUBCPMV.js.map +1 -0
- package/dist/chunk-J6ONXY6N.js +146 -0
- package/dist/chunk-J6ONXY6N.js.map +1 -0
- package/dist/{chunk-DLP2O6PN.js → chunk-JOIAG54E.js} +83 -88
- package/dist/chunk-JOIAG54E.js.map +1 -0
- package/dist/chunk-LJE4EPIU.js +56 -0
- package/dist/chunk-LJE4EPIU.js.map +1 -0
- package/dist/{chunk-QWZGB4V3.js → chunk-PAZIDRXK.js} +42 -181
- package/dist/chunk-PAZIDRXK.js.map +1 -0
- package/dist/chunk-PLSHJHHR.js +293 -0
- package/dist/chunk-PLSHJHHR.js.map +1 -0
- package/dist/chunk-R5I5DEXE.js +228 -0
- package/dist/chunk-R5I5DEXE.js.map +1 -0
- package/dist/chunk-SDN6TAGD.js +157 -0
- package/dist/chunk-SDN6TAGD.js.map +1 -0
- package/dist/chunk-T5ONCUHZ.js +198 -0
- package/dist/chunk-T5ONCUHZ.js.map +1 -0
- package/dist/cli.js +1204 -188
- package/dist/cli.js.map +1 -1
- package/dist/{config-43SK6SFI.js → config-IXBXMIUA.js} +2 -2
- package/dist/copilot-cli-5WJWK5YT.js +9 -0
- package/dist/{db-SWJUUSFX.js → db-GJALN3R7.js} +2 -2
- package/dist/db-checks-2YOVECD4.js +133 -0
- package/dist/db-checks-2YOVECD4.js.map +1 -0
- package/dist/{display-HFIFXOOL.js → display-UDIACHTP.js} +3 -3
- package/dist/{engine-EGPAS2EX.js → engine-4WNPXVMS.js} +3 -2
- package/dist/gemini-cli-3563EELZ.js +9 -0
- package/dist/gemini-cli-3563EELZ.js.map +1 -0
- package/dist/index.d.ts +205 -101
- package/dist/index.js +132 -402
- package/dist/index.js.map +1 -1
- package/dist/{ollama-HY35OHW4.js → ollama-TNMD5WHW.js} +2 -2
- package/dist/ollama-TNMD5WHW.js.map +1 -0
- package/dist/opencode-DRCY275R.js +9 -0
- package/dist/opencode-DRCY275R.js.map +1 -0
- package/dist/profiles-7CLN6TAT.js +9 -0
- package/dist/profiles-7CLN6TAT.js.map +1 -0
- package/dist/server-3CMTP4W4.js +13 -0
- package/dist/server-3CMTP4W4.js.map +1 -0
- package/dist/setup-U4R5QJMV.js +124 -0
- package/dist/setup-U4R5QJMV.js.map +1 -0
- package/dist/static/index.html +4862 -2007
- package/dist/store-WJ5Y7MOE.js +9 -0
- package/dist/store-WJ5Y7MOE.js.map +1 -0
- package/dist/{writer-4ZEAKUFD.js → writer-OMHUMJR5.js} +3 -3
- package/dist/writer-OMHUMJR5.js.map +1 -0
- package/package.json +78 -68
- package/dist/chunk-2RPTM6EQ.js.map +0 -1
- package/dist/chunk-A535VV7N.js.map +0 -1
- package/dist/chunk-DLP2O6PN.js.map +0 -1
- package/dist/chunk-EYO44OMN.js.map +0 -1
- package/dist/chunk-JYWQT2B4.js.map +0 -1
- package/dist/chunk-QWZGB4V3.js.map +0 -1
- package/dist/chunk-WPJJZLT6.js.map +0 -1
- /package/dist/{config-43SK6SFI.js.map → adapters-JAZGGNVP.js.map} +0 -0
- /package/dist/{db-SWJUUSFX.js.map → config-IXBXMIUA.js.map} +0 -0
- /package/dist/{display-HFIFXOOL.js.map → copilot-cli-5WJWK5YT.js.map} +0 -0
- /package/dist/{engine-EGPAS2EX.js.map → db-GJALN3R7.js.map} +0 -0
- /package/dist/{ollama-HY35OHW4.js.map → display-UDIACHTP.js.map} +0 -0
- /package/dist/{writer-4ZEAKUFD.js.map → engine-4WNPXVMS.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,38 +1,54 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
startMCPServer
|
|
4
|
+
} from "./chunk-PLSHJHHR.js";
|
|
5
|
+
import {
|
|
6
|
+
AnomalyDetector,
|
|
3
7
|
BackgroundWorker,
|
|
4
8
|
BashBro,
|
|
5
9
|
BashBros,
|
|
6
10
|
BashgymIntegration,
|
|
7
|
-
ClaudeCodeHooks,
|
|
8
|
-
CommandSuggester,
|
|
9
11
|
CostEstimator,
|
|
10
12
|
LoopDetector,
|
|
11
|
-
|
|
13
|
+
OutputScanner,
|
|
12
14
|
ReportGenerator,
|
|
13
15
|
SystemProfiler,
|
|
14
16
|
TaskRouter,
|
|
15
17
|
UndoStack,
|
|
16
|
-
gateCommand,
|
|
17
18
|
getBashgymIntegration,
|
|
18
19
|
resetBashgymIntegration
|
|
19
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-6QVMBCSX.js";
|
|
21
|
+
import {
|
|
22
|
+
CommandSuggester
|
|
23
|
+
} from "./chunk-5BBPRDWL.js";
|
|
24
|
+
import {
|
|
25
|
+
ClaudeCodeHooks,
|
|
26
|
+
gateCommand
|
|
27
|
+
} from "./chunk-25TREQ6V.js";
|
|
28
|
+
import {
|
|
29
|
+
MoltbotHooks,
|
|
30
|
+
getMoltbotHooks
|
|
31
|
+
} from "./chunk-J37RHCFJ.js";
|
|
20
32
|
import {
|
|
21
33
|
AuditLogger
|
|
22
34
|
} from "./chunk-SG752FZC.js";
|
|
23
35
|
import {
|
|
24
36
|
OllamaClient
|
|
25
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-JOIAG54E.js";
|
|
38
|
+
import "./chunk-4XZ64P4V.js";
|
|
39
|
+
import "./chunk-LJE4EPIU.js";
|
|
26
40
|
import {
|
|
27
41
|
loadConfig
|
|
28
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-2CI2MRKI.js";
|
|
29
43
|
import {
|
|
30
44
|
CommandFilter,
|
|
31
45
|
PathSandbox,
|
|
32
46
|
PolicyEngine,
|
|
33
|
-
RateLimiter
|
|
47
|
+
RateLimiter
|
|
48
|
+
} from "./chunk-PAZIDRXK.js";
|
|
49
|
+
import {
|
|
34
50
|
SecretsGuard
|
|
35
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-R5I5DEXE.js";
|
|
36
52
|
import {
|
|
37
53
|
allowForSession,
|
|
38
54
|
clearSessionAllowlist,
|
|
@@ -42,438 +58,151 @@ import {
|
|
|
42
58
|
import {
|
|
43
59
|
RiskScorer
|
|
44
60
|
} from "./chunk-DEAF6PYM.js";
|
|
45
|
-
import
|
|
46
|
-
MoltbotHooks,
|
|
47
|
-
getMoltbotHooks
|
|
48
|
-
} from "./chunk-J37RHCFJ.js";
|
|
61
|
+
import "./chunk-6SLR5WPD.js";
|
|
49
62
|
import "./chunk-7OCVIDC7.js";
|
|
50
63
|
|
|
51
|
-
// src/
|
|
52
|
-
var
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
typicalCommandsPerMinute: 30,
|
|
56
|
-
knownPaths: [],
|
|
57
|
-
suspiciousPatterns: [],
|
|
58
|
-
enabled: true
|
|
59
|
-
};
|
|
60
|
-
var DEFAULT_SUSPICIOUS_PATTERNS = [
|
|
61
|
-
/\bpasswd\b/,
|
|
62
|
-
/\bshadow\b/,
|
|
63
|
-
/\/root\//,
|
|
64
|
-
/\.ssh\//,
|
|
65
|
-
/\.gnupg\//,
|
|
66
|
-
/\.aws\//,
|
|
67
|
-
/\.kube\//,
|
|
68
|
-
/wallet/i,
|
|
69
|
-
/crypto/i,
|
|
70
|
-
/bitcoin/i,
|
|
71
|
-
/ethereum/i,
|
|
72
|
-
/private.*key/i
|
|
73
|
-
];
|
|
74
|
-
var AnomalyDetector = class {
|
|
75
|
-
config;
|
|
64
|
+
// src/observability/metrics.ts
|
|
65
|
+
var MetricsCollector = class {
|
|
66
|
+
sessionId;
|
|
67
|
+
startTime;
|
|
76
68
|
commands = [];
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
constructor(config = {}) {
|
|
83
|
-
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
69
|
+
filesModified = /* @__PURE__ */ new Set();
|
|
70
|
+
pathsAccessed = /* @__PURE__ */ new Set();
|
|
71
|
+
constructor() {
|
|
72
|
+
this.sessionId = this.generateSessionId();
|
|
73
|
+
this.startTime = /* @__PURE__ */ new Date();
|
|
84
74
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const now = Date.now();
|
|
92
|
-
this.commands.push({ command, timestamp: now, path: cwd });
|
|
93
|
-
if (this.commands.length > 1e3) {
|
|
94
|
-
this.commands = this.commands.slice(-500);
|
|
95
|
-
}
|
|
96
|
-
if (this.learningMode) {
|
|
97
|
-
this.learn(command, cwd);
|
|
98
|
-
if (this.learningCount >= this.LEARNING_THRESHOLD) {
|
|
99
|
-
this.learningMode = false;
|
|
100
|
-
}
|
|
101
|
-
return anomalies;
|
|
102
|
-
}
|
|
103
|
-
const timingAnomaly = this.checkTiming(now);
|
|
104
|
-
if (timingAnomaly) anomalies.push(timingAnomaly);
|
|
105
|
-
const freqAnomaly = this.checkFrequency(now);
|
|
106
|
-
if (freqAnomaly) anomalies.push(freqAnomaly);
|
|
107
|
-
if (cwd) {
|
|
108
|
-
const pathAnomaly = this.checkPath(cwd);
|
|
109
|
-
if (pathAnomaly) anomalies.push(pathAnomaly);
|
|
110
|
-
}
|
|
111
|
-
const patternAnomalies = this.checkPatterns(command);
|
|
112
|
-
anomalies.push(...patternAnomalies);
|
|
113
|
-
const behaviorAnomaly = this.checkBehavior(command);
|
|
114
|
-
if (behaviorAnomaly) anomalies.push(behaviorAnomaly);
|
|
115
|
-
return anomalies;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Learn from command (build baseline)
|
|
119
|
-
*/
|
|
120
|
-
learn(command, cwd) {
|
|
121
|
-
this.learningCount++;
|
|
122
|
-
const baseCmd = command.split(/\s+/)[0];
|
|
123
|
-
this.baselineCommands.add(baseCmd);
|
|
124
|
-
if (cwd) {
|
|
125
|
-
this.baselinePaths.add(cwd);
|
|
126
|
-
const parts = cwd.split(/[/\\]/);
|
|
127
|
-
for (let i = 1; i <= parts.length; i++) {
|
|
128
|
-
this.baselinePaths.add(parts.slice(0, i).join("/"));
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Check for timing anomalies
|
|
134
|
-
*/
|
|
135
|
-
checkTiming(now) {
|
|
136
|
-
const hour = new Date(now).getHours();
|
|
137
|
-
const [start, end] = this.config.workingHours;
|
|
138
|
-
if (hour < start || hour >= end) {
|
|
139
|
-
return {
|
|
140
|
-
type: "timing",
|
|
141
|
-
severity: "info",
|
|
142
|
-
message: `Activity outside normal hours (${hour}:00)`,
|
|
143
|
-
details: { hour, workingHours: this.config.workingHours }
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
return null;
|
|
75
|
+
generateSessionId() {
|
|
76
|
+
const now = /* @__PURE__ */ new Date();
|
|
77
|
+
const date = now.toISOString().slice(0, 10).replace(/-/g, "");
|
|
78
|
+
const time = now.toTimeString().slice(0, 8).replace(/:/g, "");
|
|
79
|
+
const rand = Math.random().toString(36).slice(2, 6);
|
|
80
|
+
return `${date}-${time}-${rand}`;
|
|
147
81
|
}
|
|
148
82
|
/**
|
|
149
|
-
*
|
|
83
|
+
* Record a command execution
|
|
150
84
|
*/
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
return {
|
|
157
|
-
type: "frequency",
|
|
158
|
-
severity: "warning",
|
|
159
|
-
message: `High command rate: ${rate}/min (typical: ${this.config.typicalCommandsPerMinute})`,
|
|
160
|
-
details: { rate, typical: this.config.typicalCommandsPerMinute }
|
|
161
|
-
};
|
|
85
|
+
record(metric) {
|
|
86
|
+
this.commands.push(metric);
|
|
87
|
+
const paths = this.extractPaths(metric.command);
|
|
88
|
+
for (const path of paths) {
|
|
89
|
+
this.pathsAccessed.add(path);
|
|
162
90
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return {
|
|
167
|
-
type: "frequency",
|
|
168
|
-
severity: "alert",
|
|
169
|
-
message: `Burst detected: ${burstCommands.length} commands in 5 seconds`,
|
|
170
|
-
details: { count: burstCommands.length, window: "5s" }
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
return null;
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Check for unusual path access
|
|
177
|
-
*/
|
|
178
|
-
checkPath(path) {
|
|
179
|
-
if (this.config.knownPaths.length > 0) {
|
|
180
|
-
const isKnown = this.config.knownPaths.some(
|
|
181
|
-
(p) => path.startsWith(p) || path.includes(p)
|
|
182
|
-
);
|
|
183
|
-
if (!isKnown) {
|
|
184
|
-
return {
|
|
185
|
-
type: "path",
|
|
186
|
-
severity: "warning",
|
|
187
|
-
message: `Access to unexpected path: ${path}`,
|
|
188
|
-
details: { path, knownPaths: this.config.knownPaths }
|
|
189
|
-
};
|
|
91
|
+
if (this.isWriteCommand(metric.command)) {
|
|
92
|
+
for (const path of paths) {
|
|
93
|
+
this.filesModified.add(path);
|
|
190
94
|
}
|
|
191
95
|
}
|
|
192
|
-
if (!this.learningMode && this.baselinePaths.size > 0) {
|
|
193
|
-
const isBaseline = this.baselinePaths.has(path) || [...this.baselinePaths].some((p) => path.startsWith(p));
|
|
194
|
-
if (!isBaseline) {
|
|
195
|
-
return {
|
|
196
|
-
type: "path",
|
|
197
|
-
severity: "info",
|
|
198
|
-
message: `New path accessed: ${path}`,
|
|
199
|
-
details: { path, isNew: true }
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
return null;
|
|
204
96
|
}
|
|
205
97
|
/**
|
|
206
|
-
*
|
|
98
|
+
* Get current session metrics
|
|
207
99
|
*/
|
|
208
|
-
|
|
209
|
-
const
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
message: `Suspicious pattern detected: ${pattern.source}`,
|
|
217
|
-
details: { command: command.slice(0, 100), pattern: pattern.source }
|
|
218
|
-
});
|
|
219
|
-
}
|
|
100
|
+
getMetrics() {
|
|
101
|
+
const now = /* @__PURE__ */ new Date();
|
|
102
|
+
const duration = now.getTime() - this.startTime.getTime();
|
|
103
|
+
const riskDist = { safe: 0, caution: 0, dangerous: 0, critical: 0 };
|
|
104
|
+
let totalRisk = 0;
|
|
105
|
+
for (const cmd of this.commands) {
|
|
106
|
+
riskDist[cmd.riskScore.level]++;
|
|
107
|
+
totalRisk += cmd.riskScore.score;
|
|
220
108
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
"curl",
|
|
232
|
-
"wget",
|
|
233
|
-
"nc",
|
|
234
|
-
"netcat",
|
|
235
|
-
"ssh",
|
|
236
|
-
"scp",
|
|
237
|
-
"rsync",
|
|
238
|
-
"sudo",
|
|
239
|
-
"su",
|
|
240
|
-
"chmod",
|
|
241
|
-
"chown",
|
|
242
|
-
"mount",
|
|
243
|
-
"umount"
|
|
244
|
-
]);
|
|
245
|
-
if (sensitiveCommands.has(baseCmd)) {
|
|
246
|
-
return {
|
|
247
|
-
type: "behavior",
|
|
248
|
-
severity: "warning",
|
|
249
|
-
message: `New sensitive command type: ${baseCmd}`,
|
|
250
|
-
details: { command: baseCmd, isNew: true }
|
|
251
|
-
};
|
|
252
|
-
}
|
|
109
|
+
const cmdFreq = /* @__PURE__ */ new Map();
|
|
110
|
+
for (const cmd of this.commands) {
|
|
111
|
+
const base = cmd.command.split(/\s+/)[0];
|
|
112
|
+
cmdFreq.set(base, (cmdFreq.get(base) || 0) + 1);
|
|
113
|
+
}
|
|
114
|
+
const topCommands = [...cmdFreq.entries()].sort((a, b) => b[1] - a[1]).slice(0, 10);
|
|
115
|
+
const violationsByType = {};
|
|
116
|
+
for (const cmd of this.commands) {
|
|
117
|
+
for (const v of cmd.violations) {
|
|
118
|
+
violationsByType[v.type] = (violationsByType[v.type] || 0) + 1;
|
|
253
119
|
}
|
|
254
120
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Get anomaly stats
|
|
259
|
-
*/
|
|
260
|
-
getStats() {
|
|
261
|
-
const now = Date.now();
|
|
262
|
-
const oneMinuteAgo = now - 6e4;
|
|
263
|
-
const recentRate = this.commands.filter((c) => c.timestamp > oneMinuteAgo).length;
|
|
121
|
+
const totalExecTime = this.commands.reduce((sum, c) => sum + c.duration, 0);
|
|
122
|
+
const avgExecTime = this.commands.length > 0 ? totalExecTime / this.commands.length : 0;
|
|
264
123
|
return {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
124
|
+
sessionId: this.sessionId,
|
|
125
|
+
startTime: this.startTime,
|
|
126
|
+
duration,
|
|
127
|
+
commandCount: this.commands.length,
|
|
128
|
+
blockedCount: this.commands.filter((c) => !c.allowed).length,
|
|
129
|
+
uniqueCommands: cmdFreq.size,
|
|
130
|
+
topCommands,
|
|
131
|
+
riskDistribution: riskDist,
|
|
132
|
+
avgRiskScore: this.commands.length > 0 ? totalRisk / this.commands.length : 0,
|
|
133
|
+
avgExecutionTime: avgExecTime,
|
|
134
|
+
totalExecutionTime: totalExecTime,
|
|
135
|
+
filesModified: [...this.filesModified],
|
|
136
|
+
pathsAccessed: [...this.pathsAccessed],
|
|
137
|
+
violationsByType
|
|
270
138
|
};
|
|
271
139
|
}
|
|
272
140
|
/**
|
|
273
|
-
*
|
|
274
|
-
*/
|
|
275
|
-
endLearning() {
|
|
276
|
-
this.learningMode = false;
|
|
277
|
-
}
|
|
278
|
-
/**
|
|
279
|
-
* Reset and restart learning
|
|
141
|
+
* Extract paths from a command
|
|
280
142
|
*/
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
// src/policy/output-scanner.ts
|
|
291
|
-
var SECRET_PATTERNS = [
|
|
292
|
-
// API Keys
|
|
293
|
-
{ pattern: /sk-[A-Za-z0-9]{20,}/, name: "OpenAI API Key" },
|
|
294
|
-
{ pattern: /sk-ant-[A-Za-z0-9\-]{20,}/, name: "Anthropic API Key" },
|
|
295
|
-
{ pattern: /ghp_[A-Za-z0-9]{36}/, name: "GitHub Token" },
|
|
296
|
-
{ pattern: /gho_[A-Za-z0-9]{36}/, name: "GitHub OAuth Token" },
|
|
297
|
-
{ pattern: /github_pat_[A-Za-z0-9_]{22,}/, name: "GitHub PAT" },
|
|
298
|
-
{ pattern: /glpat-[A-Za-z0-9\-]{20,}/, name: "GitLab Token" },
|
|
299
|
-
{ pattern: /xox[baprs]-[A-Za-z0-9\-]{10,}/, name: "Slack Token" },
|
|
300
|
-
{ pattern: /sk_live_[A-Za-z0-9]{24,}/, name: "Stripe Secret Key" },
|
|
301
|
-
{ pattern: /sq0atp-[A-Za-z0-9\-_]{22,}/, name: "Square Token" },
|
|
302
|
-
{ pattern: /AKIA[A-Z0-9]{16}/, name: "AWS Access Key" },
|
|
303
|
-
{ pattern: /amzn\.mws\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/, name: "Amazon MWS Key" },
|
|
304
|
-
// OAuth/JWT
|
|
305
|
-
{ pattern: /Bearer\s+[A-Za-z0-9\-._~+/]+=*/, name: "Bearer Token" },
|
|
306
|
-
{ pattern: /eyJ[A-Za-z0-9\-_]+\.eyJ[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+/, name: "JWT Token" },
|
|
307
|
-
// Credentials in output
|
|
308
|
-
{ pattern: /password\s*[=:]\s*['"]?[^\s'"]{4,}['"]?/i, name: "Password" },
|
|
309
|
-
{ pattern: /passwd\s*[=:]\s*['"]?[^\s'"]{4,}['"]?/i, name: "Password" },
|
|
310
|
-
{ pattern: /api[_-]?key\s*[=:]\s*['"]?[^\s'"]{8,}['"]?/i, name: "API Key" },
|
|
311
|
-
{ pattern: /secret\s*[=:]\s*['"]?[^\s'"]{8,}['"]?/i, name: "Secret" },
|
|
312
|
-
{ pattern: /token\s*[=:]\s*['"]?[^\s'"]{8,}['"]?/i, name: "Token" },
|
|
313
|
-
// Private keys
|
|
314
|
-
{ pattern: /-----BEGIN\s+(RSA\s+)?PRIVATE\s+KEY-----/, name: "Private Key" },
|
|
315
|
-
{ pattern: /-----BEGIN\s+EC\s+PRIVATE\s+KEY-----/, name: "EC Private Key" },
|
|
316
|
-
{ pattern: /-----BEGIN\s+OPENSSH\s+PRIVATE\s+KEY-----/, name: "SSH Private Key" },
|
|
317
|
-
{ pattern: /-----BEGIN\s+PGP\s+PRIVATE\s+KEY\s+BLOCK-----/, name: "PGP Private Key" },
|
|
318
|
-
// Database URLs
|
|
319
|
-
{ pattern: /mongodb(\+srv)?:\/\/[^:]+:[^@]+@/, name: "MongoDB Connection String" },
|
|
320
|
-
{ pattern: /postgres(ql)?:\/\/[^:]+:[^@]+@/, name: "PostgreSQL Connection String" },
|
|
321
|
-
{ pattern: /mysql:\/\/[^:]+:[^@]+@/, name: "MySQL Connection String" },
|
|
322
|
-
{ pattern: /redis:\/\/[^:]+:[^@]+@/, name: "Redis Connection String" },
|
|
323
|
-
// SSH
|
|
324
|
-
{ pattern: /ssh-rsa\s+[A-Za-z0-9+/]+[=]{0,2}/, name: "SSH Public Key" },
|
|
325
|
-
{ pattern: /ssh-ed25519\s+[A-Za-z0-9+/]+/, name: "SSH ED25519 Key" }
|
|
326
|
-
];
|
|
327
|
-
var ERROR_PATTERNS = [
|
|
328
|
-
{ pattern: /EACCES|EPERM|permission denied/i, name: "Permission Error" },
|
|
329
|
-
{ pattern: /ENOENT|no such file|not found/i, name: "File Not Found" },
|
|
330
|
-
{ pattern: /ECONNREFUSED|connection refused/i, name: "Connection Refused" },
|
|
331
|
-
{ pattern: /ETIMEDOUT|timed out/i, name: "Timeout Error" },
|
|
332
|
-
{ pattern: /segmentation fault|core dumped/i, name: "Crash" },
|
|
333
|
-
{ pattern: /out of memory|OOM|cannot allocate/i, name: "Memory Error" },
|
|
334
|
-
{ pattern: /stack trace|traceback|at\s+\S+:\d+:\d+/i, name: "Stack Trace" },
|
|
335
|
-
{ pattern: /error:|fatal:|failed:/i, name: "Error Message" }
|
|
336
|
-
];
|
|
337
|
-
var OutputScanner = class {
|
|
338
|
-
secretPatterns;
|
|
339
|
-
redactPatterns;
|
|
340
|
-
policy;
|
|
341
|
-
constructor(policy) {
|
|
342
|
-
this.policy = policy;
|
|
343
|
-
this.secretPatterns = SECRET_PATTERNS.map((p) => p.pattern);
|
|
344
|
-
this.redactPatterns = (policy.redactPatterns || []).map((p) => {
|
|
345
|
-
try {
|
|
346
|
-
return new RegExp(p, "gi");
|
|
347
|
-
} catch {
|
|
348
|
-
return null;
|
|
143
|
+
extractPaths(command) {
|
|
144
|
+
const paths = [];
|
|
145
|
+
const tokens = command.split(/\s+/);
|
|
146
|
+
for (const token of tokens) {
|
|
147
|
+
if (token.startsWith("-")) continue;
|
|
148
|
+
if (token.startsWith("/") || token.startsWith("./") || token.startsWith("../") || token.startsWith("~/") || token.includes(".")) {
|
|
149
|
+
paths.push(token);
|
|
349
150
|
}
|
|
350
|
-
}
|
|
151
|
+
}
|
|
152
|
+
return paths;
|
|
351
153
|
}
|
|
352
154
|
/**
|
|
353
|
-
*
|
|
155
|
+
* Check if command modifies files
|
|
354
156
|
*/
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
let processedOutput = output;
|
|
368
|
-
if (output.length > this.policy.maxOutputLength) {
|
|
369
|
-
processedOutput = output.slice(0, this.policy.maxOutputLength) + "\n... [truncated]";
|
|
370
|
-
}
|
|
371
|
-
if (this.policy.scanForSecrets) {
|
|
372
|
-
const secretFindings = this.scanForSecrets(processedOutput);
|
|
373
|
-
if (secretFindings.length > 0) {
|
|
374
|
-
hasSecrets = true;
|
|
375
|
-
findings.push(...secretFindings);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
if (this.policy.scanForErrors) {
|
|
379
|
-
const errorFindings = this.scanForErrors(processedOutput);
|
|
380
|
-
if (errorFindings.length > 0) {
|
|
381
|
-
hasErrors = true;
|
|
382
|
-
findings.push(...errorFindings);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
const redactedOutput = this.redact(processedOutput);
|
|
386
|
-
return {
|
|
387
|
-
hasSecrets,
|
|
388
|
-
hasErrors,
|
|
389
|
-
redactedOutput,
|
|
390
|
-
findings
|
|
391
|
-
};
|
|
157
|
+
isWriteCommand(command) {
|
|
158
|
+
const writePatterns = [
|
|
159
|
+
/^(vim|vi|nano|emacs|code)\s/,
|
|
160
|
+
/^(touch|mkdir|cp|mv|rm)\s/,
|
|
161
|
+
/^(echo|cat|printf).*>/,
|
|
162
|
+
/^(git\s+(add|commit|checkout|reset))/,
|
|
163
|
+
/^(npm|yarn|pnpm)\s+(install|uninstall)/,
|
|
164
|
+
/^(pip|pip3)\s+(install|uninstall)/,
|
|
165
|
+
/^chmod\s/,
|
|
166
|
+
/^chown\s/
|
|
167
|
+
];
|
|
168
|
+
return writePatterns.some((p) => p.test(command));
|
|
392
169
|
}
|
|
393
170
|
/**
|
|
394
|
-
*
|
|
171
|
+
* Get recent commands
|
|
395
172
|
*/
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
const lines = output.split("\n");
|
|
399
|
-
for (let i = 0; i < lines.length; i++) {
|
|
400
|
-
const line = lines[i];
|
|
401
|
-
for (const { pattern, name } of SECRET_PATTERNS) {
|
|
402
|
-
if (pattern.test(line)) {
|
|
403
|
-
findings.push({
|
|
404
|
-
type: "secret",
|
|
405
|
-
pattern: name,
|
|
406
|
-
message: `Potential ${name} found in output`,
|
|
407
|
-
line: i + 1
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
return findings;
|
|
173
|
+
getRecentCommands(n = 10) {
|
|
174
|
+
return this.commands.slice(-n);
|
|
413
175
|
}
|
|
414
176
|
/**
|
|
415
|
-
*
|
|
177
|
+
* Get blocked commands
|
|
416
178
|
*/
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
const lines = output.split("\n");
|
|
420
|
-
for (let i = 0; i < lines.length; i++) {
|
|
421
|
-
const line = lines[i];
|
|
422
|
-
for (const { pattern, name } of ERROR_PATTERNS) {
|
|
423
|
-
if (pattern.test(line)) {
|
|
424
|
-
findings.push({
|
|
425
|
-
type: "error",
|
|
426
|
-
pattern: name,
|
|
427
|
-
message: `${name} detected`,
|
|
428
|
-
line: i + 1
|
|
429
|
-
});
|
|
430
|
-
break;
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
return findings;
|
|
179
|
+
getBlockedCommands() {
|
|
180
|
+
return this.commands.filter((c) => !c.allowed);
|
|
435
181
|
}
|
|
436
182
|
/**
|
|
437
|
-
*
|
|
183
|
+
* Get high-risk commands
|
|
438
184
|
*/
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
for (const { pattern, name } of SECRET_PATTERNS) {
|
|
442
|
-
redacted = redacted.replace(new RegExp(pattern.source, "g"), `[REDACTED ${name}]`);
|
|
443
|
-
}
|
|
444
|
-
for (const pattern of this.redactPatterns) {
|
|
445
|
-
redacted = redacted.replace(pattern, "[REDACTED]");
|
|
446
|
-
}
|
|
447
|
-
return redacted;
|
|
185
|
+
getHighRiskCommands(threshold = 6) {
|
|
186
|
+
return this.commands.filter((c) => c.riskScore.score >= threshold);
|
|
448
187
|
}
|
|
449
188
|
/**
|
|
450
|
-
*
|
|
189
|
+
* Format duration for display
|
|
451
190
|
*/
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
}
|
|
458
|
-
return false;
|
|
191
|
+
static formatDuration(ms) {
|
|
192
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
193
|
+
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
194
|
+
if (ms < 36e5) return `${Math.floor(ms / 6e4)}m ${Math.floor(ms % 6e4 / 1e3)}s`;
|
|
195
|
+
return `${Math.floor(ms / 36e5)}h ${Math.floor(ms % 36e5 / 6e4)}m`;
|
|
459
196
|
}
|
|
460
197
|
/**
|
|
461
|
-
*
|
|
198
|
+
* Reset collector
|
|
462
199
|
*/
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
const parts = [];
|
|
470
|
-
if (secrets.length > 0) {
|
|
471
|
-
parts.push(`${secrets.length} potential secret(s)`);
|
|
472
|
-
}
|
|
473
|
-
if (errors.length > 0) {
|
|
474
|
-
parts.push(`${errors.length} error(s)`);
|
|
475
|
-
}
|
|
476
|
-
return parts.join(", ");
|
|
200
|
+
reset() {
|
|
201
|
+
this.sessionId = this.generateSessionId();
|
|
202
|
+
this.startTime = /* @__PURE__ */ new Date();
|
|
203
|
+
this.commands = [];
|
|
204
|
+
this.filesModified.clear();
|
|
205
|
+
this.pathsAccessed.clear();
|
|
477
206
|
}
|
|
478
207
|
};
|
|
479
208
|
|
|
@@ -549,6 +278,7 @@ export {
|
|
|
549
278
|
isInMoltbotSession,
|
|
550
279
|
isSandboxEnabled,
|
|
551
280
|
loadConfig,
|
|
552
|
-
resetBashgymIntegration
|
|
281
|
+
resetBashgymIntegration,
|
|
282
|
+
startMCPServer
|
|
553
283
|
};
|
|
554
284
|
//# sourceMappingURL=index.js.map
|