sealbridge 0.0.1 → 0.2.0

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.
Files changed (208) hide show
  1. package/NOTICE +43 -0
  2. package/README.ja.md +397 -0
  3. package/README.md +567 -1
  4. package/dist/cli/dist/acp.d.ts +2 -0
  5. package/dist/cli/dist/acp.js +6 -0
  6. package/dist/cli/dist/acp.js.map +1 -0
  7. package/dist/cli/dist/approval-summary.d.ts +2 -0
  8. package/dist/cli/dist/approval-summary.js +32 -0
  9. package/dist/cli/dist/approval-summary.js.map +1 -0
  10. package/dist/cli/dist/board.d.ts +47 -0
  11. package/dist/cli/dist/board.js +255 -0
  12. package/dist/cli/dist/board.js.map +1 -0
  13. package/dist/cli/dist/contacts.d.ts +18 -0
  14. package/dist/cli/dist/contacts.js +154 -0
  15. package/dist/cli/dist/contacts.js.map +1 -0
  16. package/dist/cli/dist/doctor.d.ts +13 -0
  17. package/dist/cli/dist/doctor.js +30 -0
  18. package/dist/cli/dist/doctor.js.map +1 -0
  19. package/dist/cli/dist/error-messages.d.ts +2 -0
  20. package/dist/cli/dist/error-messages.js +24 -0
  21. package/dist/cli/dist/error-messages.js.map +1 -0
  22. package/dist/cli/dist/index.d.ts +2 -0
  23. package/dist/cli/dist/index.js +194 -0
  24. package/dist/cli/dist/index.js.map +1 -0
  25. package/dist/cli/dist/invite-share.d.ts +16 -0
  26. package/dist/cli/dist/invite-share.js +163 -0
  27. package/dist/cli/dist/invite-share.js.map +1 -0
  28. package/dist/cli/dist/mcp.d.ts +17 -0
  29. package/dist/cli/dist/mcp.js +105 -0
  30. package/dist/cli/dist/mcp.js.map +1 -0
  31. package/dist/cli/dist/network.d.ts +1 -0
  32. package/dist/cli/dist/network.js +396 -0
  33. package/dist/cli/dist/network.js.map +1 -0
  34. package/dist/cli/dist/public-settings.d.ts +27 -0
  35. package/dist/cli/dist/public-settings.js +33 -0
  36. package/dist/cli/dist/public-settings.js.map +1 -0
  37. package/dist/cli/dist/receipt.d.ts +39 -0
  38. package/dist/cli/dist/receipt.js +90 -0
  39. package/dist/cli/dist/receipt.js.map +1 -0
  40. package/dist/cli/dist/receive-hook.d.ts +2 -0
  41. package/dist/cli/dist/receive-hook.js +35 -0
  42. package/dist/cli/dist/receive-hook.js.map +1 -0
  43. package/dist/cli/dist/task-input.d.ts +2 -0
  44. package/dist/cli/dist/task-input.js +19 -0
  45. package/dist/cli/dist/task-input.js.map +1 -0
  46. package/dist/cli/dist/wake-hook.d.ts +3 -0
  47. package/dist/cli/dist/wake-hook.js +32 -0
  48. package/dist/cli/dist/wake-hook.js.map +1 -0
  49. package/dist/examples/two-owner-demo/alice-policy.json +4 -0
  50. package/dist/examples/two-owner-demo/bob-policy.json +4 -0
  51. package/dist/examples/two-owner-demo/dist/run-demo.d.ts +71 -0
  52. package/dist/examples/two-owner-demo/dist/run-demo.js +383 -0
  53. package/dist/examples/two-owner-demo/dist/run-demo.js.map +1 -0
  54. package/dist/package.json +1 -0
  55. package/dist/packages/adapters/dist/command.d.ts +122 -0
  56. package/dist/packages/adapters/dist/command.js +378 -0
  57. package/dist/packages/adapters/dist/command.js.map +1 -0
  58. package/dist/packages/adapters/dist/credential-proxy.d.ts +37 -0
  59. package/dist/packages/adapters/dist/credential-proxy.js +363 -0
  60. package/dist/packages/adapters/dist/credential-proxy.js.map +1 -0
  61. package/dist/packages/adapters/dist/index.d.ts +6 -0
  62. package/dist/packages/adapters/dist/index.js +6 -0
  63. package/dist/packages/adapters/dist/index.js.map +1 -0
  64. package/dist/packages/adapters/dist/mcp.d.ts +32 -0
  65. package/dist/packages/adapters/dist/mcp.js +87 -0
  66. package/dist/packages/adapters/dist/mcp.js.map +1 -0
  67. package/dist/packages/adapters/dist/openai.d.ts +23 -0
  68. package/dist/packages/adapters/dist/openai.js +81 -0
  69. package/dist/packages/adapters/dist/openai.js.map +1 -0
  70. package/dist/packages/adapters/dist/sandbox.d.ts +45 -0
  71. package/dist/packages/adapters/dist/sandbox.js +60 -0
  72. package/dist/packages/adapters/dist/sandbox.js.map +1 -0
  73. package/dist/packages/core/dist/capability.d.ts +36 -0
  74. package/dist/packages/core/dist/capability.js +203 -0
  75. package/dist/packages/core/dist/capability.js.map +1 -0
  76. package/dist/packages/core/dist/contract.d.ts +33 -0
  77. package/dist/packages/core/dist/contract.js +97 -0
  78. package/dist/packages/core/dist/contract.js.map +1 -0
  79. package/dist/packages/core/dist/crypto.d.ts +34 -0
  80. package/dist/packages/core/dist/crypto.js +329 -0
  81. package/dist/packages/core/dist/crypto.js.map +1 -0
  82. package/dist/packages/core/dist/discovery.d.ts +129 -0
  83. package/dist/packages/core/dist/discovery.js +527 -0
  84. package/dist/packages/core/dist/discovery.js.map +1 -0
  85. package/dist/packages/core/dist/edge.d.ts +4 -0
  86. package/dist/packages/core/dist/edge.js +6 -0
  87. package/dist/packages/core/dist/edge.js.map +1 -0
  88. package/dist/packages/core/dist/index.d.ts +9 -0
  89. package/dist/packages/core/dist/index.js +10 -0
  90. package/dist/packages/core/dist/index.js.map +1 -0
  91. package/dist/packages/core/dist/receipts.d.ts +9 -0
  92. package/dist/packages/core/dist/receipts.js +67 -0
  93. package/dist/packages/core/dist/receipts.js.map +1 -0
  94. package/dist/packages/core/dist/relay-auth.d.ts +40 -0
  95. package/dist/packages/core/dist/relay-auth.js +106 -0
  96. package/dist/packages/core/dist/relay-auth.js.map +1 -0
  97. package/dist/packages/core/dist/revocation.d.ts +58 -0
  98. package/dist/packages/core/dist/revocation.js +112 -0
  99. package/dist/packages/core/dist/revocation.js.map +1 -0
  100. package/dist/packages/core/dist/schema.d.ts +11 -0
  101. package/dist/packages/core/dist/schema.js +48 -0
  102. package/dist/packages/core/dist/schema.js.map +1 -0
  103. package/dist/packages/core/dist/types.d.ts +172 -0
  104. package/dist/packages/core/dist/types.js +2 -0
  105. package/dist/packages/core/dist/types.js.map +1 -0
  106. package/dist/packages/ledger/dist/index.d.ts +84 -0
  107. package/dist/packages/ledger/dist/index.js +269 -0
  108. package/dist/packages/ledger/dist/index.js.map +1 -0
  109. package/dist/packages/relay/dist/fetch.d.ts +250 -0
  110. package/dist/packages/relay/dist/fetch.js +1401 -0
  111. package/dist/packages/relay/dist/fetch.js.map +1 -0
  112. package/dist/packages/relay/dist/index.d.ts +103 -0
  113. package/dist/packages/relay/dist/index.js +855 -0
  114. package/dist/packages/relay/dist/index.js.map +1 -0
  115. package/dist/packages/relay/dist/journal.d.ts +77 -0
  116. package/dist/packages/relay/dist/journal.js +339 -0
  117. package/dist/packages/relay/dist/journal.js.map +1 -0
  118. package/dist/packages/relay/dist/notifications.d.ts +63 -0
  119. package/dist/packages/relay/dist/notifications.js +55 -0
  120. package/dist/packages/relay/dist/notifications.js.map +1 -0
  121. package/dist/packages/relay/dist/retry.d.ts +12 -0
  122. package/dist/packages/relay/dist/retry.js +59 -0
  123. package/dist/packages/relay/dist/retry.js.map +1 -0
  124. package/dist/packages/relay/dist/ssrf.d.ts +32 -0
  125. package/dist/packages/relay/dist/ssrf.js +213 -0
  126. package/dist/packages/relay/dist/ssrf.js.map +1 -0
  127. package/dist/packages/relay/dist/worker.d.ts +92 -0
  128. package/dist/packages/relay/dist/worker.js +460 -0
  129. package/dist/packages/relay/dist/worker.js.map +1 -0
  130. package/dist/packages/runtime/dist/a2a.d.ts +8 -0
  131. package/dist/packages/runtime/dist/a2a.js +69 -0
  132. package/dist/packages/runtime/dist/a2a.js.map +1 -0
  133. package/dist/packages/runtime/dist/adapter.d.ts +51 -0
  134. package/dist/packages/runtime/dist/adapter.js +2 -0
  135. package/dist/packages/runtime/dist/adapter.js.map +1 -0
  136. package/dist/packages/runtime/dist/approval-providers.d.ts +99 -0
  137. package/dist/packages/runtime/dist/approval-providers.js +269 -0
  138. package/dist/packages/runtime/dist/approval-providers.js.map +1 -0
  139. package/dist/packages/runtime/dist/daily-limit.d.ts +2 -0
  140. package/dist/packages/runtime/dist/daily-limit.js +54 -0
  141. package/dist/packages/runtime/dist/daily-limit.js.map +1 -0
  142. package/dist/packages/runtime/dist/gateway.d.ts +35 -0
  143. package/dist/packages/runtime/dist/gateway.js +92 -0
  144. package/dist/packages/runtime/dist/gateway.js.map +1 -0
  145. package/dist/packages/runtime/dist/inbox.d.ts +10 -0
  146. package/dist/packages/runtime/dist/inbox.js +24 -0
  147. package/dist/packages/runtime/dist/inbox.js.map +1 -0
  148. package/dist/packages/runtime/dist/index.d.ts +13 -0
  149. package/dist/packages/runtime/dist/index.js +14 -0
  150. package/dist/packages/runtime/dist/index.js.map +1 -0
  151. package/dist/packages/runtime/dist/mcp-server.d.ts +90 -0
  152. package/dist/packages/runtime/dist/mcp-server.js +647 -0
  153. package/dist/packages/runtime/dist/mcp-server.js.map +1 -0
  154. package/dist/packages/runtime/dist/mcp-tool-catalog.d.ts +3 -0
  155. package/dist/packages/runtime/dist/mcp-tool-catalog.js +507 -0
  156. package/dist/packages/runtime/dist/mcp-tool-catalog.js.map +1 -0
  157. package/dist/packages/runtime/dist/mcp.d.ts +73 -0
  158. package/dist/packages/runtime/dist/mcp.js +67 -0
  159. package/dist/packages/runtime/dist/mcp.js.map +1 -0
  160. package/dist/packages/runtime/dist/policy.d.ts +19 -0
  161. package/dist/packages/runtime/dist/policy.js +41 -0
  162. package/dist/packages/runtime/dist/policy.js.map +1 -0
  163. package/dist/packages/runtime/dist/quota.d.ts +39 -0
  164. package/dist/packages/runtime/dist/quota.js +147 -0
  165. package/dist/packages/runtime/dist/quota.js.map +1 -0
  166. package/dist/packages/runtime/dist/session-audit.d.ts +107 -0
  167. package/dist/packages/runtime/dist/session-audit.js +520 -0
  168. package/dist/packages/runtime/dist/session-audit.js.map +1 -0
  169. package/dist/packages/runtime/dist/session-timeouts.d.ts +33 -0
  170. package/dist/packages/runtime/dist/session-timeouts.js +62 -0
  171. package/dist/packages/runtime/dist/session-timeouts.js.map +1 -0
  172. package/dist/packages/runtime/dist/session.d.ts +323 -0
  173. package/dist/packages/runtime/dist/session.js +2252 -0
  174. package/dist/packages/runtime/dist/session.js.map +1 -0
  175. package/dist/packages/runtime/dist/task-journal.d.ts +36 -0
  176. package/dist/packages/runtime/dist/task-journal.js +104 -0
  177. package/dist/packages/runtime/dist/task-journal.js.map +1 -0
  178. package/dist/packages/runtime/dist/verifier.d.ts +64 -0
  179. package/dist/packages/runtime/dist/verifier.js +109 -0
  180. package/dist/packages/runtime/dist/verifier.js.map +1 -0
  181. package/dist/packages/sandbox/dist/container.d.ts +33 -0
  182. package/dist/packages/sandbox/dist/container.js +189 -0
  183. package/dist/packages/sandbox/dist/container.js.map +1 -0
  184. package/dist/packages/sandbox/dist/index.d.ts +34 -0
  185. package/dist/packages/sandbox/dist/index.js +179 -0
  186. package/dist/packages/sandbox/dist/index.js.map +1 -0
  187. package/dist/packages/sandbox/dist/permission.d.ts +58 -0
  188. package/dist/packages/sandbox/dist/permission.js +90 -0
  189. package/dist/packages/sandbox/dist/permission.js.map +1 -0
  190. package/dist/spec/README.ja.md +76 -0
  191. package/dist/spec/README.md +135 -0
  192. package/dist/spec/ack-receipt.schema.json +77 -0
  193. package/dist/spec/agent-card.schema.json +83 -0
  194. package/dist/spec/approval-receipt.schema.json +94 -0
  195. package/dist/spec/audit-entry.schema.json +101 -0
  196. package/dist/spec/capability-token.schema.json +133 -0
  197. package/dist/spec/envelope.schema.json +197 -0
  198. package/dist/spec/examples/sample-ack-receipt.json +16 -0
  199. package/dist/spec/examples/sample-agent-card.json +35 -0
  200. package/dist/spec/examples/sample-approval-receipt.json +18 -0
  201. package/dist/spec/examples/sample-audit-entry.json +37 -0
  202. package/dist/spec/examples/sample-capability-token.json +39 -0
  203. package/dist/spec/examples/sample-envelope.json +21 -0
  204. package/dist/spec/examples/sample-task-manifest.json +141 -0
  205. package/dist/spec/examples/sample-usage-receipt.json +19 -0
  206. package/dist/spec/task-manifest.schema.json +422 -0
  207. package/dist/spec/usage-receipt.schema.json +91 -0
  208. package/package.json +61 -5
