isol8 0.6.2 → 0.7.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.
package/README.md CHANGED
@@ -177,7 +177,7 @@ const result = await isol8.execute({
177
177
 
178
178
  console.log(result.stdout); // "Hello from isol8!"
179
179
  console.log(result.exitCode); // 0
180
- console.log(result.durationMs); // ~55-95ms (warm pool)
180
+ console.log(result.durationMs); // ~38-69ms (warm pool)
181
181
 
182
182
  await isol8.stop();
183
183
  ```
@@ -304,9 +304,14 @@ Add the `$schema` property to get autocompletion, validation, and inline documen
304
304
  "autoPrune": true,
305
305
  "maxContainerAgeMs": 3600000
306
306
  },
307
+ "dependencies": {
308
+ "python": ["numpy", "pandas"],
307
309
  "dependencies": {
308
310
  "python": ["numpy", "pandas"],
309
311
  "node": ["lodash"]
312
+ },
313
+ "security": {
314
+ "seccomp": "safety"
310
315
  }
311
316
  }
312
317
  ```
@@ -323,11 +328,11 @@ Each run creates a new `DockerIsol8` instance, executes, and tears down.
323
328
 
324
329
  | Runtime | Min | Median | Max | Avg |
325
330
  |---------|-----|--------|-----|-----|
326
- | Python | 148ms | 155ms | 414ms | 239ms |
327
- | Node.js | 152ms | 155ms | 186ms | 165ms |
328
- | Bun | 124ms | 145ms | 260ms | 176ms |
329
- | Deno | 339ms | 372ms | 626ms | 446ms |
330
- | Bash | 115ms | 123ms | 148ms | 128ms |
331
+ | Python | 111ms | 120ms | 188ms | 140ms |
332
+ | Node.js | 114ms | 126ms | 178ms | 130ms |
333
+ | Bun | 104ms | 121ms | 196ms | 139ms |
334
+ | Deno | 112ms | 122ms | 199ms | 139ms |
335
+ | Bash | 104ms | 114ms | 152ms | 121ms |
331
336
 
332
337
  ### Warm Pool (reused engine)
333
338
 
@@ -335,11 +340,11 @@ A single `DockerIsol8` instance reused across 5 runs. The first run is cold (poo
335
340
 
336
341
  | Runtime | Cold | Warm Avg | Warm Min | Speedup |
337
342
  |---------|------|----------|----------|---------|
338
- | Python | 285ms | 95ms | 89ms | 3.2x |
339
- | Node.js | 177ms | 91ms | 76ms | 2.3x |
340
- | Bun | 157ms | 72ms | 66ms | 2.4x |
341
- | Deno | 330ms | 264ms | 231ms | 1.4x |
342
- | Bash | 222ms | 68ms | 55ms | 4.0x |
343
+ | Python | 198ms | 56ms | 49ms | 4.1x |
344
+ | Node.js | 145ms | 69ms | 60ms | 2.4x |
345
+ | Bun | 152ms | 51ms | 45ms | 3.4x |
346
+ | Deno | 128ms | 62ms | 54ms | 2.4x |
347
+ | Bash | 124ms | 43ms | 38ms | 3.3x |
343
348
 
344
349
  ### Execution Phase Breakdown
345
350
 
@@ -347,10 +352,10 @@ Where time is spent in the container lifecycle (raw Docker API, no pool):
347
352
 
348
353
  | Runtime | Create | Start | Write | Exec Setup | Run | Cleanup | Total |
349
354
  |---------|--------|-------|-------|------------|-----|---------|-------|
350
- | Python | 41ms | 49ms | 17ms | 1ms | 40ms | 43ms | 190ms |
351
- | Node.js | 32ms | 63ms | 34ms | 1ms | 39ms | 43ms | 212ms |
352
- | Bun | 32ms | 56ms | 26ms | 1ms | 27ms | 44ms | 186ms |
353
- | Bash | 35ms | 69ms | 23ms | 1ms | 20ms | 48ms | 196ms |
355
+ | Python | 69ms | 52ms | 19ms | 1ms | 22ms | 51ms | 213ms |
356
+ | Node.js | 47ms | 41ms | 15ms | 1ms | 30ms | 36ms | 169ms |
357
+ | Bun | 55ms | 42ms | 15ms | 1ms | 18ms | 37ms | 166ms |
358
+ | Bash | 50ms | 50ms | 14ms | 1ms | 13ms | 43ms | 172ms |
354
359
 
355
360
  Run benchmarks yourself:
356
361
 
@@ -365,11 +370,12 @@ bun run bench:detailed # Phase breakdown
365
370
  | Layer | Protection |
366
371
  |-------|-----------|
367
372
  | **Filesystem** | Read-only root, writable `/sandbox` (tmpfs, 512MB, exec allowed), writable `/tmp` (tmpfs, 256MB, noexec) |
368
- | **Processes** | PID limit (default 64), `no-new-privileges` |
373
+ | **Processes** | PID limit (default 64), `no-new-privileges`, non-root `sandbox` user, all user processes killed between pool reuses |
369
374
  | **Resources** | CPU (1 core), memory (512MB), execution timeout (30s) |
370
375
  | **Network** | Disabled by default; optional proxy-based filtering |
371
376
  | **Output** | Truncated at 1MB; secrets masked from stdout/stderr |
372
377
  | **Isolation** | Each execution in its own container (ephemeral) or exec (persistent) |
378
+ | **Seccomp** | Default "safety" profile blocks dangerous syscalls (mount, swap, ptrace) but allows others for compatibility; configurable via `security.seccomp` |
373
379
 
374
380
  ### Container Filesystem
375
381
 
package/dist/cli.js CHANGED
@@ -6929,6 +6929,11 @@ var require_utils2 = __commonJS((exports, module) => {
6929
6929
  };
6930
6930
  });
6931
6931
 
6932
+ // node_modules/ssh2/lib/protocol/crypto/build/Release/sshcrypto.node
6933
+ var require_sshcrypto = __commonJS((exports, module) => {
6934
+ module.exports = __require("./sshcrypto-0209sx47.node");
6935
+ });
6936
+
6932
6937
  // node_modules/ssh2/lib/protocol/crypto/poly1305.js
6933
6938
  var require_poly1305 = __commonJS((exports, module) => {
6934
6939
  var __dirname = "/home/runner/work/isol8/isol8/node_modules/ssh2/lib/protocol/crypto", __filename = "/home/runner/work/isol8/isol8/node_modules/ssh2/lib/protocol/crypto/poly1305.js";
@@ -7415,7 +7420,7 @@ var require_crypto = __commonJS((exports, module) => {
7415
7420
  var ChaChaPolyDecipher;
7416
7421
  var GenericDecipher;
7417
7422
  try {
7418
- binding = (()=>{throw new Error("Cannot require module "+"./crypto/build/Release/sshcrypto.node");})();
7423
+ binding = require_sshcrypto();
7419
7424
  ({
7420
7425
  AESGCMCipher,
7421
7426
  ChaChaPolyCipher,
@@ -54794,6 +54799,10 @@ function mergeConfig(defaults, overrides) {
54794
54799
  ...defaults.dependencies,
54795
54800
  ...overrides.dependencies
54796
54801
  },
54802
+ security: {
54803
+ seccomp: overrides.security?.seccomp ?? defaults.security.seccomp,
54804
+ customProfilePath: overrides.security?.customProfilePath ?? defaults.security.customProfilePath
54805
+ },
54797
54806
  debug: overrides.debug ?? defaults.debug
54798
54807
  };
54799
54808
  }
@@ -54818,6 +54827,9 @@ var init_config = __esm(() => {
54818
54827
  maxContainerAgeMs: 3600000
54819
54828
  },
54820
54829
  dependencies: {},
54830
+ security: {
54831
+ seccomp: "strict"
54832
+ },
54821
54833
  debug: false
54822
54834
  };
54823
54835
  });
@@ -55075,6 +55087,15 @@ class ContainerPool {
55075
55087
  return;
55076
55088
  }
55077
55089
  try {
55090
+ const killExec = await container.exec({
55091
+ Cmd: ["sh", "-c", "pkill -9 -u sandbox 2>/dev/null; true"]
55092
+ });
55093
+ await killExec.start({ Detach: true });
55094
+ let killInfo = await killExec.inspect();
55095
+ while (killInfo.Running) {
55096
+ await new Promise((r) => setTimeout(r, 5));
55097
+ killInfo = await killExec.inspect();
55098
+ }
55078
55099
  const cleanExec = await container.exec({
55079
55100
  Cmd: ["sh", "-c", "rm -rf /sandbox/* /sandbox/.[!.]* 2>/dev/null; true"]
55080
55101
  });
@@ -55259,12 +55280,14 @@ __export(exports_docker, {
55259
55280
  DockerIsol8: () => DockerIsol8
55260
55281
  });
55261
55282
  import { randomUUID } from "node:crypto";
55283
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
55262
55284
  import { PassThrough } from "node:stream";
55263
55285
  async function writeFileViaExec(container, filePath, content) {
55264
55286
  const data = typeof content === "string" ? Buffer.from(content, "utf-8") : content;
55265
55287
  const b64 = data.toString("base64");
55266
55288
  const exec = await container.exec({
55267
- Cmd: ["sh", "-c", `printf '%s' '${b64}' | base64 -d > ${filePath}`]
55289
+ Cmd: ["sh", "-c", `printf '%s' '${b64}' | base64 -d > ${filePath}`],
55290
+ User: "sandbox"
55268
55291
  });
55269
55292
  await exec.start({ Detach: true });
55270
55293
  let info2 = await exec.inspect();
@@ -55280,7 +55303,8 @@ async function readFileViaExec(container, filePath) {
55280
55303
  const exec = await container.exec({
55281
55304
  Cmd: ["base64", filePath],
55282
55305
  AttachStdout: true,
55283
- AttachStderr: true
55306
+ AttachStderr: true,
55307
+ User: "sandbox"
55284
55308
  });
55285
55309
  const stream = await exec.start({ Tty: false });
55286
55310
  const chunks = [];
@@ -55375,7 +55399,8 @@ async function installPackages(container, runtime, packages) {
55375
55399
  Cmd: cmd,
55376
55400
  AttachStdout: true,
55377
55401
  AttachStderr: true,
55378
- Env: env2
55402
+ Env: env2,
55403
+ User: runtime === "bash" ? "root" : "sandbox"
55379
55404
  });
55380
55405
  const stream = await exec.start({ Detach: false, Tty: false });
55381
55406
  return new Promise((resolve2, reject) => {
@@ -55418,6 +55443,7 @@ class DockerIsol8 {
55418
55443
  semaphore;
55419
55444
  sandboxSize;
55420
55445
  tmpSize;
55446
+ security;
55421
55447
  persist;
55422
55448
  container = null;
55423
55449
  persistentRuntime = null;
@@ -55439,6 +55465,7 @@ class DockerIsol8 {
55439
55465
  this.sandboxSize = options.sandboxSize ?? "512m";
55440
55466
  this.tmpSize = options.tmpSize ?? "256m";
55441
55467
  this.persist = options.persist ?? false;
55468
+ this.security = options.security ?? { seccomp: "strict" };
55442
55469
  if (options.debug) {
55443
55470
  logger.setDebug(true);
55444
55471
  }
@@ -55544,7 +55571,8 @@ class DockerIsol8 {
55544
55571
  Env: this.buildEnv(req.env),
55545
55572
  AttachStdout: true,
55546
55573
  AttachStderr: true,
55547
- WorkingDir: SANDBOX_WORKDIR
55574
+ WorkingDir: SANDBOX_WORKDIR,
55575
+ User: "sandbox"
55548
55576
  });
55549
55577
  const execStream = await exec.start({ Tty: false });
55550
55578
  yield* this.streamExecOutput(execStream, exec, container, timeoutMs);
@@ -55623,7 +55651,8 @@ class DockerIsol8 {
55623
55651
  Env: this.buildEnv(req.env),
55624
55652
  AttachStdout: true,
55625
55653
  AttachStderr: true,
55626
- WorkingDir: SANDBOX_WORKDIR
55654
+ WorkingDir: SANDBOX_WORKDIR,
55655
+ User: "sandbox"
55627
55656
  });
55628
55657
  const start = performance.now();
55629
55658
  const execStream = await exec.start({ Tty: false });
@@ -55696,7 +55725,8 @@ class DockerIsol8 {
55696
55725
  Env: execEnv,
55697
55726
  AttachStdout: true,
55698
55727
  AttachStderr: true,
55699
- WorkingDir: SANDBOX_WORKDIR
55728
+ WorkingDir: SANDBOX_WORKDIR,
55729
+ User: "sandbox"
55700
55730
  });
55701
55731
  const start = performance.now();
55702
55732
  const execStream = await exec.start({ Tty: false });
@@ -55766,9 +55796,9 @@ class DockerIsol8 {
55766
55796
  ReadonlyRootfs: this.readonlyRootFs,
55767
55797
  Tmpfs: {
55768
55798
  "/tmp": `rw,noexec,nosuid,nodev,size=${this.tmpSize}`,
55769
- [SANDBOX_WORKDIR]: `rw,exec,nosuid,nodev,size=${this.sandboxSize}`
55799
+ [SANDBOX_WORKDIR]: `rw,exec,nosuid,nodev,size=${this.sandboxSize},uid=100,gid=101`
55770
55800
  },
55771
- SecurityOpt: ["no-new-privileges"]
55801
+ SecurityOpt: this.buildSecurityOpts()
55772
55802
  };
55773
55803
  if (this.network === "filtered") {
55774
55804
  config.NetworkMode = "bridge";
@@ -55777,6 +55807,43 @@ class DockerIsol8 {
55777
55807
  }
55778
55808
  return config;
55779
55809
  }
55810
+ buildSecurityOpts() {
55811
+ const opts = ["no-new-privileges"];
55812
+ if (this.security.seccomp === "unconfined") {
55813
+ opts.push("seccomp=unconfined");
55814
+ return opts;
55815
+ }
55816
+ if (this.security.seccomp === "custom" && this.security.customProfilePath) {
55817
+ try {
55818
+ const profile = readFileSync2(this.security.customProfilePath, "utf-8");
55819
+ opts.push(`seccomp=${profile}`);
55820
+ } catch (e) {
55821
+ logger.error(`Failed to load custom seccomp profile: ${e}`);
55822
+ }
55823
+ return opts;
55824
+ }
55825
+ try {
55826
+ const profile = this.loadDefaultSeccompProfile();
55827
+ if (profile) {
55828
+ opts.push(`seccomp=${profile}`);
55829
+ }
55830
+ } catch (e) {
55831
+ logger.error(`Failed to load default seccomp profile: ${e}`);
55832
+ }
55833
+ return opts;
55834
+ }
55835
+ loadDefaultSeccompProfile() {
55836
+ const devPath = new URL("../../docker/seccomp-profile.json", import.meta.url);
55837
+ if (existsSync2(devPath)) {
55838
+ return readFileSync2(devPath, "utf-8");
55839
+ }
55840
+ const prodPath = new URL("./docker/seccomp-profile.json", import.meta.url);
55841
+ if (existsSync2(prodPath)) {
55842
+ return readFileSync2(prodPath, "utf-8");
55843
+ }
55844
+ logger.warn("Could not locate default seccomp profile. Running without seccomp filter.");
55845
+ return null;
55846
+ }
55780
55847
  buildEnv(extra) {
55781
55848
  const env2 = [
55782
55849
  "PYTHONUNBUFFERED=1",
@@ -55958,7 +56025,7 @@ var package_default;
55958
56025
  var init_package = __esm(() => {
55959
56026
  package_default = {
55960
56027
  name: "isol8",
55961
- version: "0.6.1",
56028
+ version: "0.6.2",
55962
56029
  description: "Secure code execution engine for AI agents",
55963
56030
  author: "Illusion47586",
55964
56031
  license: "MIT",
@@ -57881,9 +57948,9 @@ var init_server = __esm(() => {
57881
57948
  // src/cli.ts
57882
57949
  import {
57883
57950
  chmodSync,
57884
- existsSync as existsSync3,
57951
+ existsSync as existsSync4,
57885
57952
  mkdirSync,
57886
- readFileSync as readFileSync2,
57953
+ readFileSync as readFileSync3,
57887
57954
  renameSync,
57888
57955
  unlinkSync,
57889
57956
  writeFileSync
@@ -61283,10 +61350,10 @@ init_docker();
61283
61350
 
61284
61351
  // src/engine/image-builder.ts
61285
61352
  init_runtime();
61286
- import { existsSync as existsSync2 } from "node:fs";
61353
+ import { existsSync as existsSync3 } from "node:fs";
61287
61354
  function resolveDockerDir() {
61288
61355
  const fromBundled = new URL("../docker", import.meta.url).pathname;
61289
- if (existsSync2(fromBundled)) {
61356
+ if (existsSync3(fromBundled)) {
61290
61357
  return fromBundled;
61291
61358
  }
61292
61359
  return new URL("../../docker", import.meta.url).pathname;
@@ -61638,7 +61705,7 @@ function getServerBinaryName() {
61638
61705
  return `isol8-server-${resolvedOs}-${resolvedArch}`;
61639
61706
  }
61640
61707
  async function getServerBinaryVersion(binaryPath) {
61641
- if (!existsSync3(binaryPath)) {
61708
+ if (!existsSync4(binaryPath)) {
61642
61709
  logger.debug(`[Serve] No binary found at ${binaryPath}`);
61643
61710
  return null;
61644
61711
  }
@@ -61683,7 +61750,7 @@ async function downloadServerBinary(binaryPath) {
61683
61750
  } catch (err) {
61684
61751
  spinner.fail("Failed to download server binary");
61685
61752
  const tmpPath = `${binaryPath}.tmp`;
61686
- if (existsSync3(tmpPath)) {
61753
+ if (existsSync4(tmpPath)) {
61687
61754
  unlinkSync(tmpPath);
61688
61755
  }
61689
61756
  throw err;
@@ -61737,7 +61804,7 @@ program2.command("config").description("Show the resolved isol8 configuration").
61737
61804
  join2(resolve2(process.cwd()), "isol8.config.json"),
61738
61805
  join2(homedir2(), ".isol8", "config.json")
61739
61806
  ];
61740
- const loadedFrom = searchPaths.find((p) => existsSync3(p));
61807
+ const loadedFrom = searchPaths.find((p) => existsSync4(p));
61741
61808
  logger.debug(`[Config] Config source: ${loadedFrom ?? "defaults"}`);
61742
61809
  logger.debug(`[Config] Resolved config: ${JSON.stringify(config)}`);
61743
61810
  if (opts.json) {
@@ -61872,11 +61939,11 @@ async function resolveRunInput(file, opts) {
61872
61939
  } else if (file) {
61873
61940
  const filePath = resolve2(file);
61874
61941
  logger.debug(`[Run] Reading file: ${filePath}`);
61875
- if (!existsSync3(filePath)) {
61942
+ if (!existsSync4(filePath)) {
61876
61943
  console.error(`[ERR] File not found: ${file}`);
61877
61944
  process.exit(1);
61878
61945
  }
61879
- code = readFileSync2(filePath, "utf-8");
61946
+ code = readFileSync3(filePath, "utf-8");
61880
61947
  if (opts.runtime) {
61881
61948
  runtime = opts.runtime;
61882
61949
  logger.debug(`[Run] Runtime specified: ${runtime}`);
@@ -61959,4 +62026,4 @@ if (!process.argv.slice(2).length) {
61959
62026
  }
61960
62027
  program2.parse();
61961
62028
 
61962
- //# debugId=21709D38E9A7C3B264756E2164756E21
62029
+ //# debugId=F86C7DBAE803AC0664756E2164756E21
@@ -1,6 +1,7 @@
1
1
  # ── Base ──────────────────────────────────────────────────────────────
2
2
  FROM alpine:3.21 AS base
3
- RUN apk add --no-cache tini curl ca-certificates
3
+ RUN apk add --no-cache tini curl ca-certificates \
4
+ && addgroup -S sandbox && adduser -S sandbox -G sandbox -h /sandbox
4
5
  COPY proxy.mjs /usr/local/bin/proxy.mjs
5
6
  RUN chmod +x /usr/local/bin/proxy.mjs
6
7
  WORKDIR /sandbox
@@ -26,7 +27,8 @@ CMD ["bun"]
26
27
 
27
28
  # ── Deno ──────────────────────────────────────────────────────────────
28
29
  FROM denoland/deno:alpine AS deno
29
- RUN apk add --no-cache tini curl ca-certificates
30
+ RUN apk add --no-cache tini curl ca-certificates \
31
+ && addgroup -S sandbox && adduser -S sandbox -G sandbox -h /sandbox
30
32
  COPY proxy.mjs /usr/local/bin/proxy.mjs
31
33
  RUN chmod +x /usr/local/bin/proxy.mjs
32
34
  WORKDIR /sandbox
@@ -0,0 +1,67 @@
1
+ {
2
+ "defaultAction": "SCMP_ACT_ALLOW",
3
+ "architectures": [
4
+ "SCMP_ARCH_X86_64",
5
+ "SCMP_ARCH_X86",
6
+ "SCMP_ARCH_X32",
7
+ "SCMP_ARCH_AARCH64"
8
+ ],
9
+ "syscalls": [
10
+ {
11
+ "names": [
12
+ "acct",
13
+ "add_key",
14
+ "bpf",
15
+ "clock_adjtime",
16
+ "clock_settime",
17
+ "create_module",
18
+ "delete_module",
19
+ "finit_module",
20
+ "get_mempolicy",
21
+ "init_module",
22
+ "ioperm",
23
+ "iopl",
24
+ "kcmp",
25
+ "kexec_file_load",
26
+ "kexec_load",
27
+ "keyctl",
28
+ "lookup_dcookie",
29
+ "mbind",
30
+ "mount",
31
+ "move_pages",
32
+ "name_to_handle_at",
33
+ "open_by_handle_at",
34
+ "perf_event_open",
35
+ "pivot_root",
36
+ "process_vm_readv",
37
+ "process_vm_writev",
38
+ "ptrace",
39
+ "query_module",
40
+ "quotactl",
41
+ "reboot",
42
+ "request_key",
43
+ "set_mempolicy",
44
+ "setns",
45
+ "settimeofday",
46
+ "stime",
47
+ "swapon",
48
+ "swapoff",
49
+ "sysfs",
50
+ "syslog",
51
+ "umount",
52
+ "umount2",
53
+ "unshare",
54
+ "uselib",
55
+ "userfaultfd",
56
+ "ustat",
57
+ "vm86",
58
+ "vm86old"
59
+ ],
60
+ "action": "SCMP_ACT_ERRNO",
61
+ "args": [],
62
+ "comment": "",
63
+ "includes": {},
64
+ "excludes": {}
65
+ }
66
+ ]
67
+ }
package/dist/index.js CHANGED
@@ -263,6 +263,15 @@ class ContainerPool {
263
263
  return;
264
264
  }
265
265
  try {
266
+ const killExec = await container.exec({
267
+ Cmd: ["sh", "-c", "pkill -9 -u sandbox 2>/dev/null; true"]
268
+ });
269
+ await killExec.start({ Detach: true });
270
+ let killInfo = await killExec.inspect();
271
+ while (killInfo.Running) {
272
+ await new Promise((r) => setTimeout(r, 5));
273
+ killInfo = await killExec.inspect();
274
+ }
266
275
  const cleanExec = await container.exec({
267
276
  Cmd: ["sh", "-c", "rm -rf /sandbox/* /sandbox/.[!.]* 2>/dev/null; true"]
268
277
  });
@@ -439,13 +448,15 @@ __export(exports_docker, {
439
448
  DockerIsol8: () => DockerIsol8
440
449
  });
441
450
  import { randomUUID } from "node:crypto";
451
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
442
452
  import { PassThrough } from "node:stream";
443
453
  import Docker from "dockerode";
444
454
  async function writeFileViaExec(container, filePath, content) {
445
455
  const data = typeof content === "string" ? Buffer.from(content, "utf-8") : content;
446
456
  const b64 = data.toString("base64");
447
457
  const exec = await container.exec({
448
- Cmd: ["sh", "-c", `printf '%s' '${b64}' | base64 -d > ${filePath}`]
458
+ Cmd: ["sh", "-c", `printf '%s' '${b64}' | base64 -d > ${filePath}`],
459
+ User: "sandbox"
449
460
  });
450
461
  await exec.start({ Detach: true });
451
462
  let info = await exec.inspect();
@@ -461,7 +472,8 @@ async function readFileViaExec(container, filePath) {
461
472
  const exec = await container.exec({
462
473
  Cmd: ["base64", filePath],
463
474
  AttachStdout: true,
464
- AttachStderr: true
475
+ AttachStderr: true,
476
+ User: "sandbox"
465
477
  });
466
478
  const stream = await exec.start({ Tty: false });
467
479
  const chunks = [];
@@ -556,7 +568,8 @@ async function installPackages(container, runtime, packages) {
556
568
  Cmd: cmd,
557
569
  AttachStdout: true,
558
570
  AttachStderr: true,
559
- Env: env
571
+ Env: env,
572
+ User: runtime === "bash" ? "root" : "sandbox"
560
573
  });
561
574
  const stream = await exec.start({ Detach: false, Tty: false });
562
575
  return new Promise((resolve2, reject) => {
@@ -599,6 +612,7 @@ class DockerIsol8 {
599
612
  semaphore;
600
613
  sandboxSize;
601
614
  tmpSize;
615
+ security;
602
616
  persist;
603
617
  container = null;
604
618
  persistentRuntime = null;
@@ -620,6 +634,7 @@ class DockerIsol8 {
620
634
  this.sandboxSize = options.sandboxSize ?? "512m";
621
635
  this.tmpSize = options.tmpSize ?? "256m";
622
636
  this.persist = options.persist ?? false;
637
+ this.security = options.security ?? { seccomp: "strict" };
623
638
  if (options.debug) {
624
639
  logger.setDebug(true);
625
640
  }
@@ -725,7 +740,8 @@ class DockerIsol8 {
725
740
  Env: this.buildEnv(req.env),
726
741
  AttachStdout: true,
727
742
  AttachStderr: true,
728
- WorkingDir: SANDBOX_WORKDIR
743
+ WorkingDir: SANDBOX_WORKDIR,
744
+ User: "sandbox"
729
745
  });
730
746
  const execStream = await exec.start({ Tty: false });
731
747
  yield* this.streamExecOutput(execStream, exec, container, timeoutMs);
@@ -804,7 +820,8 @@ class DockerIsol8 {
804
820
  Env: this.buildEnv(req.env),
805
821
  AttachStdout: true,
806
822
  AttachStderr: true,
807
- WorkingDir: SANDBOX_WORKDIR
823
+ WorkingDir: SANDBOX_WORKDIR,
824
+ User: "sandbox"
808
825
  });
809
826
  const start = performance.now();
810
827
  const execStream = await exec.start({ Tty: false });
@@ -877,7 +894,8 @@ class DockerIsol8 {
877
894
  Env: execEnv,
878
895
  AttachStdout: true,
879
896
  AttachStderr: true,
880
- WorkingDir: SANDBOX_WORKDIR
897
+ WorkingDir: SANDBOX_WORKDIR,
898
+ User: "sandbox"
881
899
  });
882
900
  const start = performance.now();
883
901
  const execStream = await exec.start({ Tty: false });
@@ -947,9 +965,9 @@ class DockerIsol8 {
947
965
  ReadonlyRootfs: this.readonlyRootFs,
948
966
  Tmpfs: {
949
967
  "/tmp": `rw,noexec,nosuid,nodev,size=${this.tmpSize}`,
950
- [SANDBOX_WORKDIR]: `rw,exec,nosuid,nodev,size=${this.sandboxSize}`
968
+ [SANDBOX_WORKDIR]: `rw,exec,nosuid,nodev,size=${this.sandboxSize},uid=100,gid=101`
951
969
  },
952
- SecurityOpt: ["no-new-privileges"]
970
+ SecurityOpt: this.buildSecurityOpts()
953
971
  };
954
972
  if (this.network === "filtered") {
955
973
  config.NetworkMode = "bridge";
@@ -958,6 +976,43 @@ class DockerIsol8 {
958
976
  }
959
977
  return config;
960
978
  }
979
+ buildSecurityOpts() {
980
+ const opts = ["no-new-privileges"];
981
+ if (this.security.seccomp === "unconfined") {
982
+ opts.push("seccomp=unconfined");
983
+ return opts;
984
+ }
985
+ if (this.security.seccomp === "custom" && this.security.customProfilePath) {
986
+ try {
987
+ const profile = readFileSync2(this.security.customProfilePath, "utf-8");
988
+ opts.push(`seccomp=${profile}`);
989
+ } catch (e) {
990
+ logger.error(`Failed to load custom seccomp profile: ${e}`);
991
+ }
992
+ return opts;
993
+ }
994
+ try {
995
+ const profile = this.loadDefaultSeccompProfile();
996
+ if (profile) {
997
+ opts.push(`seccomp=${profile}`);
998
+ }
999
+ } catch (e) {
1000
+ logger.error(`Failed to load default seccomp profile: ${e}`);
1001
+ }
1002
+ return opts;
1003
+ }
1004
+ loadDefaultSeccompProfile() {
1005
+ const devPath = new URL("../../docker/seccomp-profile.json", import.meta.url);
1006
+ if (existsSync2(devPath)) {
1007
+ return readFileSync2(devPath, "utf-8");
1008
+ }
1009
+ const prodPath = new URL("./docker/seccomp-profile.json", import.meta.url);
1010
+ if (existsSync2(prodPath)) {
1011
+ return readFileSync2(prodPath, "utf-8");
1012
+ }
1013
+ logger.warn("Could not locate default seccomp profile. Running without seccomp filter.");
1014
+ return null;
1015
+ }
961
1016
  buildEnv(extra) {
962
1017
  const env = [
963
1018
  "PYTHONUNBUFFERED=1",
@@ -1282,6 +1337,9 @@ var DEFAULT_CONFIG = {
1282
1337
  maxContainerAgeMs: 3600000
1283
1338
  },
1284
1339
  dependencies: {},
1340
+ security: {
1341
+ seccomp: "strict"
1342
+ },
1285
1343
  debug: false
1286
1344
  };
1287
1345
  function loadConfig(cwd) {
@@ -1317,6 +1375,10 @@ function mergeConfig(defaults, overrides) {
1317
1375
  ...defaults.dependencies,
1318
1376
  ...overrides.dependencies
1319
1377
  },
1378
+ security: {
1379
+ seccomp: overrides.security?.seccomp ?? defaults.security.seccomp,
1380
+ customProfilePath: overrides.security?.customProfilePath ?? defaults.security.customProfilePath
1381
+ },
1320
1382
  debug: overrides.debug ?? defaults.debug
1321
1383
  };
1322
1384
  }
@@ -1331,7 +1393,7 @@ init_logger();
1331
1393
  // package.json
1332
1394
  var package_default = {
1333
1395
  name: "isol8",
1334
- version: "0.6.1",
1396
+ version: "0.6.2",
1335
1397
  description: "Secure code execution engine for AI agents",
1336
1398
  author: "Illusion47586",
1337
1399
  license: "MIT",
@@ -1660,4 +1722,4 @@ export {
1660
1722
  BunAdapter
1661
1723
  };
1662
1724
 
1663
- //# debugId=042AB36FB522926664756E2164756E21
1725
+ //# debugId=1AFCD54347509D5A64756E2164756E21
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C;;;GAGG;AACH,QAAA,MAAM,cAAc,EAAE,WAoBrB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW,CAepD;AA8BD,OAAO,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C;;;GAGG;AACH,QAAA,MAAM,cAAc,EAAE,WAuBrB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW,CAepD;AAmCD,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -43,6 +43,7 @@ export declare class DockerIsol8 implements Isol8Engine {
43
43
  private readonly semaphore;
44
44
  private readonly sandboxSize;
45
45
  private readonly tmpSize;
46
+ private readonly security;
46
47
  private readonly persist;
47
48
  private container;
48
49
  private persistentRuntime;
@@ -96,6 +97,8 @@ export declare class DockerIsol8 implements Isol8Engine {
96
97
  private startPersistentContainer;
97
98
  private getAdapter;
98
99
  private buildHostConfig;
100
+ private buildSecurityOpts;
101
+ private loadDefaultSeccompProfile;
99
102
  private buildEnv;
100
103
  private streamExecOutput;
101
104
  private collectExecOutput;
@@ -1 +1 @@
1
- {"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../../src/engine/docker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,MAAM,MAAM,WAAW,CAAC;AAG/B,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,WAAW,EAEX,YAAY,EAGZ,WAAW,EACZ,MAAM,UAAU,CAAC;AAgPlB,2HAA2H;AAC3H,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACtD,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,WAAY,YAAW,WAAW;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAY;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAsB;IACrD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAElC,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,IAAI,CAA8B;IAE1C;;;OAGG;gBACS,OAAO,GAAE,kBAAuB,EAAE,aAAa,SAAK;IAuBhE;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B,kFAAkF;IAC5E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB3B;;;OAGG;IACG,OAAO,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IAW9D;;;;;;;OAOG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYpE;;;;;;OAMG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAmB5C,6GAA6G;IAC7G,IAAI,WAAW,IAAI,MAAM,GAAG,IAAI,CAE/B;IAED;;;OAGG;IACI,aAAa,CAAC,GAAG,EAAE,gBAAgB,GAAG,aAAa,CAAC,WAAW,CAAC;YAoFzD,YAAY;YAcZ,gBAAgB;YAwGhB,iBAAiB;YA6FjB,aAAa;YAkBb,oBAAoB;YASpB,wBAAwB;IA2BtC,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,eAAe;IAsBvB,OAAO,CAAC,QAAQ;YAmCD,gBAAgB;YA8EjB,iBAAiB;IA8D/B,OAAO,CAAC,iBAAiB;IAYzB;;;;;;;;;;;;;;;;;;;;OAoBG;WACU,OAAO,CAClB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CA2BlE"}
1
+ {"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../../src/engine/docker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,MAAM,MAAM,WAAW,CAAC;AAG/B,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,WAAW,EAEX,YAAY,EAIZ,WAAW,EACZ,MAAM,UAAU,CAAC;AAoPlB,2HAA2H;AAC3H,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACtD,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,WAAY,YAAW,WAAW;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAY;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAsB;IACrD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAElC,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,IAAI,CAA8B;IAE1C;;;OAGG;gBACS,OAAO,GAAE,kBAAuB,EAAE,aAAa,SAAK;IAwBhE;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B,kFAAkF;IAC5E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB3B;;;OAGG;IACG,OAAO,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IAW9D;;;;;;;OAOG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYpE;;;;;;OAMG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAmB5C,6GAA6G;IAC7G,IAAI,WAAW,IAAI,MAAM,GAAG,IAAI,CAE/B;IAED;;;OAGG;IACI,aAAa,CAAC,GAAG,EAAE,gBAAgB,GAAG,aAAa,CAAC,WAAW,CAAC;YAqFzD,YAAY;YAcZ,gBAAgB;YAyGhB,iBAAiB;YA8FjB,aAAa;YAkBb,oBAAoB;YASpB,wBAAwB;IA2BtC,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,eAAe;IAsBvB,OAAO,CAAC,iBAAiB;IA+BzB,OAAO,CAAC,yBAAyB;IAyBjC,OAAO,CAAC,QAAQ;YAmCD,gBAAgB;YA8EjB,iBAAiB;IA8D/B,OAAO,CAAC,iBAAiB;IAYzB;;;;;;;;;;;;;;;;;;;;OAoBG;WACU,OAAO,CAClB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CA2BlE"}
@@ -37,8 +37,9 @@ export declare class ContainerPool {
37
37
  */
38
38
  acquire(image: string): Promise<Docker.Container>;
39
39
  /**
40
- * Return a container to the pool after use. The container's /sandbox
41
- * tmpfs is wiped clean so it's ready for the next execution.
40
+ * Return a container to the pool after use. All processes owned by the
41
+ * `sandbox` user are killed, and the `/sandbox` tmpfs is wiped clean
42
+ * so the container is ready for the next execution.
42
43
  * If the pool is full, the container is destroyed instead.
43
44
  */
44
45
  release(container: Docker.Container, image: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../../src/engine/pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,MAAM,MAAM,WAAW,CAAC;AAGpC,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC;CAC7D;AAOD;;;GAGG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA+C;IAC7E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IACxD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA4B;gBAEtD,OAAO,EAAE,WAAW;IAMhC;;;;OAIG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;IAcvD;;;;OAIG;IACG,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BxE;;;OAGG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBxC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAgBd,eAAe;IAW7B,2DAA2D;IAC3D,OAAO,CAAC,SAAS;CAuClB"}
1
+ {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../../src/engine/pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,MAAM,MAAM,WAAW,CAAC;AAGpC,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC;CAC7D;AAOD;;;GAGG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA+C;IAC7E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IACxD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA4B;gBAEtD,OAAO,EAAE,WAAW;IAMhC;;;;OAIG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;IAcvD;;;;;OAKG;IACG,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8CxE;;;OAGG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBxC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAgBd,eAAe;IAW7B,2DAA2D;IAC3D,OAAO,CAAC,SAAS;CAuClB"}
@@ -156,6 +156,8 @@ export interface Isol8Options {
156
156
  * @default false
157
157
  */
158
158
  persist?: boolean;
159
+ /** Security settings. */
160
+ security?: SecurityConfig;
159
161
  }
160
162
  /**
161
163
  * The core isol8 engine abstraction. Both {@link DockerIsol8} and {@link RemoteIsol8}
@@ -245,6 +247,20 @@ export interface Isol8Dependencies {
245
247
  /** Bash packages to install via apk (Alpine). */
246
248
  bash?: string[];
247
249
  }
250
+ /**
251
+ * Security configuration for the execution environment.
252
+ */
253
+ export interface SecurityConfig {
254
+ /**
255
+ * Seccomp profile mode.
256
+ * - "strict": Use the default strict profile (default).
257
+ * - "unconfined": Do not apply any seccomp profile.
258
+ * - "custom": Use the profile at `customProfilePath`.
259
+ */
260
+ seccomp?: "strict" | "unconfined" | "custom";
261
+ /** Path to a custom seccomp profile JSON file. Required if seccomp is "custom". */
262
+ customProfilePath?: string;
263
+ }
248
264
  /**
249
265
  * Top-level configuration schema for isol8.
250
266
  *
@@ -265,6 +281,8 @@ export interface Isol8Config {
265
281
  cleanup: Isol8Cleanup;
266
282
  /** Runtime-specific packages to bake into custom Docker images. */
267
283
  dependencies: Isol8Dependencies;
284
+ /** Security settings. */
285
+ security: SecurityConfig;
268
286
  /** Enable debug logging. @default false */
269
287
  debug: boolean;
270
288
  }
@@ -287,5 +305,7 @@ export interface Isol8UserConfig {
287
305
  cleanup?: Partial<Isol8Cleanup>;
288
306
  /** Runtime-specific packages to bake into custom Docker images. */
289
307
  dependencies?: Isol8Dependencies;
308
+ /** Security settings. */
309
+ security?: SecurityConfig;
290
310
  }
291
311
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isol8",
3
- "version": "0.6.2",
3
+ "version": "0.7.0",
4
4
  "description": "Secure code execution engine for AI agents",
5
5
  "author": "Illusion47586",
6
6
  "license": "MIT",
@@ -140,6 +140,10 @@
140
140
  }
141
141
  },
142
142
  "type": "object"
143
+ },
144
+ "security": {
145
+ "$ref": "#/definitions/SecurityConfig",
146
+ "description": "Security settings."
143
147
  }
144
148
  },
145
149
  "type": "object"
@@ -148,6 +152,22 @@
148
152
  "description": "Network access mode for isol8 containers.\n\n- `\"none\"` — All network access blocked (default, most secure).\n- `\"host\"` — Full host network access (use with caution).\n- `\"filtered\"` — HTTP/HTTPS traffic routed through a proxy that enforces whitelist/blacklist regex rules on hostnames.",
149
153
  "enum": ["none", "host", "filtered"],
150
154
  "type": "string"
155
+ },
156
+ "SecurityConfig": {
157
+ "additionalProperties": false,
158
+ "description": "Security configuration for the execution environment.",
159
+ "properties": {
160
+ "customProfilePath": {
161
+ "description": "Path to a custom seccomp profile JSON file. Required if seccomp is \"custom\".",
162
+ "type": "string"
163
+ },
164
+ "seccomp": {
165
+ "description": "Seccomp profile mode.\n- \"strict\": Use the default strict profile (default).\n- \"unconfined\": Do not apply any seccomp profile.\n- \"custom\": Use the profile at `customProfilePath`.",
166
+ "enum": ["strict", "unconfined", "custom"],
167
+ "type": "string"
168
+ }
169
+ },
170
+ "type": "object"
151
171
  }
152
172
  }
153
173
  }