@justanothermldude/mcp-exec 1.7.3 → 1.7.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.
@@ -177,8 +177,14 @@ function generateInterface(name, schema, definitions) {
177
177
  */
178
178
  function sanitizeJsDoc(text) {
179
179
  // Escape */ to prevent premature JSDoc comment closure
180
- // This handles glob patterns like "src/**/*.ts" in tool descriptions
181
- return text.replace(/\*\//g, '* /');
180
+ // (handles glob patterns like "src/**/*.ts" in tool descriptions)
181
+ let sanitized = text.replace(/\*\//g, '* /');
182
+ // Collapse newlines to prevent line-injection into JSDoc blocks
183
+ sanitized = sanitized.replace(/\r?\n/g, ' ');
184
+ // Escape @ at word boundaries to prevent JSDoc tag injection from a
185
+ // malicious tool description (e.g. "@param input.password string").
186
+ sanitized = sanitized.replace(/(?:^|\s)@([a-zA-Z_]\w*)/g, ' \\@$1');
187
+ return sanitized;
182
188
  }
183
189
  /**
184
190
  * Generate a recursive Proxy guard that warns on undefined field access on MCP responses.
@@ -203,14 +209,18 @@ function __guardFields(obj, label) {
203
209
  }
204
210
  });
205
211
  }
212
+ const __safeKeys = new Set(['then', 'toJSON', 'length', 'constructor', 'nodeType', 'valueOf', 'toString', 'inspect']);
213
+ const __dangerousKeys = new Set(['__proto__', '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'prototype']);
206
214
  return new Proxy(obj, {
207
215
  get(target, prop) {
208
- if (typeof prop === 'symbol' || prop === 'then' || prop === 'toJSON'
209
- || prop === 'length' || prop === 'constructor' || prop === 'nodeType'
210
- || prop === 'valueOf' || prop === 'toString' || prop === 'inspect') {
216
+ if (typeof prop === 'symbol') return target[prop];
217
+ const propStr = String(prop);
218
+ if (__dangerousKeys.has(propStr)) {
219
+ throw new TypeError('Access to "' + propStr + '" is not allowed on ' + label);
220
+ }
221
+ if (__safeKeys.has(propStr)) {
211
222
  return target[prop];
212
223
  }
213
- if (prop === '__proto__' || prop === 'prototype') return undefined;
214
224
  if (Object.prototype.hasOwnProperty.call(target, prop)) {
215
225
  const val = target[prop];
216
226
  if (val && typeof val === 'object') {
@@ -271,8 +281,11 @@ export function generateFuzzyProxy(targetVarName, contextName, helpString) {
271
281
  get(target, prop) {
272
282
  if (typeof prop !== 'string') return undefined;
273
283
 
274
- // Block prototype pollution vectors
275
- if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') return undefined;
284
+ // Block prototype pollution vectors with a loud error so callers cannot silently
285
+ // probe the proxy for __proto__ or prototype indirection.
286
+ if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') {
287
+ throw new TypeError('Access to "' + prop + '" is not allowed on ${safeContextName}');
288
+ }
276
289
 
277
290
  // Fast-path: exact match — use hasOwnProperty to avoid prototype chain leaks
278
291
  if (Object.prototype.hasOwnProperty.call(target, prop)) return target[prop];
package/dist/index.js CHANGED
@@ -488,7 +488,10 @@ function generateInterface(name, schema, definitions) {
488
488
  }
489
489
  __name(generateInterface, "generateInterface");
490
490
  function sanitizeJsDoc(text) {
491
- return text.replace(/\*\//g, "* /");
491
+ let sanitized = text.replace(/\*\//g, "* /");
492
+ sanitized = sanitized.replace(/\r?\n/g, " ");
493
+ sanitized = sanitized.replace(/(?:^|\s)@([a-zA-Z_]\w*)/g, " \\@$1");
494
+ return sanitized;
492
495
  }
493
496
  __name(sanitizeJsDoc, "sanitizeJsDoc");
494
497
  function generateFieldGuard() {
@@ -508,14 +511,18 @@ function __guardFields(obj, label) {
508
511
  }
509
512
  });
510
513
  }
514
+ const __safeKeys = new Set(['then', 'toJSON', 'length', 'constructor', 'nodeType', 'valueOf', 'toString', 'inspect']);
515
+ const __dangerousKeys = new Set(['__proto__', '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'prototype']);
511
516
  return new Proxy(obj, {
512
517
  get(target, prop) {
513
- if (typeof prop === 'symbol' || prop === 'then' || prop === 'toJSON'
514
- || prop === 'length' || prop === 'constructor' || prop === 'nodeType'
515
- || prop === 'valueOf' || prop === 'toString' || prop === 'inspect') {
518
+ if (typeof prop === 'symbol') return target[prop];
519
+ const propStr = String(prop);
520
+ if (__dangerousKeys.has(propStr)) {
521
+ throw new TypeError('Access to "' + propStr + '" is not allowed on ' + label);
522
+ }
523
+ if (__safeKeys.has(propStr)) {
516
524
  return target[prop];
517
525
  }
518
- if (prop === '__proto__' || prop === 'prototype') return undefined;
519
526
  if (Object.prototype.hasOwnProperty.call(target, prop)) {
520
527
  const val = target[prop];
521
528
  if (val && typeof val === 'object') {
@@ -555,8 +562,11 @@ function generateFuzzyProxy(targetVarName, contextName, helpString) {
555
562
  get(target, prop) {
556
563
  if (typeof prop !== 'string') return undefined;
557
564
 
558
- // Block prototype pollution vectors
559
- if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') return undefined;
565
+ // Block prototype pollution vectors with a loud error so callers cannot silently
566
+ // probe the proxy for __proto__ or prototype indirection.
567
+ if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') {
568
+ throw new TypeError('Access to "' + prop + '" is not allowed on ${safeContextName}');
569
+ }
560
570
 
561
571
  // Fast-path: exact match \u2014 use hasOwnProperty to avoid prototype chain leaks
562
572
  if (Object.prototype.hasOwnProperty.call(target, prop)) return target[prop];
@@ -1981,7 +1991,7 @@ __name(createMcpExecServer, "createMcpExecServer");
1981
1991
  // dist/index.js
1982
1992
  import { ServerPool, createConnection, getServerConfig as getServerConfig2, loadServerManifest as loadServerManifest2, cleanupOrphanedProcesses } from "@justanothermldude/meta-mcp-core";
1983
1993
  var APP_NAME = "mcp-exec";
1984
- var VERSION2 = "1.7.3";
1994
+ var VERSION2 = "1.7.4";
1985
1995
  var defaultExecutor = null;
1986
1996
  function getDefaultExecutor() {
1987
1997
  if (!defaultExecutor) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@justanothermldude/mcp-exec",
3
- "version": "1.7.3",
3
+ "version": "1.7.4",
4
4
  "description": "MCP execution utilities for sandboxed code execution with OS-level isolation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",