@@ -0,0 +1,189 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { randomUUID } from 'node:crypto';
3
+ import { execFile, spawn } from 'node:child_process';
4
+ import { mkdtemp, writeFile, rm, chown } from 'node:fs/promises';
5
+ import { tmpdir } from 'node:os';
6
+ import { join } from 'node:path';
7
+ import { runSandbox, sandboxWrapper, sanitizedEnvironment, terminateSubprocess } from './index.js';
8
+ import { OCI_CONTAINER_BOUNDARY, subprocessSandboxBoundary } from './permission.js';
9
+ export async function detectDockerRuntime(probe = (binary, args) => new Promise((resolve) => {
10
+ execFile(binary, args, {
11
+ timeout: 3000,
12
+ maxBuffer: 65536,
13
+ env: { PATH: '/usr/local/bin:/usr/bin:/bin', LANG: 'C.UTF-8' },
14
+ }, (error) => resolve(!error));
15
+ })) {
16
+ for (const binary of ['podman', 'docker'])
17
+ if (await probe(binary, ['info']))
18
+ return binary;
19
+ return undefined;
20
+ }
21
+ /**
22
+ * OCI argv for untrusted code. Kernel isolation is `--network none`, a read-only
23
+ * root filesystem, `--cap-drop ALL`, and `--security-opt no-new-privileges`, plus
24
+ * PID and memory limits. Node's `--permission` model is not this boundary.
25
+ */
26
+ export function containerArguments(directory, image = 'node:22-bookworm-slim', name) {
27
+ return [
28
+ 'run',
29
+ ...(name ? ['--name', name] : []),
30
+ '--rm',
31
+ '--pull=never',
32
+ '--network',
33
+ 'none',
34
+ '--read-only',
35
+ '--cap-drop',
36
+ 'ALL',
37
+ '--security-opt',
38
+ 'no-new-privileges',
39
+ '--pids-limit',
40
+ '64',
41
+ '--memory',
42
+ '128m',
43
+ '--cpus',
44
+ '1',
45
+ '--user',
46
+ `${process.getuid?.() || 65534}:${process.getgid?.() || 65534}`,
47
+ '--tmpfs',
48
+ '/tmp:rw,noexec,nosuid,size=16m',
49
+ '--mount',
50
+ `type=bind,src=${directory},dst=/work`,
51
+ '--workdir',
52
+ '/work',
53
+ '-i',
54
+ image,
55
+ 'node',
56
+ '--no-addons',
57
+ '--disable-proto=throw',
58
+ '--max-old-space-size=64',
59
+ '/work/runner.cjs',
60
+ ];
61
+ }
62
+ export async function runContainerOrSubprocessSandbox(options) {
63
+ if (!Number.isSafeInteger(options.timeoutMs) ||
64
+ options.timeoutMs < 1 ||
65
+ options.timeoutMs > 604800000)
66
+ throw new Error('INVALID_TIMEOUT');
67
+ if (!['subprocess_restricted', 'oci_container'].includes(options.isolationLevel ?? 'subprocess_restricted'))
68
+ throw new Error('UNSUPPORTED_SANDBOX_POLICY');
69
+ const runtime = options.isolationLevel === 'oci_container'
70
+ ? options.runtime === undefined
71
+ ? await detectDockerRuntime(options.probe)
72
+ : options.runtime
73
+ : undefined;
74
+ if (!runtime)
75
+ return {
76
+ output: await runSandbox(options),
77
+ effectiveIsolationLevel: 'subprocess_restricted',
78
+ // Same flag choice `runSandbox` passes. Network stays open at the kernel.
79
+ sandboxBoundary: subprocessSandboxBoundary(),
80
+ };
81
+ const directory = await mkdtemp(join(tmpdir(), 'acp-oci-')), name = 'acp-' + randomUUID();
82
+ try {
83
+ if (process.getuid?.() === 0)
84
+ await chown(directory, 65534, 65534);
85
+ const bridge = `const send=m=>process.stdout.write(JSON.stringify(m)+'\\n');process.disconnect=()=>{process.stdin.destroy();};require('node:readline').createInterface({input:process.stdin}).on('line',l=>process.emit('message',JSON.parse(l)));\n`;
86
+ await writeFile(join(directory, 'runner.cjs'), bridge + sandboxWrapper.replaceAll('process.send(', 'send('));
87
+ await writeFile(join(directory, 'task.json'), JSON.stringify({
88
+ code: options.code,
89
+ input: options.input ?? null,
90
+ timeoutMs: options.timeoutMs,
91
+ }));
92
+ // An empty config avoids Docker CLI proxy defaults and registry credentials.
93
+ await writeFile(join(directory, 'config.json'), '{}');
94
+ const output = await new Promise((resolve, reject) => {
95
+ const environment = {
96
+ ...sanitizedEnvironment(directory),
97
+ PATH: '/usr/local/bin:/usr/bin:/bin',
98
+ DOCKER_CONFIG: directory,
99
+ };
100
+ const child = options.containerSpawn
101
+ ? options.containerSpawn(runtime, containerArguments(directory, options.image, name), {
102
+ cwd: directory,
103
+ env: environment,
104
+ })
105
+ : spawn(runtime, containerArguments(directory, options.image, name), {
106
+ env: environment,
107
+ stdio: ['pipe', 'pipe', 'pipe'],
108
+ });
109
+ child.stderr.resume();
110
+ let done = false, buffer = '', calls = 0;
111
+ let serial = Promise.resolve();
112
+ const finish = (error, value) => {
113
+ if (done)
114
+ return;
115
+ done = true;
116
+ clearTimeout(timer);
117
+ options.signal?.removeEventListener('abort', abort);
118
+ terminateSubprocess(child);
119
+ error ? reject(error) : resolve(value ?? null);
120
+ };
121
+ const abort = () => finish(new Error('SANDBOX_HALTED'));
122
+ const timer = setTimeout(() => finish(new Error('SANDBOX_TIMEOUT')), options.timeoutMs);
123
+ options.signal?.addEventListener('abort', abort, { once: true });
124
+ if (options.signal?.aborted)
125
+ abort();
126
+ child.stdout.on('data', (chunk) => {
127
+ buffer += chunk.toString();
128
+ if (buffer.length > 1048576)
129
+ return finish(new Error('SANDBOX_MESSAGE_LIMIT'));
130
+ let index;
131
+ while ((index = buffer.indexOf('\n')) >= 0) {
132
+ const line = buffer.slice(0, index);
133
+ buffer = buffer.slice(index + 1);
134
+ serial = serial
135
+ .then(async () => {
136
+ if (done)
137
+ return;
138
+ const m = JSON.parse(line);
139
+ if (m.type === 'done')
140
+ return finish(m.error ? new Error(m.error) : undefined, m.value);
141
+ if (m.type !== 'tool' || ++calls > 10000)
142
+ throw new Error('SANDBOX_PROTOCOL');
143
+ let value = null;
144
+ if (m.name === '$usage') {
145
+ if (!options.onUsage)
146
+ throw new Error('USAGE_ADAPTER_REQUIRED');
147
+ options.onUsage(m.args.inputTokens, m.args.outputTokens);
148
+ }
149
+ else
150
+ value = await options.onTool(m.name, m.args);
151
+ if (!done)
152
+ child.stdin.write(JSON.stringify({ id: m.id, value }) + '\n');
153
+ })
154
+ .catch((e) => finish(e instanceof Error ? e : new Error(String(e))));
155
+ }
156
+ });
157
+ child.on('error', (e) => finish(e));
158
+ child.stdin.on('error', () => { });
159
+ child.on('close', (code) => {
160
+ void serial.then(() => {
161
+ if (!done)
162
+ finish(new Error('CONTAINER_EXIT: ' + code));
163
+ });
164
+ });
165
+ });
166
+ return {
167
+ output,
168
+ effectiveIsolationLevel: 'oci_container',
169
+ sandboxBoundary: OCI_CONTAINER_BOUNDARY,
170
+ };
171
+ }
172
+ finally {
173
+ await new Promise((resolve) => execFile(runtime, ['rm', '-f', name], {
174
+ timeout: 3000,
175
+ env: {
176
+ ...sanitizedEnvironment(directory),
177
+ PATH: '/usr/local/bin:/usr/bin:/bin',
178
+ DOCKER_CONFIG: directory,
179
+ },
180
+ }, () => resolve()));
181
+ await rm(directory, { recursive: true, force: true });
182
+ }
183
+ }
184
+ export class SandboxRunner {
185
+ run(options) {
186
+ return runContainerOrSubprocessSandbox(options);
187
+ }
188
+ }
189
+ //# sourceMappingURL=container.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { Json } from '@acp/core';
2
+ import type { NodePermissionProbe } from './permission.js';
3
+ export type { NodePermissionFlag, NodePermissionProbe, ResolvedNodePermission, SandboxBoundaryMetadata, } from './permission.js';
4
+ export { OCI_CONTAINER_BOUNDARY, detectNodePermissionFlag, prefersStableNodePermissionFlag, resolveNodePermissionArgs, subprocessSandboxBoundary, } from './permission.js';
5
+ export interface SandboxOptions {
6
+ code: string;
7
+ input?: Json;
8
+ timeoutMs: number;
9
+ onTool: (name: string, args: Record<string, unknown>) => Promise<unknown>;
10
+ onUsage?: (inputTokens: number, outputTokens: number) => void;
11
+ signal?: AbortSignal;
12
+ }
13
+ export declare const sandboxWrapper: string;
14
+ export declare function sanitizedEnvironment(directory: string): NodeJS.ProcessEnv;
15
+ /**
16
+ * Argv after `process.execPath` for a `subprocess_restricted` child.
17
+ * Permission-model flags come from `resolveNodePermissionArgs`. `--no-addons`
18
+ * stays even when this Node binary supports neither permission flag.
19
+ */
20
+ export declare function buildRestrictedSubprocessArgv(directory: string, entry: string, probe?: NodePermissionProbe): string[];
21
+ /** SIGTERM, then SIGKILL if the child is still alive. `killed` is true after either signal. */
22
+ export declare function terminateSubprocess(subprocess: {
23
+ exitCode: number | null;
24
+ kill: (signal?: NodeJS.Signals) => boolean;
25
+ }): void;
26
+ /**
27
+ * `subprocess_restricted` runner. Separate OS process, sanitized environment,
28
+ * scratch directory, timeout then SIGKILL, and an output byte cap. Node's
29
+ * permission model is applied when `detectNodePermissionFlag` finds a flag.
30
+ * `node:vm` inside the child is not a security mechanism, and the permission
31
+ * model does not block network syscalls. Untrusted code needs `oci_container`.
32
+ */
33
+ export declare function runSandbox(options: SandboxOptions): Promise<Json>;
34
+ export * from './container.js';
@@ -0,0 +1,179 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { mkdtemp, realpath, writeFile, rm } from 'node:fs/promises';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { spawn } from 'node:child_process';
6
+ import { resolveNodePermissionArgs } from './permission.js';
7
+ export { OCI_CONTAINER_BOUNDARY, detectNodePermissionFlag, prefersStableNodePermissionFlag, resolveNodePermissionArgs, subprocessSandboxBoundary, } from './permission.js';
8
+ // The parent process is the only one that holds owner keys and tool handlers.
9
+ // Task values cross that process boundary as JSON. Inside the child, `node:vm`
10
+ // evaluates task source in a null-prototype context. Node.js documents that
11
+ // `node:vm` is not a security mechanism: code that escapes the context runs as
12
+ // this child. `--permission` / `--experimental-permission` can deny filesystem,
13
+ // child-process, worker, and addon access. They do not deny network syscalls
14
+ // (`fetch`, `node:net`, `node:http`, `node:https`, `node:dns`, `node:dgram`).
15
+ // Deleting the Web globals below only hides those names in the wrapper.
16
+ export const sandboxWrapper = String.raw `
17
+ const vm = require('node:vm');
18
+ const fs = require('node:fs');
19
+ try { delete globalThis.fetch; } catch { /* name may be non-configurable */ }
20
+ try { delete globalThis.WebSocket; } catch { /* name may be non-configurable */ }
21
+ const config = JSON.parse(fs.readFileSync('task.json', 'utf8'));
22
+ const context = vm.createContext(Object.create(null), { codeGeneration: { strings: false, wasm: false }, microtaskMode: 'afterEvaluate' });
23
+ const bootstrap = 'globalThis.queue=[]; globalThis.waiters=new Map(); globalThis.serial=0; globalThis.finished=false; globalThis.callTool=(name,args)=>new Promise((resolve,reject)=>{const id=++serial;waiters.set(id,{resolve,reject});queue.push({id,name,args});}); globalThis.reportUsage=(inputTokens,outputTokens)=>callTool("$usage",{inputTokens,outputTokens}); globalThis.input=JSON.parse(' + JSON.stringify(JSON.stringify(config.input)) + ');';
24
+ vm.runInContext(bootstrap, context, { timeout: 100 });
25
+ new vm.Script('(async()=>{'+config.code+'})().then(value=>{globalThis.result=JSON.stringify({value:value===undefined?null:value});globalThis.finished=true;},error=>{globalThis.result=JSON.stringify({error:String(error)});globalThis.finished=true;});').runInContext(context, { timeout: config.timeoutMs });
26
+ const timer = setInterval(()=>{
27
+ try {
28
+ const queued=JSON.parse(vm.runInContext('JSON.stringify(queue.splice(0))',context,{timeout:100}));
29
+ for(const req of queued)process.send({type:'tool',...req});
30
+ if(vm.runInContext('finished',context,{timeout:100})){clearInterval(timer);process.send({type:'done',...JSON.parse(vm.runInContext('result',context,{timeout:100}))});process.disconnect();}
31
+ } catch(e){process.send({type:'done',error:String(e)});process.exit(1);}
32
+ },5);
33
+ process.on('message',msg=>{
34
+ try { const data=JSON.stringify(msg); vm.runInContext('{const r=JSON.parse('+JSON.stringify(data)+');const w=waiters.get(r.id);if(w){waiters.delete(r.id);r.error?w.reject(new Error(r.error)):w.resolve(r.value);}}',context,{timeout:100}); }
35
+ catch(e){process.send({type:'done',error:String(e)});process.exit(1);}
36
+ });
37
+ `;
38
+ export function sanitizedEnvironment(directory) {
39
+ // Build an allowlist from scratch: NODE_OPTIONS, proxy auth, cloud credentials,
40
+ // provider keys, SSH sockets and inherited PATH never enter the worker.
41
+ return { LANG: 'C.UTF-8', TZ: 'UTC', HOME: directory, TMPDIR: directory };
42
+ }
43
+ /**
44
+ * Argv after `process.execPath` for a `subprocess_restricted` child.
45
+ * Permission-model flags come from `resolveNodePermissionArgs`. `--no-addons`
46
+ * stays even when this Node binary supports neither permission flag.
47
+ */
48
+ export function buildRestrictedSubprocessArgv(directory, entry, probe) {
49
+ return [
50
+ ...resolveNodePermissionArgs(directory, probe).args,
51
+ '--no-addons',
52
+ '--disable-proto=throw',
53
+ '--max-old-space-size=64',
54
+ entry,
55
+ ];
56
+ }
57
+ /** SIGTERM, then SIGKILL if the child is still alive. `killed` is true after either signal. */
58
+ export function terminateSubprocess(subprocess) {
59
+ if (subprocess.exitCode !== null)
60
+ return;
61
+ subprocess.kill('SIGTERM');
62
+ const timer = setTimeout(() => {
63
+ if (subprocess.exitCode === null)
64
+ subprocess.kill('SIGKILL');
65
+ }, 40);
66
+ timer.unref?.();
67
+ }
68
+ /**
69
+ * `subprocess_restricted` runner. Separate OS process, sanitized environment,
70
+ * scratch directory, timeout then SIGKILL, and an output byte cap. Node's
71
+ * permission model is applied when `detectNodePermissionFlag` finds a flag.
72
+ * `node:vm` inside the child is not a security mechanism, and the permission
73
+ * model does not block network syscalls. Untrusted code needs `oci_container`.
74
+ */
75
+ export async function runSandbox(options) {
76
+ if (!Number.isSafeInteger(options.timeoutMs) ||
77
+ options.timeoutMs < 1 ||
78
+ options.timeoutMs > 604800000)
79
+ throw new Error('INVALID_TIMEOUT');
80
+ // macOS tmpdir() is /var/folders/..., a symlink to /private/var/folders/...
81
+ // Node's permission model realpath's the entry script and then stats '/var'
82
+ // unless --allow-fs-read already names the physical directory.
83
+ const directory = await realpath(await mkdtemp(join(tmpdir(), 'acp-task-')));
84
+ let child;
85
+ let exited = Promise.resolve();
86
+ try {
87
+ await writeFile(join(directory, 'runner.cjs'), sandboxWrapper, { mode: 0o600 });
88
+ await writeFile(join(directory, 'task.json'), JSON.stringify({
89
+ code: options.code,
90
+ input: options.input ?? null,
91
+ timeoutMs: options.timeoutMs,
92
+ }), { mode: 0o600 });
93
+ return await new Promise((resolve, reject) => {
94
+ const subprocess = spawn(process.execPath, buildRestrictedSubprocessArgv(directory, join(directory, 'runner.cjs')), {
95
+ cwd: directory,
96
+ env: sanitizedEnvironment(directory),
97
+ stdio: ['ignore', 'ignore', 'pipe', 'ipc'],
98
+ });
99
+ child = subprocess;
100
+ // `close` means stdio and the process handle are gone, so Windows can release cwd.
101
+ exited = new Promise((resolveExit) => {
102
+ const finished = () => resolveExit();
103
+ subprocess.once('exit', finished);
104
+ subprocess.once('close', finished);
105
+ });
106
+ let done = false, requests = 0, stderr = '';
107
+ const finish = (error, result) => {
108
+ if (done)
109
+ return;
110
+ done = true;
111
+ clearTimeout(timer);
112
+ options.signal?.removeEventListener('abort', abort);
113
+ terminateSubprocess(subprocess);
114
+ error ? reject(error) : resolve(result ?? null);
115
+ };
116
+ const abort = () => finish(new Error('SANDBOX_HALTED: ' + String(options.signal?.reason)));
117
+ const timer = setTimeout(() => finish(new Error('SANDBOX_TIMEOUT')), options.timeoutMs);
118
+ options.signal?.addEventListener('abort', abort, { once: true });
119
+ if (options.signal?.aborted)
120
+ abort();
121
+ subprocess.stderr?.on('data', (b) => {
122
+ stderr = (stderr + b.toString()).slice(-4096);
123
+ });
124
+ // Requests arrive from another OS process. The child has no tool handlers,
125
+ // capability counters, private keys or credentials, and cannot skip CapGuard.
126
+ let serial = Promise.resolve();
127
+ subprocess.on('message', (message) => {
128
+ serial = serial
129
+ .then(async () => {
130
+ if (done)
131
+ return;
132
+ const m = message;
133
+ // Output byte cap for one IPC message from the child.
134
+ if (JSON.stringify(m).length > 1048576)
135
+ return finish(new Error('SANDBOX_MESSAGE_LIMIT'));
136
+ if (m.type === 'done')
137
+ return finish(m.error ? new Error(m.error) : undefined, m.value);
138
+ if (m.type !== 'tool' || ++requests > 10000)
139
+ return finish(new Error('SANDBOX_PROTOCOL'));
140
+ try {
141
+ let value = null;
142
+ if (m.name === '$usage') {
143
+ if (!options.onUsage)
144
+ throw new Error('USAGE_ADAPTER_REQUIRED');
145
+ options.onUsage(m.args.inputTokens, m.args.outputTokens);
146
+ }
147
+ else
148
+ value = await options.onTool(m.name, m.args);
149
+ if (!done && subprocess.connected)
150
+ subprocess.send({ id: m.id, value });
151
+ }
152
+ catch (error) {
153
+ finish(error instanceof Error ? error : new Error(String(error)));
154
+ }
155
+ })
156
+ .catch((e) => finish(e));
157
+ });
158
+ subprocess.on('error', (e) => finish(e));
159
+ subprocess.on('exit', (code) => {
160
+ if (!done)
161
+ finish(new Error('SANDBOX_EXIT: ' + code + ' ' + stderr));
162
+ });
163
+ });
164
+ }
165
+ finally {
166
+ try {
167
+ if (child)
168
+ terminateSubprocess(child);
169
+ // Wait until the child has actually exited, then give Windows a short retry window.
170
+ await Promise.race([exited, new Promise((resolve) => setTimeout(resolve, 250))]);
171
+ await rm(directory, { recursive: true, force: true, maxRetries: 5, retryDelay: 50 });
172
+ }
173
+ catch {
174
+ // EBUSY, EPERM, and EACCES while deleting the temp dir must not replace the result.
175
+ }
176
+ }
177
+ }
178
+ export * from './container.js';
179
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * CLI spelling of Node's permission model.
3
+ * `--permission` is the stable flag on Node.js >= 22.13 and on Node.js 23+.
4
+ * Earlier Node.js 20 and 22 releases accept `--experimental-permission`.
5
+ * `--allow-fs-read` / `--allow-fs-write` are valid only together with one of these.
6
+ */
7
+ export declare const NODE_PERMISSION_FLAGS: readonly ["--permission", "--experimental-permission"];
8
+ export type NodePermissionFlag = (typeof NODE_PERMISSION_FLAGS)[number];
9
+ /**
10
+ * What a sandbox run can honestly claim about Node's permission model.
11
+ * `kernelNetworkIsolated` is true only for `oci_container` (`--network none`).
12
+ * The permission model does not deny `fetch`, `node:net`, `node:http`,
13
+ * `node:https`, `node:dns`, or `node:dgram`.
14
+ * `permissionModelActive` means a permission flag was passed. It is false for
15
+ * `oci_container`, which uses the container runtime instead of that flag.
16
+ */
17
+ export interface SandboxBoundaryMetadata {
18
+ nodePermissionFlag: NodePermissionFlag | null;
19
+ permissionModelActive: boolean;
20
+ kernelNetworkIsolated: boolean;
21
+ }
22
+ export interface NodePermissionProbe {
23
+ /** Flags the binary advertises. Defaults to `process.allowedNodeEnvironmentFlags`. */
24
+ flags?: Iterable<string>;
25
+ /** `process.versions.node`, with or without a leading `v`. */
26
+ nodeVersion?: string;
27
+ }
28
+ export interface ResolvedNodePermission {
29
+ flag: NodePermissionFlag | null;
30
+ /** Empty when neither permission flag is supported. Never contains `--allow-fs-*` alone. */
31
+ args: string[];
32
+ boundary: SandboxBoundaryMetadata;
33
+ }
34
+ /** Boundary recorded for Podman/Docker `--network none` runs. */
35
+ export declare const OCI_CONTAINER_BOUNDARY: SandboxBoundaryMetadata;
36
+ export declare function parseNodeVersion(version: string): {
37
+ major: number;
38
+ minor: number;
39
+ patch: number;
40
+ };
41
+ /** True when the documented stable spelling is `--permission` (Node.js >= 22.13, or >= 23). */
42
+ export declare function prefersStableNodePermissionFlag(nodeVersion: string): boolean;
43
+ /**
44
+ * Chooses `--permission` or `--experimental-permission` for `process.execPath`.
45
+ * Returns null when `allowedNodeEnvironmentFlags` lists neither, so callers can
46
+ * start the child without `--allow-fs-*` and record `permissionModelActive: false`.
47
+ * Version selects the spelling when both flags are advertised. A binary that
48
+ * lists only one spelling uses that spelling.
49
+ */
50
+ export declare function detectNodePermissionFlag(probe?: NodePermissionProbe): NodePermissionFlag | null;
51
+ /** Subprocess claim. `kernelNetworkIsolated` stays false even when the flag is active. */
52
+ export declare function subprocessSandboxBoundary(probe?: NodePermissionProbe): SandboxBoundaryMetadata;
53
+ /**
54
+ * Permission-model argv for one scratch directory.
55
+ * `--allow-fs-read` and `--allow-fs-write` are omitted when no permission flag exists,
56
+ * because Node rejects them unless `--permission` or `--experimental-permission` is active.
57
+ */
58
+ export declare function resolveNodePermissionArgs(directory: string, probe?: NodePermissionProbe): ResolvedNodePermission;
@@ -0,0 +1,90 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ /**
3
+ * CLI spelling of Node's permission model.
4
+ * `--permission` is the stable flag on Node.js >= 22.13 and on Node.js 23+.
5
+ * Earlier Node.js 20 and 22 releases accept `--experimental-permission`.
6
+ * `--allow-fs-read` / `--allow-fs-write` are valid only together with one of these.
7
+ */
8
+ export const NODE_PERMISSION_FLAGS = ['--permission', '--experimental-permission'];
9
+ /** Boundary recorded for Podman/Docker `--network none` runs. */
10
+ export const OCI_CONTAINER_BOUNDARY = {
11
+ nodePermissionFlag: null,
12
+ permissionModelActive: false,
13
+ kernelNetworkIsolated: true,
14
+ };
15
+ export function parseNodeVersion(version) {
16
+ const match = /^v?(\d+)\.(\d+)(?:\.(\d+))?/.exec(version.trim());
17
+ if (!match)
18
+ return { major: 0, minor: 0, patch: 0 };
19
+ return {
20
+ major: Number(match[1]),
21
+ minor: Number(match[2]),
22
+ patch: match[3] ? Number(match[3]) : 0,
23
+ };
24
+ }
25
+ /** True when the documented stable spelling is `--permission` (Node.js >= 22.13, or >= 23). */
26
+ export function prefersStableNodePermissionFlag(nodeVersion) {
27
+ const { major, minor } = parseNodeVersion(nodeVersion);
28
+ return major > 22 || (major === 22 && minor >= 13);
29
+ }
30
+ function advertisedFlags(probe) {
31
+ return new Set(probe?.flags ?? process.allowedNodeEnvironmentFlags);
32
+ }
33
+ /**
34
+ * Chooses `--permission` or `--experimental-permission` for `process.execPath`.
35
+ * Returns null when `allowedNodeEnvironmentFlags` lists neither, so callers can
36
+ * start the child without `--allow-fs-*` and record `permissionModelActive: false`.
37
+ * Version selects the spelling when both flags are advertised. A binary that
38
+ * lists only one spelling uses that spelling.
39
+ */
40
+ export function detectNodePermissionFlag(probe) {
41
+ const flags = advertisedFlags(probe);
42
+ const version = probe?.nodeVersion ?? process.versions.node;
43
+ const hasStable = flags.has('--permission');
44
+ const hasExperimental = flags.has('--experimental-permission');
45
+ if (prefersStableNodePermissionFlag(version) && hasStable)
46
+ return '--permission';
47
+ if (hasExperimental)
48
+ return '--experimental-permission';
49
+ if (hasStable)
50
+ return '--permission';
51
+ return null;
52
+ }
53
+ /** Subprocess claim. `kernelNetworkIsolated` stays false even when the flag is active. */
54
+ export function subprocessSandboxBoundary(probe) {
55
+ const flag = detectNodePermissionFlag(probe);
56
+ return {
57
+ nodePermissionFlag: flag,
58
+ permissionModelActive: flag !== null,
59
+ kernelNetworkIsolated: false,
60
+ };
61
+ }
62
+ function assertScratchDirectory(directory) {
63
+ // A comma is a permission-model path separator, so it would widen the allowlist.
64
+ if (directory.length === 0 ||
65
+ directory === '/' ||
66
+ directory.includes(',') ||
67
+ directory.includes('\0'))
68
+ throw new Error('INVALID_SANDBOX_DIRECTORY');
69
+ }
70
+ /**
71
+ * Permission-model argv for one scratch directory.
72
+ * `--allow-fs-read` and `--allow-fs-write` are omitted when no permission flag exists,
73
+ * because Node rejects them unless `--permission` or `--experimental-permission` is active.
74
+ */
75
+ export function resolveNodePermissionArgs(directory, probe) {
76
+ const boundary = subprocessSandboxBoundary(probe);
77
+ if (!boundary.nodePermissionFlag)
78
+ return { flag: null, args: [], boundary };
79
+ assertScratchDirectory(directory);
80
+ return {
81
+ flag: boundary.nodePermissionFlag,
82
+ args: [
83
+ boundary.nodePermissionFlag,
84
+ '--allow-fs-read=' + directory,
85
+ '--allow-fs-write=' + directory,
86
+ ],
87
+ boundary,
88
+ };
89
+ }
90
+ //# sourceMappingURL=permission.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission.js","sourceRoot":"","sources":["../src/permission.ts"],"names":[],"mappings":"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"}