mstro-app 0.3.1 → 0.3.4
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 +3 -19
- package/bin/mstro.js +0 -175
- package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
- package/dist/server/mcp/bouncer-integration.js +43 -135
- package/dist/server/mcp/bouncer-integration.js.map +1 -1
- package/dist/server/services/websocket/file-utils.d.ts.map +1 -1
- package/dist/server/services/websocket/file-utils.js +26 -20
- package/dist/server/services/websocket/file-utils.js.map +1 -1
- package/dist/server/utils/paths.d.ts +0 -12
- package/dist/server/utils/paths.d.ts.map +1 -1
- package/dist/server/utils/paths.js +0 -12
- package/dist/server/utils/paths.js.map +1 -1
- package/package.json +1 -2
- package/server/README.md +0 -1
- package/server/mcp/README.md +0 -5
- package/server/mcp/bouncer-integration.ts +55 -210
- package/server/services/websocket/file-utils.ts +29 -24
- package/server/utils/paths.ts +0 -14
- package/bin/configure-claude.js +0 -298
- package/dist/server/mcp/bouncer-cli.d.ts +0 -3
- package/dist/server/mcp/bouncer-cli.d.ts.map +0 -1
- package/dist/server/mcp/bouncer-cli.js +0 -138
- package/dist/server/mcp/bouncer-cli.js.map +0 -1
- package/hooks/bouncer.sh +0 -159
- package/server/mcp/bouncer-cli.ts +0 -180
|
@@ -255,6 +255,28 @@ function readTextContent(fullPath, filePath, fileName, stats) {
|
|
|
255
255
|
size: stats.size, modifiedAt: stats.mtime.toISOString()
|
|
256
256
|
};
|
|
257
257
|
}
|
|
258
|
+
function validateFileAccess(fullPath, filePath, fileName, workingDir) {
|
|
259
|
+
const normalizedPath = join(fullPath);
|
|
260
|
+
if (!normalizedPath.startsWith(join(workingDir)) && !isPathInSafeLocation(normalizedPath)) {
|
|
261
|
+
return { path: filePath, fileName, content: '', error: 'Access denied: path outside allowed locations' };
|
|
262
|
+
}
|
|
263
|
+
if (!existsSync(fullPath)) {
|
|
264
|
+
return { path: filePath, fileName, content: '', error: 'File not found' };
|
|
265
|
+
}
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
function readValidatedFile(fullPath, filePath, fileName, stats) {
|
|
269
|
+
if (stats.isDirectory())
|
|
270
|
+
return readDirectoryContent(fullPath, filePath, fileName);
|
|
271
|
+
const isBin = isBinaryFile(fullPath);
|
|
272
|
+
const MAX_FILE_SIZE = isBin ? 10 * 1024 * 1024 : 1024 * 1024;
|
|
273
|
+
if (stats.size > MAX_FILE_SIZE) {
|
|
274
|
+
return { path: filePath, fileName, content: '', size: stats.size, error: `File too large (${Math.round(stats.size / 1024)}KB). Maximum is ${isBin ? '10MB' : '1MB'}.` };
|
|
275
|
+
}
|
|
276
|
+
return isBin
|
|
277
|
+
? readBinaryContent(fullPath, filePath, fileName, stats)
|
|
278
|
+
: readTextContent(fullPath, filePath, fileName, stats);
|
|
279
|
+
}
|
|
258
280
|
/**
|
|
259
281
|
* Read file content for context injection
|
|
260
282
|
*/
|
|
@@ -262,26 +284,10 @@ export function readFileContent(filePath, workingDir) {
|
|
|
262
284
|
try {
|
|
263
285
|
const fullPath = filePath.startsWith('/') ? filePath : join(workingDir, filePath);
|
|
264
286
|
const fileName = fullPath.split(sep).pop() || filePath;
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
if (!existsSync(fullPath)) {
|
|
271
|
-
return { path: filePath, fileName, content: '', error: 'File not found' };
|
|
272
|
-
}
|
|
273
|
-
const stats = statSync(fullPath);
|
|
274
|
-
if (stats.isDirectory()) {
|
|
275
|
-
return readDirectoryContent(fullPath, filePath, fileName);
|
|
276
|
-
}
|
|
277
|
-
const isBin = isBinaryFile(fullPath);
|
|
278
|
-
const MAX_FILE_SIZE = isBin ? 10 * 1024 * 1024 : 1024 * 1024;
|
|
279
|
-
if (stats.size > MAX_FILE_SIZE) {
|
|
280
|
-
return { path: filePath, fileName, content: '', size: stats.size, error: `File too large (${Math.round(stats.size / 1024)}KB). Maximum is ${isBin ? '10MB' : '1MB'}.` };
|
|
281
|
-
}
|
|
282
|
-
return isBin
|
|
283
|
-
? readBinaryContent(fullPath, filePath, fileName, stats)
|
|
284
|
-
: readTextContent(fullPath, filePath, fileName, stats);
|
|
287
|
+
const accessError = validateFileAccess(fullPath, filePath, fileName, workingDir);
|
|
288
|
+
if (accessError)
|
|
289
|
+
return accessError;
|
|
290
|
+
return readValidatedFile(fullPath, filePath, fileName, statSync(fullPath));
|
|
285
291
|
}
|
|
286
292
|
catch (error) {
|
|
287
293
|
console.error('[FileUtils] Error reading file:', error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-utils.js","sourceRoot":"","sources":["../../../../server/services/websocket/file-utils.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,gEAAgE;AAEhE;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAGzD,yDAAyD;AACzD,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa;IACzD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU;IAChD,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU;IAC1D,aAAa,EAAE,MAAM,EAAE,OAAO;CAC/B,CAAC,CAAC;AAEH,qCAAqC;AACrC,MAAM,CAAC,MAAM,aAAa,GAA2B;IACnD,wBAAwB;IACxB,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,MAAM;IACN,OAAO,EAAE,MAAM;IACf,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,KAAK;IACb,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,KAAK;IACd,OAAO;IACP,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,MAAM;IACf,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,KAAK;IACb,OAAO,EAAE,QAAQ;IACjB,SAAS;IACT,MAAM,EAAE,QAAQ;IAChB,YAAY,EAAE,QAAQ;IACtB,WAAW,EAAE,QAAQ;IACrB,aAAa,EAAE,QAAQ;IACvB,gBAAgB;IAChB,KAAK,EAAE,UAAU;IACjB,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,MAAM;IACd,SAAS;IACT,MAAM,EAAE,OAAO;IACf,MAAM,EAAE,OAAO;IACf,OAAO,EAAE,OAAO;IAChB,MAAM,EAAE,OAAO;IACf,MAAM,EAAE,OAAO;IACf,OAAO,EAAE,OAAO;IAChB,MAAM,EAAE,OAAO;IACf,kBAAkB;IAClB,KAAK,EAAE,QAAQ;IACf,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,MAAM;IACb,OAAO,EAAE,MAAM;IACf,KAAK,EAAE,QAAQ;IACf,QAAQ,EAAE,OAAO;IACjB,IAAI,EAAE,GAAG;IACT,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,GAAG;IACT,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,OAAO;IAChB,MAAM,EAAE,OAAO;IACf,OAAO,EAAE,OAAO;IAChB,gBAAgB;IAChB,OAAO,EAAE,MAAM;IACf,MAAM,EAAE,KAAK;CACd,CAAC;AAEF,kBAAkB;AAClB,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,EAAsB,CAAC;AAC5D,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,CAAC,iBAAiB;AAEnD;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5C,OAAO,aAAa,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,UAAkB;IAC/C,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IACrD,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,OAAO;aACrB,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aACxB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1E,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,KAAK,CAAC,CAAC;QAC9D,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,oBAAoB,CAAC,cAAsB,EAAE,YAAsB,EAAE,OAAe;IAC3F,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACtD,MAAM,kBAAkB,GAAG,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC3D,MAAM,YAAY,GAAG,kBAAkB,CAAC,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC;IAE7F,IAAI,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO,cAAc,KAAK,YAAY,IAAI,cAAc,CAAC,UAAU,CAAC,GAAG,YAAY,GAAG,CAAC,CAAC;IAC1F,CAAC;IAED,IAAI,YAAY,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,YAAY,GAAG,YAAY;aAC9B,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;aACrB,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC;aACtB,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC3B,OAAO,IAAI,MAAM,CAAC,QAAQ,YAAY,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,QAAkB;IACxD,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAChD,MAAM,YAAY,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,oBAAoB,CAAC,cAAc,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,KAAmD,EAAE,YAAoB,EAAE,iBAA2B;IAC7H,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5E,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,YAAY,EAAE,iBAAiB,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7F,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,+BAA+B,CAC7C,GAAW,EACX,OAAe,EACf,iBAA2B,EAC3B,UAAiE,EAAE,EACnE,aAAqB,IAAI,EACzB,WAAmB,EAAE,EACrB,eAAuB,CAAC;IAExB,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,MAAM,IAAI,UAAU,IAAI,YAAY,IAAI,QAAQ,EAAE,CAAC;YAC7D,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAE1D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,OAAO,CAAC,MAAM,IAAI,UAAU;gBAAE,MAAM;YAExC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAEjD,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,iBAAiB,CAAC;gBAAE,SAAS;YAEvE,OAAO,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YAEjE,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,OAAO,CAAC,MAAM,GAAG,UAAU,IAAI,YAAY,GAAG,CAAC,GAAG,QAAQ,EAAE,CAAC;gBACtF,+BAA+B,CAAC,QAAQ,EAAE,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,GAAG,CAAC,CAAC,CAAC;YACzH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,iCAAiC;IACnC,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACnD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC;IAClE,MAAM,YAAY,GAAG;QACnB,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC;QACxB,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC;QAC1B,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC;QACzB,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC;QAC1B,eAAe,EAAE,yCAAyC;QAC1D,OAAO;QACP,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,MAAM;KAC7B,CAAC;IACF,OAAO,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;AACtE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACpG,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IACpD,OAAO,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAC3D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,OAAO,WAAW,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,SAAS,CAAC,QAAgB;IACjC,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IACpD,OAAO,GAAG,KAAK,KAAK,CAAC;AACvB,CAAC;AAID,SAAS,oBAAoB,CAAC,QAAgB,EAAE,QAAgB,EAAE,QAAgB;IAChF,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/D,MAAM,OAAO,GAAG,OAAO;aACpB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;aACpC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACb,IAAI,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE;gBAAE,OAAO,CAAC,CAAC,CAAC;YACnD,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,WAAW,EAAE;gBAAE,OAAO,CAAC,CAAC;YAClD,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC,CAAC;aACD,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;aACjD,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;IACnF,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAW;IACpC,IAAI,GAAG,KAAK,KAAK;QAAE,OAAO,eAAe,CAAC;IAC1C,IAAI,GAAG,KAAK,KAAK;QAAE,OAAO,YAAY,CAAC;IACvC,IAAI,GAAG,KAAK,KAAK;QAAE,OAAO,iBAAiB,CAAC;IAC5C,OAAO,SAAS,GAAG,EAAE,CAAC;AACxB,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAgB,EAAE,QAAgB,EAAE,QAAgB,EAAE,KAAoC;IACnH,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,KAAK,CAAC;IAC7D,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACxC,OAAO;QACL,IAAI,EAAE,QAAQ,EAAE,QAAQ;QACxB,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAClC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE;QACvD,OAAO,EAAE,IAAI,EAAE,QAAQ;KACxB,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB,EAAE,QAAgB,EAAE,QAAgB,EAAE,KAAoC;IACjH,OAAO;QACL,IAAI,EAAE,QAAQ,EAAE,QAAQ;QACxB,OAAO,EAAE,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC;QACxC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE;KACxD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,UAAkB;IAClE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAClF,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,QAAQ,CAAC;QAEvD,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,cAAc,GAAG,cAAc,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QACnE,IAAI,CAAC,cAAc,IAAI,CAAC,oBAAoB,CAAC,cAAc,CAAC,EAAE,CAAC;YAC7D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,+CAA+C,EAAE,CAAC;QAC3G,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAC5E,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,OAAO,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACrC,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC;QAC7D,IAAI,KAAK,CAAC,IAAI,GAAG,aAAa,EAAE,CAAC;YAC/B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,mBAAmB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,mBAAmB,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;QAC1K,CAAC;QAED,OAAO,KAAK;YACV,CAAC,CAAC,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC;YACxD,CAAC,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC3D,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;QACxD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,qBAAqB,EAAE,CAAC;IACpL,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"file-utils.js","sourceRoot":"","sources":["../../../../server/services/websocket/file-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,16 +10,4 @@ export declare const MSTRO_ROOT: string;
|
|
|
10
10
|
* Path to the MCP bouncer server script
|
|
11
11
|
*/
|
|
12
12
|
export declare const MCP_SERVER_PATH: string;
|
|
13
|
-
/**
|
|
14
|
-
* Path to the MCP bouncer configuration template
|
|
15
|
-
*/
|
|
16
|
-
export declare const MCP_CONFIG_TEMPLATE_PATH: string;
|
|
17
|
-
/**
|
|
18
|
-
* Path to the hooks directory
|
|
19
|
-
*/
|
|
20
|
-
export declare const HOOKS_DIR: string;
|
|
21
|
-
/**
|
|
22
|
-
* Path to the bouncer hook script
|
|
23
|
-
*/
|
|
24
|
-
export declare const BOUNCER_HOOK: string;
|
|
25
13
|
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../server/utils/paths.ts"],"names":[],"mappings":"AAiBA;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,QAA8B,CAAC;AAEtD;;GAEG;AACH,eAAO,MAAM,eAAe,QAA8C,CAAC
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../server/utils/paths.ts"],"names":[],"mappings":"AAiBA;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,QAA8B,CAAC;AAEtD;;GAEG;AACH,eAAO,MAAM,eAAe,QAA8C,CAAC"}
|
|
@@ -23,16 +23,4 @@ export const MSTRO_ROOT = resolve(__dirname, '../..');
|
|
|
23
23
|
* Path to the MCP bouncer server script
|
|
24
24
|
*/
|
|
25
25
|
export const MCP_SERVER_PATH = resolve(MSTRO_ROOT, 'server/mcp/server.ts');
|
|
26
|
-
/**
|
|
27
|
-
* Path to the MCP bouncer configuration template
|
|
28
|
-
*/
|
|
29
|
-
export const MCP_CONFIG_TEMPLATE_PATH = resolve(MSTRO_ROOT, 'mstro-bouncer-mcp.json');
|
|
30
|
-
/**
|
|
31
|
-
* Path to the hooks directory
|
|
32
|
-
*/
|
|
33
|
-
export const HOOKS_DIR = resolve(MSTRO_ROOT, 'hooks');
|
|
34
|
-
/**
|
|
35
|
-
* Path to the bouncer hook script
|
|
36
|
-
*/
|
|
37
|
-
export const BOUNCER_HOOK = resolve(HOOKS_DIR, 'bouncer.sh');
|
|
38
26
|
//# sourceMappingURL=paths.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../server/utils/paths.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,gEAAgE;AAEhE;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,kDAAkD;AAClD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAEtD;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../server/utils/paths.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,gEAAgE;AAEhE;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,kDAAkD;AAClD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAEtD;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mstro-app",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "Run Claude Code from any browser - streams live sessions from your machine to mstro.app",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
"files": [
|
|
30
30
|
"bin/",
|
|
31
31
|
"server/",
|
|
32
|
-
"hooks/",
|
|
33
32
|
"dist/",
|
|
34
33
|
"PRIVACY.md",
|
|
35
34
|
"!bin/release.sh",
|
package/server/README.md
CHANGED
|
@@ -93,7 +93,6 @@ server/
|
|
|
93
93
|
│ ├── server.ts # MCP server entry
|
|
94
94
|
│ ├── bouncer-integration.ts # 2-layer security (patterns + AI)
|
|
95
95
|
│ ├── security-patterns.ts # Threat pattern matching
|
|
96
|
-
│ ├── bouncer-cli.ts # CLI wrapper for hook integration
|
|
97
96
|
│ └── security-audit.ts # Audit logging
|
|
98
97
|
└── utils/
|
|
99
98
|
├── paths.ts # Path utilities
|
package/server/mcp/README.md
CHANGED
|
@@ -22,7 +22,6 @@ MCP (Model Context Protocol) server that provides tool approval decisions for Cl
|
|
|
22
22
|
- **bouncer-integration.ts** — Core 2-layer security review logic. Orchestrates pattern check → AI analysis flow.
|
|
23
23
|
- **security-patterns.ts** — Pattern definitions: CRITICAL_THREATS, SAFE_OPERATIONS, NEEDS_AI_REVIEW, SENSITIVE_PATHS.
|
|
24
24
|
- **security-audit.ts** — Audit logging to `~/.mstro/logs/bouncer-audit.jsonl` (JSON Lines format).
|
|
25
|
-
- **bouncer-cli.ts** — Shell-callable wrapper invoked by `~/.claude/hooks/bouncer.sh`. Reads JSON from stdin, outputs decision to stdout.
|
|
26
25
|
|
|
27
26
|
## Usage
|
|
28
27
|
|
|
@@ -49,10 +48,6 @@ claude --print \
|
|
|
49
48
|
|
|
50
49
|
The MCP config is auto-generated by the headless runner at `~/.mstro/mcp-config.json`. It includes the bouncer server plus any user-configured MCP servers from `~/.claude.json`.
|
|
51
50
|
|
|
52
|
-
### Hook Integration
|
|
53
|
-
|
|
54
|
-
When installed via `mstro configure-hooks`, a shell script at `~/.claude/hooks/bouncer.sh` calls `bouncer-cli.ts` as a PreToolUse hook. This provides security for both mstro sessions and standalone Claude Code usage.
|
|
55
|
-
|
|
56
51
|
## Environment Variables
|
|
57
52
|
|
|
58
53
|
| Variable | Default | Description |
|
|
@@ -271,18 +271,50 @@ or
|
|
|
271
271
|
});
|
|
272
272
|
}
|
|
273
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Finalize a bouncer decision: log, track analytics, cache, and return.
|
|
276
|
+
*/
|
|
277
|
+
function finalizeDecision(
|
|
278
|
+
operation: string,
|
|
279
|
+
decision: BouncerDecision,
|
|
280
|
+
layer: string,
|
|
281
|
+
startTime: number,
|
|
282
|
+
context: BouncerReviewRequest['context'],
|
|
283
|
+
logFn: typeof import('./security-audit.js')['logBouncerDecision'],
|
|
284
|
+
opts?: { error?: string; skipCache?: boolean; skipAnalytics?: boolean },
|
|
285
|
+
): BouncerDecision {
|
|
286
|
+
const latencyMs = Math.round(performance.now() - startTime);
|
|
287
|
+
|
|
288
|
+
logFn(operation, decision.decision, decision.confidence, decision.reasoning, {
|
|
289
|
+
context, threatLevel: decision.threatLevel, layer, latencyMs, ...(opts?.error && { error: opts.error }),
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
if (!opts?.skipAnalytics) {
|
|
293
|
+
const event = decision.decision === 'deny' ? AnalyticsEvents.BOUNCER_TOOL_DENIED : AnalyticsEvents.BOUNCER_TOOL_ALLOWED;
|
|
294
|
+
trackEvent(event, {
|
|
295
|
+
layer,
|
|
296
|
+
operation_length: operation.length,
|
|
297
|
+
threat_level: decision.threatLevel,
|
|
298
|
+
confidence: decision.confidence,
|
|
299
|
+
latency_ms: latencyMs,
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (!opts?.skipCache) cacheDecision(operation, decision);
|
|
304
|
+
return decision;
|
|
305
|
+
}
|
|
306
|
+
|
|
274
307
|
/**
|
|
275
308
|
* Main bouncer review function - 2-layer hybrid system
|
|
276
309
|
*/
|
|
277
310
|
export async function reviewOperation(request: BouncerReviewRequest): Promise<BouncerDecision> {
|
|
278
|
-
// Import audit logger
|
|
279
311
|
const { logBouncerDecision } = await import('./security-audit.js');
|
|
280
|
-
|
|
281
312
|
const startTime = performance.now();
|
|
282
|
-
|
|
283
313
|
const { operation } = request;
|
|
314
|
+
const fin = (d: BouncerDecision, layer: string, opts?: Parameters<typeof finalizeDecision>[6]) =>
|
|
315
|
+
finalizeDecision(operation, d, layer, startTime, request.context, logBouncerDecision, opts);
|
|
284
316
|
|
|
285
|
-
// Check cache first
|
|
317
|
+
// Check cache first
|
|
286
318
|
const cached = getCachedDecision(operation);
|
|
287
319
|
if (cached) {
|
|
288
320
|
console.error(`[Bouncer] ⚡ Cache hit: ${cached.decision} (${cached.confidence}%)`);
|
|
@@ -295,257 +327,70 @@ export async function reviewOperation(request: BouncerReviewRequest): Promise<Bo
|
|
|
295
327
|
console.error(`[Bouncer] User request: ${request.context.userRequest}`);
|
|
296
328
|
}
|
|
297
329
|
|
|
298
|
-
//
|
|
299
|
-
// PRE-CHECK: Malformed/empty tool calls
|
|
300
|
-
// ========================================
|
|
301
|
-
// Empty-param Edit/Write calls are no-ops that will fail validation anyway.
|
|
302
|
-
// Allow immediately instead of wasting ~8s on Haiku analysis.
|
|
330
|
+
// PRE-CHECK: Empty-param Edit/Write calls are no-ops — allow immediately
|
|
303
331
|
const toolInput = request.context?.toolInput;
|
|
304
332
|
if (toolInput && typeof toolInput === 'object' && Object.keys(toolInput).length === 0) {
|
|
305
333
|
console.error('[Bouncer] ⚡ Fast path: Empty tool parameters (no-op)');
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
const decision: BouncerDecision = {
|
|
309
|
-
decision: 'allow',
|
|
310
|
-
confidence: 95,
|
|
311
|
-
reasoning: 'Empty tool parameters - operation is a no-op with no side effects.',
|
|
312
|
-
threatLevel: 'low'
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
logBouncerDecision(
|
|
316
|
-
operation,
|
|
317
|
-
decision.decision,
|
|
318
|
-
decision.confidence,
|
|
319
|
-
decision.reasoning,
|
|
320
|
-
{ context: request.context, threatLevel: decision.threatLevel, layer: 'pattern-noop', latencyMs }
|
|
321
|
-
);
|
|
322
|
-
|
|
323
|
-
cacheDecision(operation, decision);
|
|
324
|
-
return decision;
|
|
334
|
+
return fin({ decision: 'allow', confidence: 95, reasoning: 'Empty tool parameters - operation is a no-op with no side effects.', threatLevel: 'low' }, 'pattern-noop', { skipAnalytics: true });
|
|
325
335
|
}
|
|
326
336
|
|
|
327
|
-
// ========================================
|
|
328
337
|
// LAYER 1: Pattern-Based Fast Path (< 5ms)
|
|
329
|
-
// ========================================
|
|
330
338
|
|
|
331
|
-
// Check safe operations FIRST
|
|
339
|
+
// Check safe operations FIRST — allows trusted sources (e.g., brew, rustup)
|
|
332
340
|
// to pass before hitting critical threat patterns like curl|bash
|
|
333
341
|
const safeOperation = matchesPattern(operation, SAFE_OPERATIONS);
|
|
334
342
|
if (safeOperation) {
|
|
335
343
|
console.error('[Bouncer] ⚡ Fast path: Safe operation approved');
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
const decision: BouncerDecision = {
|
|
339
|
-
decision: 'allow',
|
|
340
|
-
confidence: 95,
|
|
341
|
-
reasoning: 'Operation matches known-safe patterns. No security concerns detected.',
|
|
342
|
-
threatLevel: 'low'
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
logBouncerDecision(
|
|
346
|
-
operation,
|
|
347
|
-
decision.decision,
|
|
348
|
-
decision.confidence,
|
|
349
|
-
decision.reasoning,
|
|
350
|
-
{ context: request.context, threatLevel: decision.threatLevel, layer: 'pattern-safe', latencyMs }
|
|
351
|
-
);
|
|
352
|
-
trackEvent(AnalyticsEvents.BOUNCER_TOOL_ALLOWED, {
|
|
353
|
-
layer: 'pattern-safe',
|
|
354
|
-
operation_length: operation.length,
|
|
355
|
-
threat_level: 'low',
|
|
356
|
-
confidence: 95,
|
|
357
|
-
latency_ms: latencyMs,
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
cacheDecision(operation, decision);
|
|
361
|
-
return decision;
|
|
344
|
+
return fin({ decision: 'allow', confidence: 95, reasoning: 'Operation matches known-safe patterns. No security concerns detected.', threatLevel: 'low' }, 'pattern-safe');
|
|
362
345
|
}
|
|
363
346
|
|
|
364
|
-
//
|
|
365
|
-
// These are ALWAYS denied - no context can justify them
|
|
347
|
+
// Critical threats (rm -rf /, fork bombs) — ALWAYS denied
|
|
366
348
|
const criticalThreat = matchesPattern(operation, CRITICAL_THREATS);
|
|
367
349
|
if (criticalThreat) {
|
|
368
350
|
console.error('[Bouncer] ⚡ Fast path: CRITICAL THREAT detected');
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
const decision: BouncerDecision = {
|
|
372
|
-
decision: 'deny',
|
|
373
|
-
confidence: 99,
|
|
374
|
-
reasoning: `🚨 CRITICAL THREAT: ${criticalThreat.reason}`,
|
|
375
|
-
threatLevel: 'critical',
|
|
351
|
+
return fin({
|
|
352
|
+
decision: 'deny', confidence: 99, reasoning: `🚨 CRITICAL THREAT: ${criticalThreat.reason}`, threatLevel: 'critical',
|
|
376
353
|
alternative: 'This operation should never be performed. If you need to accomplish a specific task, please describe your goal and I can suggest safe alternatives.',
|
|
377
|
-
enforceable: true
|
|
378
|
-
};
|
|
379
|
-
|
|
380
|
-
logBouncerDecision(
|
|
381
|
-
operation,
|
|
382
|
-
decision.decision,
|
|
383
|
-
decision.confidence,
|
|
384
|
-
decision.reasoning,
|
|
385
|
-
{ context: request.context, threatLevel: decision.threatLevel, layer: 'pattern-critical', latencyMs }
|
|
386
|
-
);
|
|
387
|
-
trackEvent(AnalyticsEvents.BOUNCER_TOOL_DENIED, {
|
|
388
|
-
layer: 'pattern-critical',
|
|
389
|
-
operation_length: operation.length,
|
|
390
|
-
threat_level: 'critical',
|
|
391
|
-
confidence: 99,
|
|
392
|
-
latency_ms: latencyMs,
|
|
393
|
-
});
|
|
394
|
-
|
|
395
|
-
cacheDecision(operation, decision);
|
|
396
|
-
return decision;
|
|
354
|
+
enforceable: true,
|
|
355
|
+
}, 'pattern-critical');
|
|
397
356
|
}
|
|
398
357
|
|
|
399
|
-
// ========================================
|
|
400
358
|
// LAYER 2: Haiku AI Analysis (~200-500ms)
|
|
401
|
-
// ========================================
|
|
402
359
|
|
|
403
|
-
//
|
|
360
|
+
// Default allow for operations that don't need AI review
|
|
404
361
|
if (!requiresAIReview(operation)) {
|
|
405
|
-
// Default allow for operations that don't match any pattern
|
|
406
362
|
console.error('[Bouncer] ⚡ Fast path: No concerning patterns, allowing');
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
const decision: BouncerDecision = {
|
|
410
|
-
decision: 'allow',
|
|
411
|
-
confidence: 80,
|
|
412
|
-
reasoning: 'Operation appears safe based on pattern analysis. No obvious threats detected.',
|
|
413
|
-
threatLevel: 'low'
|
|
414
|
-
};
|
|
415
|
-
|
|
416
|
-
logBouncerDecision(
|
|
417
|
-
operation,
|
|
418
|
-
decision.decision,
|
|
419
|
-
decision.confidence,
|
|
420
|
-
decision.reasoning,
|
|
421
|
-
{ context: request.context, threatLevel: decision.threatLevel, layer: 'pattern-default', latencyMs }
|
|
422
|
-
);
|
|
423
|
-
trackEvent(AnalyticsEvents.BOUNCER_TOOL_ALLOWED, {
|
|
424
|
-
layer: 'pattern-default',
|
|
425
|
-
operation_length: operation.length,
|
|
426
|
-
threat_level: 'low',
|
|
427
|
-
confidence: 80,
|
|
428
|
-
latency_ms: latencyMs,
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
cacheDecision(operation, decision);
|
|
432
|
-
return decision;
|
|
363
|
+
return fin({ decision: 'allow', confidence: 80, reasoning: 'Operation appears safe based on pattern analysis. No obvious threats detected.', threatLevel: 'low' }, 'pattern-default');
|
|
433
364
|
}
|
|
434
365
|
|
|
435
|
-
|
|
436
|
-
const useAI = process.env.BOUNCER_USE_AI !== 'false';
|
|
437
|
-
|
|
438
|
-
if (!useAI) {
|
|
366
|
+
if (process.env.BOUNCER_USE_AI === 'false') {
|
|
439
367
|
console.error('[Bouncer] AI analysis disabled (BOUNCER_USE_AI=false)');
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
const decision: BouncerDecision = {
|
|
443
|
-
decision: 'warn_allow',
|
|
444
|
-
confidence: 60,
|
|
445
|
-
reasoning: 'Operation requires review but AI analysis is disabled. Proceeding with caution.',
|
|
446
|
-
threatLevel: 'medium'
|
|
447
|
-
};
|
|
448
|
-
|
|
449
|
-
logBouncerDecision(
|
|
450
|
-
operation,
|
|
451
|
-
decision.decision,
|
|
452
|
-
decision.confidence,
|
|
453
|
-
decision.reasoning,
|
|
454
|
-
{ context: request.context, threatLevel: decision.threatLevel, layer: 'ai-disabled', latencyMs }
|
|
455
|
-
);
|
|
456
|
-
|
|
457
|
-
return decision;
|
|
368
|
+
return fin({ decision: 'warn_allow', confidence: 60, reasoning: 'Operation requires review but AI analysis is disabled. Proceeding with caution.', threatLevel: 'medium' }, 'ai-disabled', { skipCache: true, skipAnalytics: true });
|
|
458
369
|
}
|
|
459
370
|
|
|
460
371
|
console.error('[Bouncer] 🤖 Invoking Haiku for AI analysis...');
|
|
461
|
-
trackEvent(AnalyticsEvents.BOUNCER_HAIKU_REVIEW, {
|
|
462
|
-
operation_length: operation.length,
|
|
463
|
-
});
|
|
372
|
+
trackEvent(AnalyticsEvents.BOUNCER_HAIKU_REVIEW, { operation_length: operation.length });
|
|
464
373
|
|
|
465
|
-
// Get Claude command and working directory from context or use defaults
|
|
466
374
|
const claudeCommand = process.env.CLAUDE_COMMAND || 'claude';
|
|
467
375
|
const workingDir = request.context?.workingDirectory || process.cwd();
|
|
468
376
|
|
|
469
377
|
try {
|
|
470
378
|
const decision = await analyzeWithHaiku(request, claudeCommand, workingDir);
|
|
471
|
-
|
|
472
|
-
console.error(`[Bouncer] ✓ Haiku decision: ${decision.decision} (${decision.confidence}% confidence) [${latencyMs}ms]`);
|
|
379
|
+
console.error(`[Bouncer] ✓ Haiku decision: ${decision.decision} (${decision.confidence}% confidence) [${Math.round(performance.now() - startTime)}ms]`);
|
|
473
380
|
console.error(`[Bouncer] Reasoning: ${decision.reasoning}`);
|
|
474
|
-
|
|
475
|
-
logBouncerDecision(
|
|
476
|
-
operation,
|
|
477
|
-
decision.decision,
|
|
478
|
-
decision.confidence,
|
|
479
|
-
decision.reasoning,
|
|
480
|
-
{ context: request.context, threatLevel: decision.threatLevel, layer: 'haiku-ai', latencyMs }
|
|
481
|
-
);
|
|
482
|
-
trackEvent(decision.decision === 'deny' ? AnalyticsEvents.BOUNCER_TOOL_DENIED : AnalyticsEvents.BOUNCER_TOOL_ALLOWED, {
|
|
483
|
-
layer: 'haiku-ai',
|
|
484
|
-
operation_length: operation.length,
|
|
485
|
-
threat_level: decision.threatLevel,
|
|
486
|
-
confidence: decision.confidence,
|
|
487
|
-
latency_ms: latencyMs,
|
|
488
|
-
});
|
|
489
|
-
|
|
490
|
-
cacheDecision(operation, decision);
|
|
491
|
-
return decision;
|
|
492
|
-
|
|
381
|
+
return fin(decision, 'haiku-ai');
|
|
493
382
|
} catch (error: unknown) {
|
|
494
|
-
const latencyMs = Math.round(performance.now() - startTime);
|
|
495
383
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
496
|
-
const isTimeout = errorMessage.includes('timed out');
|
|
497
384
|
|
|
498
|
-
if (
|
|
499
|
-
// Timeout: default to ALLOW — prefer availability over security stall,
|
|
500
|
-
// since the user drove the interaction
|
|
385
|
+
if (errorMessage.includes('timed out')) {
|
|
501
386
|
console.error(`[Bouncer] ⚠️ Haiku analysis timed out after ${HAIKU_TIMEOUT_MS}ms — defaulting to ALLOW`);
|
|
502
387
|
captureException(error, { context: 'bouncer.haiku_timeout', operation });
|
|
503
|
-
|
|
504
|
-
const decision: BouncerDecision = {
|
|
505
|
-
decision: 'allow',
|
|
506
|
-
confidence: 50,
|
|
507
|
-
reasoning: `Security analysis timed out after ${HAIKU_TIMEOUT_MS}ms. Defaulting to allow — user initiated the action.`,
|
|
508
|
-
threatLevel: 'medium'
|
|
509
|
-
};
|
|
510
|
-
|
|
511
|
-
logBouncerDecision(
|
|
512
|
-
operation,
|
|
513
|
-
decision.decision,
|
|
514
|
-
decision.confidence,
|
|
515
|
-
decision.reasoning,
|
|
516
|
-
{ context: request.context, threatLevel: decision.threatLevel, layer: 'haiku-timeout', latencyMs, error: errorMessage }
|
|
517
|
-
);
|
|
518
|
-
trackEvent(AnalyticsEvents.BOUNCER_TOOL_ALLOWED, {
|
|
519
|
-
layer: 'haiku-timeout',
|
|
520
|
-
operation_length: operation.length,
|
|
521
|
-
threat_level: 'medium',
|
|
522
|
-
confidence: 50,
|
|
523
|
-
latency_ms: latencyMs,
|
|
524
|
-
});
|
|
525
|
-
|
|
526
|
-
return decision;
|
|
388
|
+
return fin({ decision: 'allow', confidence: 50, reasoning: `Security analysis timed out after ${HAIKU_TIMEOUT_MS}ms. Defaulting to allow — user initiated the action.`, threatLevel: 'medium' }, 'haiku-timeout', { skipCache: true });
|
|
527
389
|
}
|
|
528
390
|
|
|
529
391
|
console.error(`[Bouncer] ⚠️ Haiku analysis failed: ${errorMessage}`);
|
|
530
392
|
captureException(error, { context: 'bouncer.haiku_analysis', operation });
|
|
531
|
-
|
|
532
|
-
// Fail-safe: deny on non-timeout AI failure
|
|
533
|
-
const decision: BouncerDecision = {
|
|
534
|
-
decision: 'deny',
|
|
535
|
-
confidence: 0,
|
|
536
|
-
reasoning: `Security analysis failed: ${errorMessage}. Denying for safety.`,
|
|
537
|
-
threatLevel: 'critical'
|
|
538
|
-
};
|
|
539
|
-
|
|
540
|
-
logBouncerDecision(
|
|
541
|
-
operation,
|
|
542
|
-
decision.decision,
|
|
543
|
-
decision.confidence,
|
|
544
|
-
decision.reasoning,
|
|
545
|
-
{ context: request.context, threatLevel: decision.threatLevel, layer: 'ai-error', latencyMs, error: errorMessage }
|
|
546
|
-
);
|
|
547
|
-
|
|
548
|
-
return decision;
|
|
393
|
+
return fin({ decision: 'deny', confidence: 0, reasoning: `Security analysis failed: ${errorMessage}. Denying for safety.`, threatLevel: 'critical' }, 'ai-error', { skipCache: true, skipAnalytics: true, error: errorMessage });
|
|
549
394
|
}
|
|
550
395
|
}
|
|
551
396
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* File type detection, gitignore parsing, and directory scanning utilities.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
10
|
+
import { existsSync, readdirSync, readFileSync, type Stats, statSync } from 'node:fs';
|
|
11
11
|
import { extname, join, relative, sep } from 'node:path';
|
|
12
12
|
import type { CacheEntry, } from './types.js';
|
|
13
13
|
|
|
@@ -285,6 +285,31 @@ function readTextContent(fullPath: string, filePath: string, fileName: string, s
|
|
|
285
285
|
};
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
function validateFileAccess(fullPath: string, filePath: string, fileName: string, workingDir: string): FileContentResult | null {
|
|
289
|
+
const normalizedPath = join(fullPath);
|
|
290
|
+
if (!normalizedPath.startsWith(join(workingDir)) && !isPathInSafeLocation(normalizedPath)) {
|
|
291
|
+
return { path: filePath, fileName, content: '', error: 'Access denied: path outside allowed locations' };
|
|
292
|
+
}
|
|
293
|
+
if (!existsSync(fullPath)) {
|
|
294
|
+
return { path: filePath, fileName, content: '', error: 'File not found' };
|
|
295
|
+
}
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function readValidatedFile(fullPath: string, filePath: string, fileName: string, stats: Stats): FileContentResult {
|
|
300
|
+
if (stats.isDirectory()) return readDirectoryContent(fullPath, filePath, fileName);
|
|
301
|
+
|
|
302
|
+
const isBin = isBinaryFile(fullPath);
|
|
303
|
+
const MAX_FILE_SIZE = isBin ? 10 * 1024 * 1024 : 1024 * 1024;
|
|
304
|
+
if (stats.size > MAX_FILE_SIZE) {
|
|
305
|
+
return { path: filePath, fileName, content: '', size: stats.size, error: `File too large (${Math.round(stats.size / 1024)}KB). Maximum is ${isBin ? '10MB' : '1MB'}.` };
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return isBin
|
|
309
|
+
? readBinaryContent(fullPath, filePath, fileName, stats)
|
|
310
|
+
: readTextContent(fullPath, filePath, fileName, stats);
|
|
311
|
+
}
|
|
312
|
+
|
|
288
313
|
/**
|
|
289
314
|
* Read file content for context injection
|
|
290
315
|
*/
|
|
@@ -293,30 +318,10 @@ export function readFileContent(filePath: string, workingDir: string): FileConte
|
|
|
293
318
|
const fullPath = filePath.startsWith('/') ? filePath : join(workingDir, filePath);
|
|
294
319
|
const fileName = fullPath.split(sep).pop() || filePath;
|
|
295
320
|
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
if (!isInWorkingDir && !isPathInSafeLocation(normalizedPath)) {
|
|
299
|
-
return { path: filePath, fileName, content: '', error: 'Access denied: path outside allowed locations' };
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
if (!existsSync(fullPath)) {
|
|
303
|
-
return { path: filePath, fileName, content: '', error: 'File not found' };
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
const stats = statSync(fullPath);
|
|
307
|
-
if (stats.isDirectory()) {
|
|
308
|
-
return readDirectoryContent(fullPath, filePath, fileName);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
const isBin = isBinaryFile(fullPath);
|
|
312
|
-
const MAX_FILE_SIZE = isBin ? 10 * 1024 * 1024 : 1024 * 1024;
|
|
313
|
-
if (stats.size > MAX_FILE_SIZE) {
|
|
314
|
-
return { path: filePath, fileName, content: '', size: stats.size, error: `File too large (${Math.round(stats.size / 1024)}KB). Maximum is ${isBin ? '10MB' : '1MB'}.` };
|
|
315
|
-
}
|
|
321
|
+
const accessError = validateFileAccess(fullPath, filePath, fileName, workingDir);
|
|
322
|
+
if (accessError) return accessError;
|
|
316
323
|
|
|
317
|
-
return
|
|
318
|
-
? readBinaryContent(fullPath, filePath, fileName, stats)
|
|
319
|
-
: readTextContent(fullPath, filePath, fileName, stats);
|
|
324
|
+
return readValidatedFile(fullPath, filePath, fileName, statSync(fullPath));
|
|
320
325
|
} catch (error: unknown) {
|
|
321
326
|
console.error('[FileUtils] Error reading file:', error);
|
|
322
327
|
return { path: filePath, fileName: filePath.split(sep).pop() || filePath, content: '', error: (error instanceof Error ? error.message : String(error)) || 'Failed to read file' };
|
package/server/utils/paths.ts
CHANGED
|
@@ -29,17 +29,3 @@ export const MSTRO_ROOT = resolve(__dirname, '../..');
|
|
|
29
29
|
*/
|
|
30
30
|
export const MCP_SERVER_PATH = resolve(MSTRO_ROOT, 'server/mcp/server.ts');
|
|
31
31
|
|
|
32
|
-
/**
|
|
33
|
-
* Path to the MCP bouncer configuration template
|
|
34
|
-
*/
|
|
35
|
-
export const MCP_CONFIG_TEMPLATE_PATH = resolve(MSTRO_ROOT, 'mstro-bouncer-mcp.json');
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Path to the hooks directory
|
|
39
|
-
*/
|
|
40
|
-
export const HOOKS_DIR = resolve(MSTRO_ROOT, 'hooks');
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Path to the bouncer hook script
|
|
44
|
-
*/
|
|
45
|
-
export const BOUNCER_HOOK = resolve(HOOKS_DIR, 'bouncer.sh');
|