@blen/fedreg-mcp-server 2.2.1 → 2.2.3

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.
@@ -1,203 +1,389 @@
1
1
  import { spawn } from 'node:child_process';
2
- import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { existsSync, mkdtempSync, rmSync, writeFileSync, chmodSync } from 'node:fs';
3
3
  import { tmpdir } from 'node:os';
4
4
  import { join } from 'node:path';
5
+ import { log } from '../util/logger.js';
5
6
  import { preflight } from './policy.js';
7
+ import { DEFAULT_LIMITS, LOG_LINE_OVERHEAD, LOG_TRUNCATED, LogSink, MAX_ERROR_MESSAGE, boundMessage, checkRpcArgs, finishValue, policyMessage, resultTooLarge } from './limits.js';
6
8
  /**
7
- * Deno fallback sandbox. We launch `deno run --no-prompt <runner>` with NO
8
- * `--allow-*` flags, so Deno's deny-by-default grants no net/fs/env/ffi/subprocess
9
- * access, and bridge RPC over stdin/stdout using a length-prefixed JSON protocol.
9
+ * Deno sandbox.
10
+ *
11
+ * Boundary: Node host (owns the deadline, byte budgets, and the child's lifetime)
12
+ * → `deno run` of a fixed supervisor script with NO --allow-* flags (deny-by-default: no net, fs,
13
+ * env, ffi, subprocess), a minimal environment, and no user code on disk
14
+ * → a module Worker that receives the user code by message. Before user code runs, the worker's
15
+ * ambient globals that could reach the process or the protocol (`Deno`, `postMessage`, `fetch`,
16
+ * `Worker`, ...) are replaced with `undefined` and `console` is redirected to log messages.
17
+ *
18
+ * Protocol: the supervisor talks to the host over stdin/stdout with one JSON frame per line,
19
+ * prefixed by a random token the supervisor generates and announces before the worker exists.
20
+ * The worker never sees the token, so it cannot forge frames; any other stdout bytes are treated
21
+ * as untrusted log text. All child output is untrusted: frames are size-bounded and validated, the
22
+ * execution settles exactly once, and the process group is killed on every exit path. A frame can
23
+ * never cancel the host's deadline or its cleanup.
10
24
  */
