@enclave-vm/core
Advanced tools
| { | ||
| "name": "@enclave-vm/core", | ||
| "version": "2.10.1", | ||
| "description": "Sandbox runtime for secure JavaScript code execution", | ||
| "author": "AgentFront <info@agentfront.dev>", | ||
| "homepage": "https://github.com/agentfront/enclave", | ||
| "license": "Apache-2.0", | ||
| "keywords": [ | ||
| "sandbox", | ||
| "vm", | ||
| "enclave", | ||
| "enclave-vm", | ||
| "agentscript", | ||
| "llm", | ||
| "javascript", | ||
| "execution", | ||
| "security", | ||
| "ast-guard" | ||
| ], | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/agentfront/enclave.git" | ||
| }, | ||
| "bugs": { | ||
| "url": "https://github.com/agentfront/enclave/issues" | ||
| }, | ||
| "main": "./dist/index.js", | ||
| "module": "./dist/esm/index.mjs", | ||
| "types": "./dist/index.d.ts", | ||
| "exports": { | ||
| "./package.json": "./package.json", | ||
| ".": { | ||
| "development": "./src/index.ts", | ||
| "types": "./dist/index.d.ts", | ||
| "import": "./dist/esm/index.mjs", | ||
| "require": "./dist/index.js", | ||
| "default": "./dist/index.js" | ||
| } | ||
| }, | ||
| "dependencies": { | ||
| "@babel/standalone": "^7.29.0", | ||
| "@enclave-vm/types": "2.10.1", | ||
| "@enclave-vm/ast": "2.10.1", | ||
| "acorn": "8.15.0", | ||
| "acorn-walk": "8.3.4", | ||
| "astring": "1.9.0", | ||
| "zod": "^4.3.6" | ||
| }, | ||
| "peerDependencies": { | ||
| "@huggingface/transformers": "^3.2.2", | ||
| "vectoriadb": "^2.1.3" | ||
| }, | ||
| "peerDependenciesMeta": { | ||
| "@huggingface/transformers": { | ||
| "optional": true | ||
| }, | ||
| "vectoriadb": { | ||
| "optional": true | ||
| } | ||
| } | ||
| } |
| "use strict"; | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
| // If the importer is in node compatibility mode or this is not an ESM | ||
| // file that has been converted to a CommonJS file using a Babel- | ||
| // compatible transform (i.e. "__esModule" has not been set), then set | ||
| // "default" to the CommonJS "module.exports" for node compatibility. | ||
| isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
| mod | ||
| )); | ||
| // libs/core/src/adapters/worker-pool/worker-script.ts | ||
| var import_worker_threads = require("worker_threads"); | ||
| var import_vm = __toESM(require("vm")); | ||
| var import_crypto = __toESM(require("crypto")); | ||
| // libs/core/src/adapters/worker-pool/errors.ts | ||
| var WorkerPoolError = class extends Error { | ||
| constructor(message) { | ||
| super(message); | ||
| this.name = "WorkerPoolError"; | ||
| if (Error.captureStackTrace) { | ||
| Error.captureStackTrace(this, this.constructor); | ||
| } | ||
| } | ||
| }; | ||
| var MessageValidationError = class extends WorkerPoolError { | ||
| constructor(details) { | ||
| super(details ? `Invalid message: ${details}` : "Invalid message format"); | ||
| this.name = "MessageValidationError"; | ||
| } | ||
| }; | ||
| var MessageSizeError = class extends WorkerPoolError { | ||
| /** Actual message size */ | ||
| sizeBytes; | ||
| /** Maximum allowed size */ | ||
| maxBytes; | ||
| constructor(sizeBytes, maxBytes) { | ||
| super(`Message size ${Math.round(sizeBytes / 1024)}KB exceeds limit ${Math.round(maxBytes / 1024)}KB`); | ||
| this.name = "MessageSizeError"; | ||
| this.sizeBytes = sizeBytes; | ||
| this.maxBytes = maxBytes; | ||
| } | ||
| }; | ||
| // libs/core/src/adapters/worker-pool/safe-deserialize.ts | ||
| var DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]); | ||
| var MAX_DEPTH = 50; | ||
| function safeDeserialize(raw, maxSizeBytes) { | ||
| if (maxSizeBytes !== void 0) { | ||
| const byteLength = Buffer.byteLength(raw, "utf-8"); | ||
| if (byteLength > maxSizeBytes) { | ||
| throw new MessageSizeError(byteLength, maxSizeBytes); | ||
| } | ||
| } | ||
| try { | ||
| const parsed = JSON.parse(raw); | ||
| return sanitizeObjectWithDepthCheck(parsed, 0); | ||
| } catch (error) { | ||
| if (error instanceof MessageValidationError || error instanceof MessageSizeError) { | ||
| throw error; | ||
| } | ||
| throw new MessageValidationError("Invalid JSON"); | ||
| } | ||
| } | ||
| function sanitizeObjectWithDepthCheck(value, depth) { | ||
| if (depth > MAX_DEPTH) { | ||
| throw new MessageValidationError(`Message exceeds maximum depth of ${MAX_DEPTH}`); | ||
| } | ||
| if (value === null || value === void 0) { | ||
| return value; | ||
| } | ||
| if (typeof value !== "object") { | ||
| return value; | ||
| } | ||
| if (Array.isArray(value)) { | ||
| return value.map((item) => sanitizeObjectWithDepthCheck(item, depth + 1)); | ||
| } | ||
| const result = /* @__PURE__ */ Object.create(null); | ||
| for (const key of Object.keys(value)) { | ||
| if (!DANGEROUS_KEYS.has(key)) { | ||
| result[key] = sanitizeObjectWithDepthCheck(value[key], depth + 1); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| function safeSerialize(value) { | ||
| return JSON.stringify(value, (key, val) => { | ||
| if (DANGEROUS_KEYS.has(key)) { | ||
| return void 0; | ||
| } | ||
| return val; | ||
| }); | ||
| } | ||
| function sanitizeObject(value, depth = 0) { | ||
| if (depth > MAX_DEPTH) { | ||
| return void 0; | ||
| } | ||
| if (value === null || value === void 0) { | ||
| return value; | ||
| } | ||
| if (typeof value !== "object") { | ||
| return value; | ||
| } | ||
| if (Array.isArray(value)) { | ||
| return value.map((item) => sanitizeObject(item, depth + 1)); | ||
| } | ||
| const result = /* @__PURE__ */ Object.create(null); | ||
| for (const key of Object.keys(value)) { | ||
| if (!DANGEROUS_KEYS.has(key)) { | ||
| result[key] = sanitizeObject(value[key], depth + 1); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| // libs/core/src/adapters/worker-pool/worker-script.ts | ||
| var STACK_TRACE_HARDENING_CODE = ` | ||
| (function() { | ||
| function __ag_redactStackString(stackStr) { | ||
| try { | ||
| if (typeof stackStr !== 'string' || !stackStr) return 'Error'; | ||
| var lines = String(stackStr).split('\\n'); | ||
| var header = lines[0] ? String(lines[0]) : 'Error'; | ||
| var frameCount = (lines.length > 1) ? (lines.length - 1) : 0; | ||
| var max = frameCount; | ||
| if (max > 25) max = 25; | ||
| var out = [header]; | ||
| for (var i = 0; i < max; i++) out.push(' at [REDACTED]'); | ||
| if (frameCount > max) out.push(' at [REDACTED]'); | ||
| return out.join('\\n'); | ||
| } catch (e) { | ||
| return 'Error'; | ||
| } | ||
| } | ||
| function __ag_prepareStackTrace(err, stack) { | ||
| try { | ||
| var name = (err && err.name) ? String(err.name) : 'Error'; | ||
| var message = (err && err.message) ? String(err.message) : ''; | ||
| var header = message ? (name + ': ' + message) : name; | ||
| if (!stack || !stack.length) return header; | ||
| var lines = [header]; | ||
| var max = stack.length; | ||
| if (max > 25) max = 25; | ||
| for (var i = 0; i < max; i++) { | ||
| lines.push(' at [REDACTED]'); | ||
| } | ||
| if (stack.length > max) { | ||
| lines.push(' at [REDACTED]'); | ||
| } | ||
| return lines.join('\\n'); | ||
| } catch (e) { | ||
| return 'Error'; | ||
| } | ||
| } | ||
| function __ag_lockStackGetter(proto) { | ||
| if (!proto) return; | ||
| try { | ||
| var desc = Object.getOwnPropertyDescriptor(proto, 'stack'); | ||
| if (!desc || typeof desc.get !== 'function') return; | ||
| var origGet = desc.get; | ||
| var origSet = desc.set; | ||
| Object.defineProperty(proto, 'stack', { | ||
| get: function() { | ||
| try { | ||
| return __ag_redactStackString(origGet.call(this)); | ||
| } catch (e) { | ||
| return 'Error'; | ||
| } | ||
| }, | ||
| set: function(v) { | ||
| try { | ||
| if (typeof origSet === 'function') return origSet.call(this, v); | ||
| } catch (e) {} | ||
| }, | ||
| configurable: false, | ||
| enumerable: false | ||
| }); | ||
| } catch (e) {} | ||
| } | ||
| function __ag_lockPrepareStackTrace(ErrCtor) { | ||
| if (!ErrCtor) return; | ||
| try { | ||
| Object.defineProperty(ErrCtor, 'prepareStackTrace', { | ||
| value: __ag_prepareStackTrace, | ||
| writable: false, | ||
| configurable: false, | ||
| enumerable: false | ||
| }); | ||
| } catch (e) {} | ||
| try { | ||
| Object.defineProperty(ErrCtor, 'stackTraceLimit', { | ||
| value: 25, | ||
| writable: false, | ||
| configurable: false, | ||
| enumerable: false | ||
| }); | ||
| } catch (e) {} | ||
| } | ||
| __ag_lockStackGetter(Error && Error.prototype); | ||
| __ag_lockPrepareStackTrace(Error); | ||
| __ag_lockPrepareStackTrace(EvalError); | ||
| __ag_lockPrepareStackTrace(RangeError); | ||
| __ag_lockPrepareStackTrace(ReferenceError); | ||
| __ag_lockPrepareStackTrace(SyntaxError); | ||
| __ag_lockPrepareStackTrace(TypeError); | ||
| __ag_lockPrepareStackTrace(URIError); | ||
| try { | ||
| if (typeof AggregateError !== 'undefined') __ag_lockPrepareStackTrace(AggregateError); | ||
| } catch (e) {} | ||
| })(); | ||
| `.trim(); | ||
| var STACK_TRACE_HARDENING_SCRIPT = new import_vm.default.Script(STACK_TRACE_HARDENING_CODE); | ||
| var CODE_GENERATION_VIOLATION_DETECTOR_CODE = ` | ||
| (function() { | ||
| var __ag_report = (typeof __ag_reportViolation__ === 'function') ? __ag_reportViolation__ : null; | ||
| function __ag_reportOnce(kind) { | ||
| try { | ||
| if (__ag_report) __ag_report(kind); | ||
| } catch (e) {} | ||
| } | ||
| // Capture intrinsics so later global sanitization can't break the proxy handler. | ||
| var __ag_Reflect = (typeof Reflect !== 'undefined') ? Reflect : null; | ||
| var __ag_Proxy = (typeof Proxy !== 'undefined') ? Proxy : null; | ||
| var __ag_Object = (typeof Object !== 'undefined') ? Object : null; | ||
| function __ag_wrapCtor(Ctor, kind) { | ||
| if (!Ctor || !__ag_Proxy || !__ag_Reflect || !__ag_Object) return; | ||
| try { | ||
| var proxy = new __ag_Proxy(Ctor, { | ||
| apply: function(target, thisArg, args) { | ||
| __ag_reportOnce(kind); | ||
| return __ag_Reflect.apply(target, thisArg, args); | ||
| }, | ||
| construct: function(target, args, newTarget) { | ||
| __ag_reportOnce(kind); | ||
| return __ag_Reflect.construct(target, args, newTarget); | ||
| } | ||
| }); | ||
| try { | ||
| if (Ctor.prototype) { | ||
| __ag_Object.defineProperty(Ctor.prototype, 'constructor', { | ||
| value: proxy, | ||
| writable: false, | ||
| configurable: false, | ||
| enumerable: false | ||
| }); | ||
| } | ||
| } catch (e) {} | ||
| } catch (e) {} | ||
| } | ||
| try { __ag_wrapCtor(Function, 'CODE_GENERATION'); } catch (e) {} | ||
| try { __ag_wrapCtor((async function(){}).constructor, 'CODE_GENERATION'); } catch (e) {} | ||
| try { __ag_wrapCtor((function*(){}).constructor, 'CODE_GENERATION'); } catch (e) {} | ||
| try { __ag_wrapCtor((async function*(){}).constructor, 'CODE_GENERATION'); } catch (e) {} | ||
| })(); | ||
| `.trim(); | ||
| var CODE_GENERATION_VIOLATION_DETECTOR_SCRIPT = new import_vm.default.Script(CODE_GENERATION_VIOLATION_DETECTOR_CODE); | ||
| var port = import_worker_threads.parentPort; | ||
| if (!port) { | ||
| throw new Error("worker-script.ts must run inside a worker thread"); | ||
| } | ||
| var DANGEROUS_GLOBALS = [ | ||
| "parentPort", | ||
| "workerData", | ||
| "threadId", | ||
| "isMainThread", | ||
| "MessagePort", | ||
| "MessageChannel", | ||
| "BroadcastChannel", | ||
| "Worker", | ||
| "SharedArrayBuffer", | ||
| "Atomics" | ||
| ]; | ||
| for (const name of DANGEROUS_GLOBALS) { | ||
| try { | ||
| Object.defineProperty(globalThis, name, { | ||
| value: void 0, | ||
| writable: false, | ||
| configurable: false | ||
| }); | ||
| } catch { | ||
| } | ||
| } | ||
| var currentExecution = null; | ||
| var pendingToolCalls = /* @__PURE__ */ new Map(); | ||
| port.on("message", async (raw) => { | ||
| try { | ||
| const msg = safeDeserialize(raw); | ||
| switch (msg.type) { | ||
| case "execute": | ||
| await handleExecute(msg); | ||
| break; | ||
| case "tool-response": | ||
| handleToolResponse(msg); | ||
| break; | ||
| case "memory-report": | ||
| handleMemoryReport(); | ||
| break; | ||
| case "abort": | ||
| handleAbort(msg.requestId); | ||
| break; | ||
| case "terminate": | ||
| handleTerminate(msg.graceful); | ||
| break; | ||
| default: | ||
| console.error("Unknown message type:", msg.type); | ||
| } | ||
| } catch (error) { | ||
| console.error("Worker message handler error:", error); | ||
| } | ||
| }); | ||
| async function handleExecute(msg) { | ||
| const startTime = Date.now(); | ||
| currentExecution = { | ||
| id: msg.requestId, | ||
| aborted: false, | ||
| config: msg.config, | ||
| stats: { | ||
| duration: 0, | ||
| toolCallCount: 0, | ||
| iterationCount: 0, | ||
| startTime, | ||
| endTime: 0 | ||
| } | ||
| }; | ||
| try { | ||
| const sandbox = createSandbox(msg.requestId, msg.config); | ||
| const context = import_vm.default.createContext(sandbox, { | ||
| codeGeneration: { strings: false, wasm: false } | ||
| }); | ||
| const isStrictOrSecure = msg.config.securityLevel === "STRICT" || msg.config.securityLevel === "SECURE"; | ||
| const policyViolation = {}; | ||
| const shouldHardenStacks = msg.config.sanitizeStackTraces ?? true; | ||
| if (shouldHardenStacks) { | ||
| try { | ||
| STACK_TRACE_HARDENING_SCRIPT.runInContext(context); | ||
| } catch { | ||
| } | ||
| } | ||
| if (isStrictOrSecure) { | ||
| try { | ||
| Object.defineProperty(context, "__ag_reportViolation__", { | ||
| value: (type) => { | ||
| if (!policyViolation.type) policyViolation.type = String(type); | ||
| }, | ||
| writable: false, | ||
| configurable: false, | ||
| enumerable: false | ||
| }); | ||
| CODE_GENERATION_VIOLATION_DETECTOR_SCRIPT.runInContext(context); | ||
| } catch { | ||
| } | ||
| } | ||
| const wrappedCode = "(async () => {\n" + msg.code + '\nreturn typeof __ag_main === "function" ? await __ag_main() : undefined;\n})();'; | ||
| const script = new import_vm.default.Script(wrappedCode, { | ||
| filename: "agentscript.js" | ||
| }); | ||
| const result = await script.runInContext(context, { | ||
| timeout: msg.config.timeout, | ||
| breakOnSigint: true | ||
| }); | ||
| currentExecution.stats.endTime = Date.now(); | ||
| currentExecution.stats.duration = currentExecution.stats.endTime - startTime; | ||
| if (isStrictOrSecure && policyViolation.type) { | ||
| sendMessage({ | ||
| type: "result", | ||
| requestId: msg.requestId, | ||
| success: false, | ||
| error: { | ||
| name: "SecurityViolationError", | ||
| message: "Blocked operation: security policy violation", | ||
| code: "SECURITY_VIOLATION" | ||
| }, | ||
| stats: currentExecution.stats | ||
| }); | ||
| return; | ||
| } | ||
| sendMessage({ | ||
| type: "result", | ||
| requestId: msg.requestId, | ||
| success: true, | ||
| value: sanitizeObject(result), | ||
| stats: currentExecution.stats | ||
| }); | ||
| } catch (error) { | ||
| if (currentExecution) { | ||
| currentExecution.stats.endTime = Date.now(); | ||
| currentExecution.stats.duration = currentExecution.stats.endTime - startTime; | ||
| } | ||
| sendMessage({ | ||
| type: "result", | ||
| requestId: msg.requestId, | ||
| success: false, | ||
| error: serializeError(error, msg.config.sanitizeStackTraces), | ||
| stats: currentExecution?.stats ?? { | ||
| duration: Date.now() - startTime, | ||
| toolCallCount: 0, | ||
| iterationCount: 0, | ||
| startTime, | ||
| endTime: Date.now() | ||
| } | ||
| }); | ||
| } finally { | ||
| for (const [callId, pending] of pendingToolCalls) { | ||
| if (callId.startsWith(`${msg.requestId}-`)) { | ||
| pending.reject(new Error("Execution ended")); | ||
| pendingToolCalls.delete(callId); | ||
| } | ||
| } | ||
| currentExecution = null; | ||
| } | ||
| } | ||
| function handleToolResponse(msg) { | ||
| const pending = pendingToolCalls.get(msg.callId); | ||
| if (!pending) { | ||
| console.warn("Received response for unknown tool call:", msg.callId); | ||
| return; | ||
| } | ||
| pendingToolCalls.delete(msg.callId); | ||
| if (msg.error) { | ||
| const error = new Error(msg.error.message); | ||
| error.name = msg.error.name; | ||
| pending.reject(error); | ||
| } else { | ||
| pending.resolve(sanitizeObject(msg.result)); | ||
| } | ||
| } | ||
| function handleMemoryReport() { | ||
| const usage = process.memoryUsage(); | ||
| sendMessage({ | ||
| type: "memory-report-result", | ||
| usage: { | ||
| rss: usage.rss, | ||
| heapTotal: usage.heapTotal, | ||
| heapUsed: usage.heapUsed, | ||
| external: usage.external, | ||
| arrayBuffers: usage.arrayBuffers | ||
| } | ||
| }); | ||
| } | ||
| function handleAbort(requestId) { | ||
| if (currentExecution && currentExecution.id === requestId) { | ||
| currentExecution.aborted = true; | ||
| } | ||
| for (const [callId, pending] of pendingToolCalls) { | ||
| if (callId.startsWith(`${requestId}-`)) { | ||
| pending.reject(new Error("Execution aborted")); | ||
| pendingToolCalls.delete(callId); | ||
| } | ||
| } | ||
| } | ||
| function handleTerminate(graceful) { | ||
| if (graceful && currentExecution) { | ||
| currentExecution.aborted = true; | ||
| } else { | ||
| process.exit(0); | ||
| } | ||
| } | ||
| function getGlobalValue(name, requestId, config) { | ||
| switch (name) { | ||
| case "__safe_callTool": | ||
| case "callTool": | ||
| return createProxiedCallTool(requestId, config); | ||
| case "__safe_forOf": | ||
| return createSafeForOf(); | ||
| case "__safe_for": | ||
| return createSafeFor(); | ||
| case "__safe_while": | ||
| case "__safe_doWhile": | ||
| return createSafeWhile(); | ||
| case "__maxIterations": | ||
| return config.maxIterations ?? 1e4; | ||
| case "console": | ||
| case "__safe_console": | ||
| return createSafeConsole(requestId, config); | ||
| // Core built-in objects (always safe) | ||
| case "Math": | ||
| return Math; | ||
| case "JSON": | ||
| return JSON; | ||
| case "Object": | ||
| return Object; | ||
| case "Array": | ||
| return Array; | ||
| case "String": | ||
| return String; | ||
| case "Number": | ||
| return Number; | ||
| case "Date": | ||
| return Date; | ||
| // Safe standard globals | ||
| case "undefined": | ||
| return void 0; | ||
| case "NaN": | ||
| return NaN; | ||
| case "Infinity": | ||
| return Infinity; | ||
| // Utility functions (STANDARD level and above) | ||
| case "parseInt": | ||
| return parseInt; | ||
| case "parseFloat": | ||
| return parseFloat; | ||
| case "isNaN": | ||
| return isNaN; | ||
| case "isFinite": | ||
| return isFinite; | ||
| case "encodeURI": | ||
| return encodeURI; | ||
| case "decodeURI": | ||
| return decodeURI; | ||
| case "encodeURIComponent": | ||
| return encodeURIComponent; | ||
| case "decodeURIComponent": | ||
| return decodeURIComponent; | ||
| default: | ||
| return void 0; | ||
| } | ||
| } | ||
| function getAllowedGlobalsForSecurityLevel(securityLevel) { | ||
| const strictGlobals = [ | ||
| "callTool", | ||
| "__safe_callTool", | ||
| "Math", | ||
| "JSON", | ||
| "Array", | ||
| "Object", | ||
| "String", | ||
| "Number", | ||
| "Date", | ||
| "undefined", | ||
| "NaN", | ||
| "Infinity", | ||
| "__safe_forOf", | ||
| "__safe_for", | ||
| "__safe_while", | ||
| "__safe_doWhile", | ||
| "__maxIterations" | ||
| ]; | ||
| const secureGlobals = [ | ||
| ...strictGlobals, | ||
| "parseInt", | ||
| "parseFloat", | ||
| "isNaN", | ||
| "isFinite", | ||
| "encodeURI", | ||
| "decodeURI", | ||
| "encodeURIComponent", | ||
| "decodeURIComponent" | ||
| ]; | ||
| const standardGlobals = [...secureGlobals]; | ||
| const permissiveGlobals = [...standardGlobals, "console", "__safe_console"]; | ||
| switch (securityLevel) { | ||
| case "PERMISSIVE": | ||
| return permissiveGlobals; | ||
| case "STANDARD": | ||
| return standardGlobals; | ||
| case "SECURE": | ||
| return secureGlobals; | ||
| case "STRICT": | ||
| default: | ||
| return strictGlobals; | ||
| } | ||
| } | ||
| function createSandbox(requestId, config) { | ||
| const sandbox = /* @__PURE__ */ Object.create(null); | ||
| const allowedGlobals = getAllowedGlobalsForSecurityLevel(config.securityLevel); | ||
| for (const name of allowedGlobals) { | ||
| const value = getGlobalValue(name, requestId, config); | ||
| if (value !== void 0 || name === "undefined") { | ||
| sandbox[name] = value; | ||
| } | ||
| } | ||
| if (config.globals) { | ||
| for (const [key, value] of Object.entries(config.globals)) { | ||
| if (typeof value !== "function") { | ||
| sandbox[key] = sanitizeObject(value); | ||
| } | ||
| } | ||
| } | ||
| return sandbox; | ||
| } | ||
| function createProxiedCallTool(requestId, config) { | ||
| return async function __safe_callTool(toolName, args) { | ||
| if (currentExecution?.aborted) { | ||
| throw new Error("Execution aborted"); | ||
| } | ||
| if (currentExecution) { | ||
| currentExecution.stats.toolCallCount++; | ||
| } | ||
| if (currentExecution && currentExecution.stats.toolCallCount > config.maxToolCalls) { | ||
| throw new Error( | ||
| `Maximum tool call limit exceeded (${config.maxToolCalls}). This limit prevents runaway script execution.` | ||
| ); | ||
| } | ||
| if (typeof toolName !== "string" || !toolName) { | ||
| throw new TypeError("Tool name must be a non-empty string"); | ||
| } | ||
| if (typeof args !== "object" || args === null || Array.isArray(args)) { | ||
| throw new TypeError("Tool arguments must be an object"); | ||
| } | ||
| const callId = `${requestId}-${Date.now()}-${import_crypto.default.randomUUID()}`; | ||
| return new Promise((resolve, reject) => { | ||
| pendingToolCalls.set(callId, { resolve, reject }); | ||
| sendMessage({ | ||
| type: "tool-call", | ||
| requestId, | ||
| callId, | ||
| toolName, | ||
| args: sanitizeObject(args) | ||
| }); | ||
| }); | ||
| }; | ||
| } | ||
| function createSafeForOf() { | ||
| return function* __safe_forOf(iterable) { | ||
| let iterations = 0; | ||
| for (const item of iterable) { | ||
| if (currentExecution?.aborted) { | ||
| throw new Error("Execution aborted"); | ||
| } | ||
| iterations++; | ||
| if (currentExecution) { | ||
| currentExecution.stats.iterationCount++; | ||
| } | ||
| const maxIterations = currentExecution?.config.maxIterations ?? 1e4; | ||
| if (iterations > maxIterations) { | ||
| throw new Error( | ||
| `Maximum iteration limit exceeded (${maxIterations}). This limit prevents infinite loops.` | ||
| ); | ||
| } | ||
| yield item; | ||
| } | ||
| }; | ||
| } | ||
| function createSafeFor() { | ||
| return function __safe_for(init, test, update, body) { | ||
| let iterations = 0; | ||
| init(); | ||
| while (test()) { | ||
| if (currentExecution?.aborted) { | ||
| throw new Error("Execution aborted"); | ||
| } | ||
| iterations++; | ||
| if (currentExecution) { | ||
| currentExecution.stats.iterationCount++; | ||
| } | ||
| const maxIterations = currentExecution?.config.maxIterations ?? 1e4; | ||
| if (iterations > maxIterations) { | ||
| throw new Error( | ||
| `Maximum iteration limit exceeded (${maxIterations}). This limit prevents infinite loops.` | ||
| ); | ||
| } | ||
| body(); | ||
| update(); | ||
| } | ||
| }; | ||
| } | ||
| function createSafeWhile() { | ||
| return function __safe_while(test, body) { | ||
| let iterations = 0; | ||
| while (test()) { | ||
| if (currentExecution?.aborted) { | ||
| throw new Error("Execution aborted"); | ||
| } | ||
| iterations++; | ||
| if (currentExecution) { | ||
| currentExecution.stats.iterationCount++; | ||
| } | ||
| const maxIterations = currentExecution?.config.maxIterations ?? 1e4; | ||
| if (iterations > maxIterations) { | ||
| throw new Error( | ||
| `Maximum iteration limit exceeded (${maxIterations}). This limit prevents infinite loops.` | ||
| ); | ||
| } | ||
| body(); | ||
| } | ||
| }; | ||
| } | ||
| function createSafeConsole(requestId, config) { | ||
| let totalBytes = 0; | ||
| let callCount = 0; | ||
| function safeLog(level, args) { | ||
| callCount++; | ||
| if (callCount > config.maxConsoleCalls) { | ||
| throw new Error(`Console call limit exceeded (${config.maxConsoleCalls})`); | ||
| } | ||
| const serialized = args.map((a) => { | ||
| try { | ||
| return JSON.stringify(sanitizeObject(a)); | ||
| } catch { | ||
| return String(a); | ||
| } | ||
| }); | ||
| const bytes = serialized.reduce((sum, s) => sum + (s?.length ?? 0), 0); | ||
| totalBytes += bytes; | ||
| if (totalBytes > config.maxConsoleOutputBytes) { | ||
| throw new Error(`Console output limit exceeded (${config.maxConsoleOutputBytes} bytes)`); | ||
| } | ||
| sendMessage({ | ||
| type: "console", | ||
| requestId, | ||
| level, | ||
| args: serialized | ||
| }); | ||
| } | ||
| return { | ||
| log: (...args) => safeLog("log", args), | ||
| warn: (...args) => safeLog("warn", args), | ||
| error: (...args) => safeLog("error", args), | ||
| info: (...args) => safeLog("info", args) | ||
| }; | ||
| } | ||
| function sendMessage(msg) { | ||
| if (!port) { | ||
| throw new Error("Worker port not initialized"); | ||
| } | ||
| port.postMessage(safeSerialize(msg)); | ||
| } | ||
| function serializeError(error, sanitizeStackTraces) { | ||
| if (typeof error === "string") { | ||
| return { name: "Error", message: error }; | ||
| } | ||
| const err = error; | ||
| const serialized = { | ||
| name: err.name || "Error", | ||
| message: err.message || "Unknown error" | ||
| }; | ||
| if (err.code) { | ||
| serialized.code = err.code; | ||
| } | ||
| if (err.stack && !sanitizeStackTraces) { | ||
| serialized.stack = err.stack; | ||
| } else if (err.stack && sanitizeStackTraces) { | ||
| serialized.stack = err.stack.split("\n").slice(0, 5).map((line) => line.replace(/\(.*?:\d+:\d+\)/g, "(...)")).join("\n"); | ||
| } | ||
| return serialized; | ||
| } | ||
| sendMessage({ type: "ready" }); |
@@ -30,2 +30,3 @@ /** | ||
| private initialized; | ||
| private readonly boundMemoryExceededHandler; | ||
| private _totalExecutions; | ||
@@ -32,0 +33,0 @@ private _successfulExecutions; |
+1
-0
@@ -51,2 +51,3 @@ /** | ||
| private readonly doubleVmConfig; | ||
| private readonly customGlobalNames; | ||
| private adapter?; | ||
@@ -53,0 +54,0 @@ constructor(options?: CreateEnclaveOptions); |
+5
-5
| { | ||
| "name": "@enclave-vm/core", | ||
| "version": "2.10.0", | ||
| "version": "2.10.1", | ||
| "description": "Sandbox runtime for secure JavaScript code execution", | ||
@@ -40,9 +40,9 @@ "author": "AgentFront <info@agentfront.dev>", | ||
| "dependencies": { | ||
| "@babel/standalone": "^7.28.6", | ||
| "@enclave-vm/types": "2.10.0", | ||
| "@enclave-vm/ast": "2.10.0", | ||
| "@babel/standalone": "^7.29.0", | ||
| "@enclave-vm/types": "2.10.1", | ||
| "@enclave-vm/ast": "2.10.1", | ||
| "acorn": "8.15.0", | ||
| "acorn-walk": "8.3.4", | ||
| "astring": "1.9.0", | ||
| "zod": "^4.1.13" | ||
| "zod": "^4.3.6" | ||
| }, | ||
@@ -49,0 +49,0 @@ "peerDependencies": { |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
1057372
4.05%64
3.23%29015
4.05%47
6.82%+ Added
+ Added
- Removed
- Removed
Updated
Updated
Updated
Updated