@cogitator-ai/sandbox 0.2.0 → 0.2.1

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 (2) hide show
  1. package/README.md +486 -37
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @cogitator-ai/sandbox
2
2
 
3
- Sandbox execution for Cogitator agents. Supports Docker containers and WASM (via Extism) for secure code execution.
3
+ Secure sandbox execution for Cogitator agents. Run untrusted code in isolated Docker containers, WASM modules, or native fallback with resource limits, network isolation, and timeout enforcement.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,77 +8,526 @@ Sandbox execution for Cogitator agents. Supports Docker containers and WASM (via
8
8
  pnpm add @cogitator-ai/sandbox
9
9
 
10
10
  # Optional peer dependencies
11
- pnpm add dockerode # For Docker sandbox
11
+ pnpm add dockerode # For Docker sandbox
12
12
  pnpm add @extism/extism # For WASM sandbox
13
13
  ```
14
14
 
15
- ## Usage
15
+ ## Quick Start
16
16
 
17
- ### Docker Sandbox
17
+ ```typescript
18
+ import { SandboxManager } from '@cogitator-ai/sandbox';
19
+
20
+ const manager = new SandboxManager();
21
+ await manager.initialize();
22
+
23
+ const result = await manager.execute(
24
+ { command: ['python', '-c', 'print("Hello!")'] },
25
+ { type: 'docker', image: 'python:3.11-alpine' }
26
+ );
27
+
28
+ console.log(result.data?.stdout); // "Hello!"
29
+ ```
30
+
31
+ ## Features
32
+
33
+ - **Docker Sandbox** - Full container isolation with dropped capabilities
34
+ - **WASM Sandbox** - Extism-powered WebAssembly execution
35
+ - **Native Fallback** - Direct execution when containers unavailable
36
+ - **Container Pool** - Reuse warm containers for faster execution
37
+ - **Resource Limits** - Memory, CPU, PID limits
38
+ - **Network Isolation** - Disabled by default
39
+ - **Timeout Enforcement** - Kill runaway processes
40
+ - **Security Hardening** - No privilege escalation, all capabilities dropped
41
+
42
+ ---
43
+
44
+ ## Sandbox Manager
45
+
46
+ The `SandboxManager` orchestrates multiple execution backends with automatic fallback.
47
+
48
+ ```typescript
49
+ import { SandboxManager } from '@cogitator-ai/sandbox';
50
+
51
+ const manager = new SandboxManager({
52
+ docker: {
53
+ socketPath: '/var/run/docker.sock',
54
+ },
55
+ pool: {
56
+ maxSize: 10,
57
+ idleTimeoutMs: 120_000,
58
+ },
59
+ defaults: {
60
+ timeout: 30_000,
61
+ resources: {
62
+ memory: '256MB',
63
+ cpus: 1,
64
+ },
65
+ network: { mode: 'none' },
66
+ },
67
+ });
68
+
69
+ await manager.initialize();
70
+
71
+ const result = await manager.execute(
72
+ {
73
+ command: ['node', '-e', 'console.log(2+2)'],
74
+ timeout: 5000,
75
+ env: { NODE_ENV: 'production' },
76
+ cwd: '/workspace',
77
+ },
78
+ {
79
+ type: 'docker',
80
+ image: 'node:20-alpine',
81
+ }
82
+ );
83
+
84
+ if (result.success) {
85
+ console.log('Output:', result.data.stdout);
86
+ console.log('Exit code:', result.data.exitCode);
87
+ console.log('Duration:', result.data.duration, 'ms');
88
+ }
89
+ ```
90
+
91
+ ### Availability Checks
92
+
93
+ ```typescript
94
+ const dockerAvailable = await manager.isDockerAvailable();
95
+ const wasmAvailable = await manager.isWasmAvailable();
96
+
97
+ console.log('Docker:', dockerAvailable);
98
+ console.log('WASM:', wasmAvailable);
99
+ ```
100
+
101
+ ### Shutdown
102
+
103
+ ```typescript
104
+ await manager.shutdown();
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Docker Executor
110
+
111
+ Full container isolation with security hardening.
18
112
 
19
113
  ```typescript
20
114
  import { DockerSandboxExecutor } from '@cogitator-ai/sandbox';
21
115
 
22
- const sandbox = new DockerSandboxExecutor({
23
- image: 'cogitator/sandbox-node:latest',
24
- timeout: 30000,
25
- resources: {
26
- memory: '256m',
27
- cpus: '0.5',
116
+ const docker = new DockerSandboxExecutor({
117
+ docker: {
118
+ socketPath: '/var/run/docker.sock',
119
+ },
120
+ pool: {
121
+ maxSize: 5,
122
+ idleTimeoutMs: 60_000,
123
+ },
124
+ });
125
+
126
+ const connectResult = await docker.connect();
127
+ if (!connectResult.success) {
128
+ console.error('Docker not available:', connectResult.error);
129
+ }
130
+
131
+ const result = await docker.execute(
132
+ {
133
+ command: ['python', '-c', 'print("Hello!")'],
134
+ stdin: 'input data',
135
+ timeout: 10_000,
136
+ cwd: '/app',
137
+ env: { MY_VAR: 'value' },
28
138
  },
139
+ {
140
+ type: 'docker',
141
+ image: 'python:3.11-alpine',
142
+ timeout: 30_000,
143
+ resources: {
144
+ memory: '512MB',
145
+ cpus: 2,
146
+ pidsLimit: 50,
147
+ },
148
+ network: {
149
+ mode: 'none',
150
+ },
151
+ mounts: [{ source: '/tmp/data', target: '/data', readOnly: true }],
152
+ env: { GLOBAL_VAR: 'value' },
153
+ workdir: '/workspace',
154
+ user: 'nobody',
155
+ }
156
+ );
157
+
158
+ await docker.disconnect();
159
+ ```
160
+
161
+ ### Security Features
162
+
163
+ Docker containers run with these security settings:
164
+
165
+ ```typescript
166
+ {
167
+ NetworkMode: 'none', // No network access
168
+ CapDrop: ['ALL'], // Drop all capabilities
169
+ SecurityOpt: ['no-new-privileges'], // No privilege escalation
170
+ PidsLimit: 100, // Limit process count
171
+ ReadonlyRootfs: false, // Writable (can enable true)
172
+ }
173
+ ```
174
+
175
+ ---
176
+
177
+ ## Container Pool
178
+
179
+ Reuse warm containers for faster execution.
180
+
181
+ ```typescript
182
+ import { ContainerPool } from '@cogitator-ai/sandbox';
183
+
184
+ const pool = new ContainerPool(dockerClient, {
185
+ maxSize: 10,
186
+ idleTimeoutMs: 60_000,
29
187
  });
30
188
 
31
- const result = await sandbox.execute({
32
- command: 'node',
33
- args: ['-e', 'console.log("Hello!")'],
189
+ const container = await pool.acquire('python:3.11-alpine', {
190
+ memory: 256 * 1024 * 1024,
191
+ cpus: 1,
192
+ networkMode: 'none',
193
+ mounts: [],
34
194
  });
35
195
 
36
- console.log(result.stdout); // "Hello!"
196
+ await pool.release(container);
197
+
198
+ await pool.destroyAll();
37
199
  ```
38
200
 
39
- ### WASM Sandbox
201
+ ### Pool Options
202
+
203
+ | Option | Type | Default | Description |
204
+ | --------------- | -------- | ------- | -------------------------------------- |
205
+ | `maxSize` | `number` | `5` | Maximum containers to keep warm |
206
+ | `idleTimeoutMs` | `number` | `60000` | Time before destroying idle containers |
207
+
208
+ ---
209
+
210
+ ## WASM Executor
211
+
212
+ Execute WebAssembly modules via Extism.
40
213
 
41
214
  ```typescript
42
215
  import { WasmSandboxExecutor } from '@cogitator-ai/sandbox';
43
216
 
44
- const sandbox = new WasmSandboxExecutor({
45
- timeout: 10000,
46
- wasi: true,
217
+ const wasm = new WasmSandboxExecutor({
218
+ wasm: {
219
+ cacheDir: '/tmp/wasm-cache',
220
+ allowNetwork: false,
221
+ memoryLimit: 64,
222
+ },
47
223
  });
48
224
 
49
- const result = await sandbox.execute({
50
- module: 'https://example.com/tool.wasm',
51
- input: { data: 'test' },
225
+ await wasm.connect();
226
+
227
+ const result = await wasm.execute(
228
+ {
229
+ command: ['process'],
230
+ stdin: JSON.stringify({ data: 'input' }),
231
+ },
232
+ {
233
+ type: 'wasm',
234
+ wasm: {
235
+ url: 'https://example.com/plugin.wasm',
236
+ hash: 'sha256:abc123...',
237
+ },
238
+ timeout: 5000,
239
+ }
240
+ );
241
+
242
+ await wasm.disconnect();
243
+ ```
244
+
245
+ ---
246
+
247
+ ## Native Executor
248
+
249
+ Direct execution without isolation (fallback mode).
250
+
251
+ ```typescript
252
+ import { NativeSandboxExecutor } from '@cogitator-ai/sandbox';
253
+
254
+ const native = new NativeSandboxExecutor();
255
+ await native.connect();
256
+
257
+ const result = await native.execute(
258
+ {
259
+ command: ['ls', '-la'],
260
+ cwd: '/tmp',
261
+ env: { LC_ALL: 'C' },
262
+ timeout: 5000,
263
+ },
264
+ { type: 'native' }
265
+ );
266
+
267
+ console.log(result.data?.stdout);
268
+ ```
269
+
270
+ **Warning:** Native execution has no isolation. Use only when Docker is unavailable.
271
+
272
+ ---
273
+
274
+ ## Execution Request
275
+
276
+ ```typescript
277
+ interface SandboxExecutionRequest {
278
+ command: string[];
279
+ stdin?: string;
280
+ timeout?: number;
281
+ cwd?: string;
282
+ env?: Record<string, string>;
283
+ }
284
+ ```
285
+
286
+ ## Execution Result
287
+
288
+ ```typescript
289
+ interface SandboxExecutionResult {
290
+ stdout: string;
291
+ stderr: string;
292
+ exitCode: number;
293
+ timedOut: boolean;
294
+ duration: number;
295
+ }
296
+ ```
297
+
298
+ ---
299
+
300
+ ## Resource Limits
301
+
302
+ ### Memory
303
+
304
+ ```typescript
305
+ const result = await manager.execute(request, {
306
+ type: 'docker',
307
+ image: 'alpine',
308
+ resources: {
309
+ memory: '256MB',
310
+ },
52
311
  });
53
312
  ```
54
313
 
55
- ### Sandbox Manager
314
+ Supported formats: `'256B'`, `'256KB'`, `'256MB'`, `'256GB'`
56
315
 
57
- Automatic fallback between sandboxes:
316
+ ### CPU
58
317
 
59
318
  ```typescript
60
- import { SandboxManager } from '@cogitator-ai/sandbox';
319
+ {
320
+ resources: {
321
+ cpus: 0.5,
322
+ cpuShares: 512,
323
+ },
324
+ }
325
+ ```
61
326
 
62
- const manager = new SandboxManager({
63
- preferredType: 'docker',
64
- fallbackToNative: true,
327
+ ### Process Limits
328
+
329
+ ```typescript
330
+ {
331
+ resources: {
332
+ pidsLimit: 50,
333
+ },
334
+ }
335
+ ```
336
+
337
+ ---
338
+
339
+ ## Network Configuration
340
+
341
+ ```typescript
342
+ {
343
+ network: {
344
+ mode: 'none',
345
+ },
346
+ }
347
+ ```
348
+
349
+ Network modes:
350
+
351
+ - `'none'` - No network access (default, most secure)
352
+ - `'bridge'` - Docker bridge network
353
+ - `'host'` - Host network (not recommended)
354
+
355
+ ---
356
+
357
+ ## Volume Mounts
358
+
359
+ Mount host directories into the container:
360
+
361
+ ```typescript
362
+ {
363
+ mounts: [
364
+ { source: '/host/data', target: '/data', readOnly: true },
365
+ { source: '/host/output', target: '/output', readOnly: false },
366
+ ],
367
+ }
368
+ ```
369
+
370
+ ---
371
+
372
+ ## Utility Functions
373
+
374
+ ### Parse Memory
375
+
376
+ ```typescript
377
+ import { parseMemory } from '@cogitator-ai/sandbox';
378
+
379
+ parseMemory('256MB');
380
+ parseMemory('1GB');
381
+ parseMemory('512KB');
382
+ ```
383
+
384
+ ### CPU to NanoCPUs
385
+
386
+ ```typescript
387
+ import { cpusToNanoCpus } from '@cogitator-ai/sandbox';
388
+
389
+ cpusToNanoCpus(0.5);
390
+ cpusToNanoCpus(2);
391
+ ```
392
+
393
+ ---
394
+
395
+ ## Type Reference
396
+
397
+ ```typescript
398
+ import type {
399
+ SandboxType,
400
+ SandboxConfig,
401
+ SandboxResourceLimits,
402
+ SandboxNetworkConfig,
403
+ SandboxMount,
404
+ SandboxExecutionRequest,
405
+ SandboxExecutionResult,
406
+ SandboxManagerConfig,
407
+ SandboxPoolConfig,
408
+ SandboxDockerConfig,
409
+ SandboxResult,
410
+ } from '@cogitator-ai/sandbox';
411
+ ```
412
+
413
+ ---
414
+
415
+ ## Integration with Cogitator
416
+
417
+ Use sandboxed tools in your agents:
418
+
419
+ ```typescript
420
+ import { Cogitator, tool } from '@cogitator-ai/core';
421
+ import { z } from 'zod';
422
+
423
+ const shellTool = tool({
424
+ name: 'run_shell',
425
+ description: 'Execute shell commands safely',
426
+ parameters: z.object({
427
+ command: z.string(),
428
+ }),
429
+ sandbox: {
430
+ type: 'docker',
431
+ image: 'ubuntu:22.04',
432
+ resources: { memory: '256MB' },
433
+ network: { mode: 'none' },
434
+ },
435
+ timeout: 30000,
436
+ execute: async ({ command }) => command,
65
437
  });
66
438
 
67
- // Uses Docker if available, falls back to native
68
- const result = await manager.execute(request);
439
+ const cog = new Cogitator({
440
+ sandbox: {
441
+ pool: { maxSize: 5 },
442
+ },
443
+ });
69
444
  ```
70
445
 
71
- ### Security Features
446
+ ---
447
+
448
+ ## Examples
449
+
450
+ ### Run Python Code
72
451
 
73
- - Network isolation (`NetworkMode: 'none'`)
74
- - Dropped capabilities (`CapDrop: ['ALL']`)
75
- - No privilege escalation (`SecurityOpt: ['no-new-privileges']`)
76
- - Resource limits (memory, CPU, PIDs)
77
- - Timeout enforcement
452
+ ```typescript
453
+ const result = await manager.execute(
454
+ {
455
+ command: [
456
+ 'python',
457
+ '-c',
458
+ `
459
+ import json
460
+ data = {"sum": 2 + 2}
461
+ print(json.dumps(data))
462
+ `,
463
+ ],
464
+ },
465
+ {
466
+ type: 'docker',
467
+ image: 'python:3.11-alpine',
468
+ timeout: 10_000,
469
+ }
470
+ );
78
471
 
79
- ## Documentation
472
+ const output = JSON.parse(result.data!.stdout);
473
+ console.log(output.sum);
474
+ ```
475
+
476
+ ### Run Node.js Code
477
+
478
+ ```typescript
479
+ const result = await manager.execute(
480
+ {
481
+ command: ['node', '-e', 'console.log(JSON.stringify({result: 42}))'],
482
+ },
483
+ {
484
+ type: 'docker',
485
+ image: 'node:20-alpine',
486
+ resources: { memory: '128MB' },
487
+ }
488
+ );
489
+ ```
490
+
491
+ ### Run Shell Commands
492
+
493
+ ```typescript
494
+ const result = await manager.execute(
495
+ {
496
+ command: ['sh', '-c', 'ls -la /workspace && pwd'],
497
+ cwd: '/workspace',
498
+ },
499
+ {
500
+ type: 'docker',
501
+ image: 'alpine:3.19',
502
+ }
503
+ );
504
+ ```
505
+
506
+ ### Handle Timeouts
507
+
508
+ ```typescript
509
+ const result = await manager.execute(
510
+ { command: ['sleep', '60'] },
511
+ { type: 'docker', image: 'alpine', timeout: 5000 }
512
+ );
513
+
514
+ if (result.data?.timedOut) {
515
+ console.log('Command timed out');
516
+ }
517
+ ```
518
+
519
+ ### Check Exit Codes
520
+
521
+ ```typescript
522
+ const result = await manager.execute(
523
+ { command: ['sh', '-c', 'exit 42'] },
524
+ { type: 'docker', image: 'alpine' }
525
+ );
526
+
527
+ console.log('Exit code:', result.data?.exitCode);
528
+ ```
80
529
 
81
- See the [Cogitator documentation](https://github.com/eL1fe/cogitator) for full API reference.
530
+ ---
82
531
 
83
532
  ## License
84
533
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cogitator-ai/sandbox",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Sandbox execution for Cogitator agents (Docker and WASM)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -18,7 +18,7 @@
18
18
  "@types/dockerode": "^3.3.31",
19
19
  "@types/node": "^25.0.0",
20
20
  "nanoid": "^5.0.4",
21
- "@cogitator-ai/types": "0.3.1"
21
+ "@cogitator-ai/types": "0.4.0"
22
22
  },
23
23
  "optionalDependencies": {
24
24
  "@extism/extism": "^1.0.3",