11
25
  export class DenoRunner {
26
+ limits;
12
27
  kind = 'deno';
28
+ static supervisorPath;
29
+ constructor(limits = DEFAULT_LIMITS) {
30
+ this.limits = limits;
31
+ }
13
32
  async available() {
14
33
  return await new Promise(resolve => {
15
- const p = spawn('deno', ['--version'], { stdio: 'ignore' });
34
+ const p = spawn('deno', ['--version'], { stdio: 'ignore', env: childEnv() });
16
35
  p.on('error', () => resolve(false));
17
36
  p.on('exit', code => resolve(code === 0));
18
37
  });
19
38
  }
39
+ /** The supervisor holds no user data; it is written once per process, readable only by us. */
40
+ static supervisor() {
41
+ // Re-check on disk: a long-lived server's temp dir may be reaped by a tmp cleaner.
42
+ if (!DenoRunner.supervisorPath || !existsSync(DenoRunner.supervisorPath)) {
43
+ const dir = mkdtempSync(join(tmpdir(), 'fedreg-deno-'));
44
+ chmodSync(dir, 0o700);
45
+ const path = join(dir, 'supervisor.js');
46
+ writeFileSync(path, SUPERVISOR_SOURCE, { mode: 0o600 });
47
+ DenoRunner.supervisorPath = path;
48
+ process.once('exit', () => { try {
49
+ rmSync(dir, { recursive: true, force: true });
50
+ }
51
+ catch { /* ignore */ } });
52
+ }
53
+ return DenoRunner.supervisorPath;
54
+ }
20
55
  async execute(opts, rpc) {
21
56
  const started = Date.now();
57
+ const limits = { ...this.limits, ...(opts.limits ?? {}) };
58
+ const timeoutMs = opts.timeoutMs ?? 15_000;
59
+ const fail = (name, message, logs = []) => ({ ok: false, logs, error: { name, message }, durationMs: Date.now() - started });
22
60
  const policy = preflight(opts.code);
23
- if (!policy.ok) {
24
- return { ok: false, logs: [], error: { name: 'PolicyError', message: policy.errors.join('; ') }, durationMs: Date.now() - started };
61
+ if (!policy.ok)
62
+ return fail('PolicyError', policyMessage(policy.errors));
63
+ if (Buffer.byteLength(opts.code, 'utf8') > limits.maxCodeBytes)
64
+ return fail('CodeTooLarge', `Code exceeds ${limits.maxCodeBytes} bytes.`);
65
+ let child;
66
+ try {
67
+ child = spawn('deno', [
68
+ 'run', '--no-prompt', '--no-config', '--no-lock', '--no-remote', '--no-npm', '--quiet',
69
+ `--v8-flags=--max-old-space-size=${Math.max(16, opts.memoryMb ?? 64)}`,
70
+ DenoRunner.supervisor(),
71
+ ], { stdio: ['pipe', 'pipe', 'pipe'], env: childEnv(), detached: process.platform !== 'win32' });
25
72
  }
26
- const runner = buildDenoRunner(opts.code, opts.timeoutMs ?? 15_000, opts.bindings ?? []);
27
- // Write the runner to a temp file rather than piping it on stdin: `deno run -`
28
- // reads the program from stdin until EOF, but we keep stdin open as the RPC
29
- // channel, so it would never start. A file path leaves stdin free for RPC.
30
- const tmpDir = mkdtempSync(join(tmpdir(), 'fedreg-deno-'));
31
- const runnerPath = join(tmpDir, 'runner.ts');
32
- writeFileSync(runnerPath, runner);
33
- const cleanup = () => { try {
34
- rmSync(tmpDir, { recursive: true, force: true });
73
+ catch (err) {
74
+ return fail('SpawnError', err.message);
35
75
  }
36
- catch { /* ignore */ } };
37
- const child = spawn('deno', [
38
- 'run',
39
- '--no-prompt',
40
- runnerPath,
41
- ], { stdio: ['pipe', 'pipe', 'pipe'] });
42
- const logs = [];
43
- let stdoutBuf = Buffer.alloc(0);
44
- return await new Promise((resolve) => {
45
- const timeout = setTimeout(() => {
76
+ const logs = new LogSink(limits.maxLogBytes, limits.maxLogLines);
77
+ return await new Promise(resolve => {
78
+ let settled = false;
79
+ let token;
80
+ let partial = [];
81
+ let partialLen = 0;
82
+ let bufferedBytes = 0;
83
+ let pendingRpc = 0;
84
+ // Choosing the outcome and tearing down are separate: the first terminal event fixes the
85
+ // result, and the promise resolves once the child has exited (bounded wait).
86
+ let exited = false;
87
+ const exitWaiters = [];
88
+ child.once('close', () => { exited = true; for (const w of exitWaiters.splice(0))
89
+ w(); });
90
+ const settle = (result) => {
91
+ if (settled)
92
+ return;
93
+ settled = true;
94
+ clearTimeout(deadline);
95
+ const outcome = { ...result, logs: logs.lines(), durationMs: Date.now() - started };
96
+ killTree(child);
97
+ if (exited)
98
+ return resolve(outcome);
99
+ // Normally the child exits within milliseconds of the kill. If it has not after 2 s, kill
100
+ // again, log it, and return the result anyway.
101
+ const giveUp = setTimeout(() => {
102
+ log.error('sandbox.teardown_pending', { pid: child.pid });
103
+ killTree(child);
104
+ resolve(outcome);
105
+ }, 2000);
106
+ exitWaiters.push(() => { clearTimeout(giveUp); resolve(outcome); });
107
+ };
108
+ const deadline = setTimeout(() => settle({ ok: false, error: { name: 'TimeoutError', message: `Execution exceeded ${timeoutMs}ms` } }), timeoutMs);
109
+ child.on('error', err => settle({ ok: false, error: { name: 'SpawnError', message: err.message } }));
110
+ // 'close', not 'exit': stdout may still hold the final frame when the process exits.
111
+ child.on('close', code => settle({ ok: false, error: { name: 'ExitError', message: `The sandbox exited unexpectedly (code ${code}).` } }));
112
+ const send = (frame) => {
113
+ if (settled || !token)
114
+ return;
115
+ let line;
46
116
  try {
47
- child.kill('SIGKILL');
117
+ line = `${token}${JSON.stringify(frame)}\n`;
48
118
  }
49
- catch { /* ignore */ }
50
- cleanup();
51
- resolve({
52
- ok: false, logs,
53
- error: { name: 'TimeoutError', message: `Execution exceeded ${opts.timeoutMs ?? 15_000}ms` },
54
- durationMs: Date.now() - started,
55
- });
56
- }, (opts.timeoutMs ?? 15_000) + 1_000);
57
- child.stdout.on('data', async (chunk) => {
58
- stdoutBuf = Buffer.concat([stdoutBuf, chunk]);
59
- // length-prefixed JSON frames: 8-byte ascii hex length + payload
60
- while (stdoutBuf.length >= 9) {
61
- const lenHex = stdoutBuf.subarray(0, 8).toString('ascii');
62
- if (stdoutBuf[8] !== 0x0a) {
63
- logs.push(stdoutBuf.toString('utf8'));
64
- stdoutBuf = Buffer.alloc(0);
65
- break;
66
- }
67
- const len = parseInt(lenHex, 16);
68
- if (Number.isNaN(len))
69
- break;
70
- if (stdoutBuf.length < 9 + len)
71
- break;
72
- const payload = stdoutBuf.subarray(9, 9 + len).toString('utf8');
73
- stdoutBuf = stdoutBuf.subarray(9 + len);
74
- const msg = JSON.parse(payload);
75
- if (msg.kind === 'log') {
76
- logs.push(msg.text);
119
+ catch {
120
+ // An SDK result that cannot be serialized must still answer the call, or the sandbox waits for the deadline.
121
+ const f = frame;
122
+ if (f.t !== 'rpc-result')
123
+ return;
124
+ line = `${token}${JSON.stringify({ t: 'rpc-result', id: f.id, ok: false, error: { name: 'TypeError', message: 'The SDK result is not JSON-serializable.' } })}\n`;
125
+ }
126
+ try {
127
+ child.stdin.write(line);
128
+ }
129
+ catch { /* child gone; exit handler settles */ }
130
+ };
131
+ const onFrame = async (raw) => {
132
+ let msg;
133
+ try {
134
+ msg = JSON.parse(raw);
135
+ }
136
+ catch {
137
+ return settle({ ok: false, error: { name: 'SandboxProtocolError', message: 'The sandbox sent a malformed frame.' } });
138
+ }
139
+ if (msg.t === 'log' && typeof msg.text === 'string')
140
+ return logs.push(msg.text);
141
+ if (msg.t === 'rpc' && Number.isSafeInteger(msg.id) && typeof msg.binding === 'string'
142
+ && Array.isArray(msg.path) && Array.isArray(msg.args)) {
143
+ if (pendingRpc >= limits.maxPendingRpc) {
144
+ return send({ t: 'rpc-result', id: msg.id, ok: false, error: { name: 'TooManyPendingCalls', message: `At most ${limits.maxPendingRpc} SDK calls may be pending at once.` } });
77
145
  }
78
- else if (msg.kind === 'rpc') {
146
+ const tooBig = checkRpcArgs(msg.args, limits);
147
+ if (tooBig)
148
+ return send({ t: 'rpc-result', id: msg.id, ok: false, error: tooBig });
149
+ pendingRpc++;
150
+ try {
79
151
  const res = await rpc.dispatch({ binding: msg.binding, path: msg.path, args: msg.args });
80
- writeFrame(child.stdin, { kind: 'rpc-result', id: msg.id, ok: res.ok, value: res.value, error: res.error });
152
+ send({ t: 'rpc-result', id: msg.id, ok: res.ok, value: res.value, error: res.error });
81
153
  }
82
- else if (msg.kind === 'result') {
83
- clearTimeout(timeout);
84
- try {
85
- child.stdin.end();
86
- }
87
- catch { /* ignore */ }
88
- resolve({
89
- ok: msg.ok,
90
- logs,
91
- value: msg.value,
92
- error: msg.error,
93
- durationMs: Date.now() - started,
94
- });
154
+ finally {
155
+ pendingRpc--;
95
156
  }
157
+ return;
96
158
  }
97
- });
98
- child.stderr.on('data', (b) => logs.push(b.toString('utf8')));
99
- child.on('error', err => {
100
- clearTimeout(timeout);
101
- cleanup();
102
- resolve({ ok: false, logs, error: { name: 'SpawnError', message: err.message }, durationMs: Date.now() - started });
103
- });
104
- child.on('exit', code => {
105
- cleanup();
106
- if (code !== 0 && code !== null) {
107
- clearTimeout(timeout);
108
- resolve({ ok: false, logs, error: { name: 'ExitError', message: `deno exited with ${code}` }, durationMs: Date.now() - started });
159
+ if (msg.t === 'done') {
160
+ if (msg.ok === true && typeof msg.json === 'string')
161
+ return settle(finishValue(msg.json, limits));
162
+ if (msg.tooLarge === true && typeof msg.size === 'number')
163
+ return settle({ ok: false, error: resultTooLarge(msg.size, limits) });
164
+ const e = (msg.error ?? {});
165
+ return settle({
166
+ ok: false,
167
+ error: {
168
+ name: typeof e.name === 'string' ? e.name.slice(0, 100) : 'Error',
169
+ message: typeof e.message === 'string' ? boundMessage(e.message) : 'Execution failed',
170
+ ...(typeof e.status === 'number' ? { status: e.status } : {}),
171
+ },
172
+ });
173
+ }
174
+ return settle({ ok: false, error: { name: 'SandboxProtocolError', message: 'The sandbox sent an unexpected frame.' } });
175
+ };
176
+ child.stdout.setEncoding('utf8');
177
+ child.stdout.on('data', (chunk) => {
178
+ if (settled)
179
+ return;
180
+ bufferedBytes += Buffer.byteLength(chunk, 'utf8');
181
+ if (bufferedBytes > limits.maxStdoutBytes) {
182
+ return settle({ ok: false, error: { name: 'OutputTooLarge', message: `The sandbox produced more than ${limits.maxStdoutBytes} bytes of output.` } });
183
+ }
184
+ // Split only the new chunk, so a long unterminated frame is never rescanned or re-flattened.
185
+ const segments = chunk.split('\n');
186
+ const tail = segments.pop();
187
+ for (const seg of segments) {
188
+ if (settled)
189
+ return;
190
+ const line = partial.length ? partial.join('') + seg : seg;
191
+ partial = [];
192
+ partialLen = 0;
193
+ if (!token) {
194
+ // The supervisor's first line announces the frame token; nothing else may precede it.
195
+ const m = /^FEDREG-SANDBOX ([0-9a-f]{64})$/.exec(line);
196
+ if (!m)
197
+ return settle({ ok: false, error: { name: 'SandboxProtocolError', message: 'The sandbox did not start correctly.' } });
198
+ token = m[1];
199
+ send({ t: 'start', code: opts.code, bindings: opts.bindings ?? [], limits: {
200
+ maxLogBytes: limits.maxLogBytes, maxLogLines: limits.maxLogLines, logLineOverhead: LOG_LINE_OVERHEAD,
201
+ logTruncated: LOG_TRUNCATED, maxRpcArgBytes: limits.maxRpcArgBytes, maxResultBytes: limits.maxResultBytes,
202
+ maxError: MAX_ERROR_MESSAGE,
203
+ } });
204
+ continue;
205
+ }
206
+ if (line.startsWith(token)) {
207
+ onFrame(line.slice(token.length)).catch(err => settle({ ok: false, error: { name: 'SandboxProtocolError', message: boundMessage(String(err?.message ?? err)) } }));
208
+ }
209
+ else if (line.length)
210
+ logs.push(line);
211
+ }
212
+ if (settled)
213
+ return;
214
+ partial.push(tail);
215
+ partialLen += tail.length;
216
+ if (partialLen > limits.maxFrameBytes) {
217
+ settle({ ok: false, error: { name: 'OutputTooLarge', message: `A sandbox message exceeded ${limits.maxFrameBytes} bytes.` } });
109
218
  }
110
219
  });
220
+ child.stderr.setEncoding('utf8');
221
+ child.stderr.on('data', (chunk) => { if (!settled)
222
+ logs.push(chunk.trimEnd()); });
223
+ child.stdin.on('error', () => { });
111
224
  });
112
225
  }
113
226
  }
114
- function writeFrame(stream, obj) {
115
- const payload = JSON.stringify(obj);
116
- const len = Buffer.byteLength(payload, 'utf8').toString(16).padStart(8, '0');
117
- stream.write(len + '\n' + payload);
227
+ /** Only what Deno needs to start; never the server's secrets. */
228
+ function childEnv() {
229
+ const env = { NO_COLOR: '1', DENO_NO_UPDATE_CHECK: '1', DENO_NO_PROMPT: '1' };
230
+ for (const k of ['PATH', 'HOME', 'DENO_DIR', 'TMPDIR', 'SystemRoot', 'USERPROFILE', 'LOCALAPPDATA']) {
231
+ if (process.env[k])
232
+ env[k] = process.env[k];
233
+ }
234
+ return env;
118
235
  }
119
- // `bindings` is interpolated into the generated source via JSON.stringify; it is safe
120
- // only because names are pre-validated as JS identifiers by getSources()
121
- // (src/sdk/sources/index.ts). Do NOT pass unvalidated strings here.
122
- export function buildDenoRunner(userCode, timeoutMs, bindings) {
123
- // Runs inside deno. Talks to host over stdin/stdout with the same framing.
124
- return `
125
- const enc = new TextEncoder();
126
- const dec = new TextDecoder();
127
-
128
- function writeFrame(obj) {
129
- const s = JSON.stringify(obj);
130
- const len = (new TextEncoder().encode(s)).byteLength.toString(16).padStart(8, '0');
131
- Deno.stdout.writeSync(enc.encode(len + '\\n' + s));
236
+ /** Kill the child and anything it started. POSIX: the whole process group. */
237
+ function killTree(child) {
238
+ try {
239
+ child.stdin.destroy();
240
+ }
241
+ catch { /* ignore */ }
242
+ if (child.exitCode !== null || child.signalCode !== null)
243
+ return;
244
+ if (process.platform !== 'win32' && child.pid) {
245
+ try {
246
+ process.kill(-child.pid, 'SIGKILL');
247
+ return;
248
+ }
249
+ catch { /* fall through */ }
250
+ }
251
+ try {
252
+ child.kill('SIGKILL');
253
+ }
254
+ catch { /* ignore */ }
132
255
  }
256
+ /**
257
+ * Runs in Deno with no permissions. Holds no user data until the start frame arrives over stdin.
258
+ * Binding names come from the host (pre-validated identifiers) and are only used as object keys.
259
+ */
260
+ export const SUPERVISOR_SOURCE = String.raw `
261
+ const enc = new TextEncoder();
262
+ const bytes = new Uint8Array(32);
263
+ crypto.getRandomValues(bytes);
264
+ const TOKEN = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
265
+ const writeLine = (s) => { const b = enc.encode(s + '\n'); let o = 0; while (o < b.length) o += Deno.stdout.writeSync(b.subarray(o)); };
266
+ const frame = (obj) => writeLine(TOKEN + JSON.stringify(obj));
267
+ writeLine('FEDREG-SANDBOX ' + TOKEN);
133
268
 
134
- let inbuf = new Uint8Array(0);
269
+ const WORKER_SOURCE = ${'`'}
270
+ // Trusted primitives, captured before user code exists: budgets below use these, so user code that
271
+ // replaces JSON.stringify, TextEncoder or Promise.prototype.then cannot push oversized data out.
272
+ const post = self.postMessage.bind(self);
273
+ const listen = self.addEventListener.bind(self);
274
+ const S = JSON.stringify, P = JSON.parse, Str = String, apply = Reflect.apply, then = Promise.prototype.then;
275
+ const encoder = new TextEncoder(), encode = TextEncoder.prototype.encode, sl = String.prototype.slice;
276
+ // The intrinsic %TypedArray%.prototype.byteLength getter, captured: user code may redefine
277
+ // Uint8Array.prototype.length, but cannot change a getter we already hold.
278
+ const byteLength = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Uint8Array.prototype), 'byteLength').get;
279
+ const bytes = (s) => apply(byteLength, apply(encode, encoder, [s]), []);
280
+ const cut = (s, n) => s.length > n ? apply(sl, s, [0, n]) : s;
281
+ let started = false;
135
282
  const pending = new Map();
136
283
  let nextId = 1;
137
-
138
- async function readLoop() {
139
- const reader = Deno.stdin.readable.getReader();
140
- while (true) {
141
- const { value, done } = await reader.read();
142
- if (done) return;
143
- const merged = new Uint8Array(inbuf.length + value.length);
144
- merged.set(inbuf); merged.set(value, inbuf.length);
145
- inbuf = merged;
146
- while (inbuf.length >= 9) {
147
- const lenHex = dec.decode(inbuf.subarray(0, 8));
148
- const len = parseInt(lenHex, 16);
149
- if (isNaN(len)) { inbuf = new Uint8Array(0); break; }
150
- if (inbuf.length < 9 + len) break;
151
- const payload = dec.decode(inbuf.subarray(9, 9 + len));
152
- inbuf = inbuf.subarray(9 + len);
153
- const msg = JSON.parse(payload);
154
- if (msg.kind === 'rpc-result') {
155
- const cb = pending.get(msg.id);
156
- if (cb) { pending.delete(msg.id); cb(msg); }
157
- }
158
- }
284
+ listen('message', (ev) => {
285
+ const m = ev.data;
286
+ if (m && m.t === 'rpc-result') {
287
+ const p = pending.get(m.id);
288
+ if (!p) return;
289
+ pending.delete(m.id);
290
+ if (m.ok) p.resolve(m.value);
291
+ else { const e = new Error(String(m.error?.message ?? 'SDK call failed')); e.name = String(m.error?.name ?? 'Error'); if (typeof m.error?.status === 'number') e.status = m.error.status; p.reject(e); }
292
+ return;
159
293
  }
160
- }
161
- readLoop();
162
-
294
+ if (!m || m.t !== 'start' || started) return;
295
+ started = true;
296
+ run(String(m.code), Array.isArray(m.bindings) ? m.bindings.map(String) : [], m.limits || {});
297
+ });
298
+ let L = {};
163
299
  function call(binding, path, args) {
164
300
  return new Promise((resolve, reject) => {
301
+ let json;
302
+ try { json = S(args ?? []); } catch (e) { reject(new TypeError('SDK arguments must be JSON-serializable')); return; }
303
+ if (typeof json !== 'string' || bytes(json) > L.maxRpcArgBytes) { const e = new Error('SDK call arguments exceed ' + L.maxRpcArgBytes + ' bytes.'); e.name = 'ArgumentsTooLarge'; reject(e); return; }
165
304
  const id = nextId++;
166
- pending.set(id, (r) => {
167
- if (!r.ok) { const e = new Error(r.error.message); e.name = r.error.name; reject(e); }
168
- else resolve(r.value);
169
- });
170
- writeFrame({ kind: 'rpc', id, binding, path, args });
305
+ pending.set(id, { resolve, reject });
306
+ post({ t: 'rpc', id, binding, path, args: P(json) });
171
307
  });
172
308
  }
173
-
174
309
  function makeProxy(binding) {
175
- const handler = (path) => new Proxy(function(){}, {
176
- get(_, key) { return handler([...path, String(key)]); },
310
+ const handler = (path) => new Proxy(function () {}, {
311
+ get(_, key) { return typeof key === 'symbol' ? undefined : handler([...path, String(key)]); },
177
312
  apply(_, __, args) { return call(binding, path, args); },
178
313
  });
179
314
  return handler([]);
180
315
  }
316
+ function run(code, bindings, limits) {
317
+ L = limits;
318
+ const show = (v) => { if (typeof v === 'string') return v; try { const j = S(v); return j === undefined ? Str(v) : j; } catch { return Str(v); } };
319
+ let logBytes = 0, logLines = 0, logDone = false;
320
+ const log = (...a) => {
321
+ if (logDone) return;
322
+ let text = '';
323
+ for (let i = 0; i < a.length; i++) text += (i ? ' ' : '') + show(a[i]);
324
+ text = cut(text, L.maxLogBytes);
325
+ logBytes += bytes(text) + L.logLineOverhead; logLines++;
326
+ if (logBytes > L.maxLogBytes - L.logTruncated.length - L.logLineOverhead || logLines >= L.maxLogLines) { logDone = true; text = L.logTruncated; }
327
+ post({ t: 'log', text });
328
+ };
329
+ self.console = { log, info: log, warn: log, error: log, debug: log };
330
+ for (const k of ['Deno', 'postMessage', 'close', 'fetch', 'WebSocket', 'WebSocketStream', 'Worker', 'EventSource',
331
+ 'navigator', 'caches', 'localStorage', 'sessionStorage', 'importScripts', 'BroadcastChannel']) {
332
+ try { Object.defineProperty(self, k, { value: undefined, writable: false, configurable: false }); } catch {}
333
+ }
334
+ for (const name of bindings) {
335
+ try { Object.defineProperty(self, name, { value: makeProxy(name), writable: false, configurable: false }); } catch {}
336
+ }
337
+ let fn;
338
+ try { fn = new Function('"use strict"; return (async () => {\\n' + code + '\\n})();'); }
339
+ catch (e) { post({ t: 'done', ok: false, error: { name: Str(e?.name ?? 'SyntaxError'), message: cut(Str(e?.message ?? e), L.maxError) } }); return; }
340
+ const fail = (e) => {
341
+ let name = 'Error', message = '', status;
342
+ try { name = cut(Str(e?.name ?? 'Error'), 100); message = cut(Str(e?.message !== undefined ? e.message : e), L.maxError); status = typeof e?.status === 'number' ? e.status : undefined; } catch {}
343
+ post({ t: 'done', ok: false, error: { name, message, ...(status === undefined ? {} : { status }) } });
344
+ };
345
+ const done = (value) => {
346
+ let json;
347
+ try { json = S(value === undefined ? null : value); } catch (e) { fail({ name: 'TypeError', message: 'The returned value is not JSON-serializable' }); return; }
348
+ if (typeof json !== 'string') json = 'null';
349
+ const size = bytes(json);
350
+ if (size > L.maxResultBytes) post({ t: 'done', ok: false, tooLarge: true, size });
351
+ else post({ t: 'done', ok: true, json });
352
+ };
353
+ let started;
354
+ try { started = fn(); } catch (e) { fail(e); return; }
355
+ apply(then, started, [done, fail]);
356
+ }
357
+ ${'`'};
181
358
 
182
- const __bindings = ${JSON.stringify(bindings)};
183
- for (const name of __bindings) { globalThis[name] = makeProxy(name); }
184
-
185
- const origLog = console.log;
186
- console.log = (...a) => writeFrame({ kind: 'log', text: a.map(String).join(' ') });
187
- console.info = console.log; console.warn = console.log; console.error = console.log;
188
-
189
- const userFn = async () => {
190
- ${userCode}
359
+ const url = URL.createObjectURL(new Blob([WORKER_SOURCE], { type: 'application/javascript' }));
360
+ const worker = new Worker(url, { type: 'module' });
361
+ worker.onmessage = (ev) => {
362
+ const m = ev.data;
363
+ if (!m || typeof m !== 'object') return;
364
+ if (m.t === 'log') frame({ t: 'log', text: String(m.text).slice(0, 65536) });
365
+ else if (m.t === 'rpc') frame({ t: 'rpc', id: m.id, binding: m.binding, path: m.path, args: m.args });
366
+ else if (m.t === 'done') frame({ t: 'done', ok: m.ok === true, json: m.json, error: m.error, tooLarge: m.tooLarge === true, size: m.size });
191
367
  };
368
+ worker.onerror = (e) => { e.preventDefault(); frame({ t: 'done', ok: false, error: { name: 'Error', message: String(e.message ?? 'Worker error') } }); };
192
369
 
193
- const timer = setTimeout(() => {
194
- writeFrame({ kind: 'result', ok: false, error: { name: 'TimeoutError', message: 'Execution exceeded ${timeoutMs}ms' }});
195
- Deno.exit(0);
196
- }, ${timeoutMs});
197
-
198
- userFn()
199
- .then(value => { clearTimeout(timer); writeFrame({ kind: 'result', ok: true, value }); Deno.exit(0); })
200
- .catch(err => { clearTimeout(timer); writeFrame({ kind: 'result', ok: false, error: { name: err.name || 'Error', message: err.message || String(err) }}); Deno.exit(0); });
201
- `;
370
+ // Host → supervisor: token-prefixed JSON lines on stdin.
371
+ const dec = new TextDecoder();
372
+ let buf = '';
373
+ for await (const chunk of Deno.stdin.readable) {
374
+ buf += dec.decode(chunk, { stream: true });
375
+ let nl;
376
+ while ((nl = buf.indexOf('\n')) >= 0) {
377
+ const line = buf.slice(0, nl);
378
+ buf = buf.slice(nl + 1);
379
+ if (!line.startsWith(TOKEN)) continue;
380
+ let msg;
381
+ try { msg = JSON.parse(line.slice(TOKEN.length)); } catch { continue; }
382
+ if (msg.t === 'start') worker.postMessage({ t: 'start', code: msg.code, bindings: msg.bindings, limits: msg.limits });
383
+ else if (msg.t === 'rpc-result') worker.postMessage(msg);
384
+ }
202
385
  }
386
+ // The host went away (stdin closed): do not leave a possibly busy Worker running as an orphan.
387
+ Deno.exit(0);
388
+ `;
203
389
  //# sourceMappingURL=deno.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"deno.js","sourceRoot":"","sources":["../../src/sandbox/deno.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deno.js","sourceRoot":"","sources":["../../src/sandbox/deno.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,16 @@
1
1
  import type { ExecuteOptions, ExecuteResult, RpcBridge, SandboxRunner } from './types.js';
2
+ import { type SandboxLimits } from './limits.js';
3
+ /**
4
+ * isolated-vm sandbox: a fresh V8 isolate per execution with a heap cap. The host owns a
5
+ * wall-clock deadline that starts before setup: when it fires the isolate
6
+ * is disposed, which stops running code and rejects anything it awaits, and the execution settles
7
+ * once. V8's own `timeout` stays as a second guard for synchronous loops. This runs in the server
8
+ * process, so for hosted multi-user execution prefer the Deno runner (separate process).
9
+ */
2
10
  export declare class IsolateRunner implements SandboxRunner {
11
+ private readonly limits;
3
12
  kind: "isolate";
13
+ constructor(limits?: SandboxLimits);
4
14
  available(): Promise<boolean>;
5
15
  execute(opts: ExecuteOptions, rpc: RpcBridge): Promise<ExecuteResult>;
6
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"isolate.d.ts","sourceRoot":"","sources":["../../src/sandbox/isolate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAoB1F,qBAAa,aAAc,YAAW,aAAa;IACjD,IAAI,EAAG,SAAS,CAAU;IAEpB,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAY7B,OAAO,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC;CAoF5E"}
1
+ {"version":3,"file":"isolate.d.ts","sourceRoot":"","sources":["../../src/sandbox/isolate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE1F,OAAO,EAA0I,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAWzL;;;;;;GAMG;AACH,qBAAa,aAAc,YAAW,aAAa;IAGrC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,IAAI,EAAG,SAAS,CAAU;gBAEG,MAAM,GAAE,aAA8B;IAE7D,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAW7B,OAAO,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC;CA2I5E"}