isol8 0.6.2 → 0.8.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
@@ -1,5 +1,10 @@
1
1
  # isol8
2
2
 
3
+ [![CI](https://github.com/Illusion47586/isol8/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Illusion47586/isol8/actions/workflows/ci.yml)
4
+ [![Coverage](https://raw.githubusercontent.com/Illusion47586/isol8/main/coverage/coverage-badge.svg)](https://github.com/Illusion47586/isol8/actions)
5
+ [![npm](https://img.shields.io/npm/v/isol8)](https://www.npmjs.com/package/isol8)
6
+ [![license](https://img.shields.io/npm/l/isol8)](./LICENSE)
7
+
3
8
  Secure code execution engine for AI agents. Run untrusted Python, Node.js, Bun, Deno, and Bash code inside locked-down Docker containers with network filtering, resource limits, and output controls.
4
9
 
5
10
  ## Features
@@ -177,7 +182,7 @@ const result = await isol8.execute({
177
182
 
178
183
  console.log(result.stdout); // "Hello from isol8!"
179
184
  console.log(result.exitCode); // 0
180
- console.log(result.durationMs); // ~55-95ms (warm pool)
185
+ console.log(result.durationMs); // ~38-69ms (warm pool)
181
186
 
182
187
  await isol8.stop();
183
188
  ```
@@ -304,9 +309,14 @@ Add the `$schema` property to get autocompletion, validation, and inline documen
304
309
  "autoPrune": true,
305
310
  "maxContainerAgeMs": 3600000
306
311
  },
312
+ "dependencies": {
313
+ "python": ["numpy", "pandas"],
307
314
  "dependencies": {
308
315
  "python": ["numpy", "pandas"],
309
316
  "node": ["lodash"]
317
+ },
318
+ "security": {
319
+ "seccomp": "safety"
310
320
  }
311
321
  }
312
322
  ```
@@ -323,11 +333,11 @@ Each run creates a new `DockerIsol8` instance, executes, and tears down.
323
333
 
324
334
  | Runtime | Min | Median | Max | Avg |
325
335
  |---------|-----|--------|-----|-----|
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 |
336
+ | Python | 111ms | 120ms | 188ms | 140ms |
337
+ | Node.js | 114ms | 126ms | 178ms | 130ms |
338
+ | Bun | 104ms | 121ms | 196ms | 139ms |
339
+ | Deno | 112ms | 122ms | 199ms | 139ms |
340
+ | Bash | 104ms | 114ms | 152ms | 121ms |
331
341
 
332
342
  ### Warm Pool (reused engine)
333
343
 
@@ -335,11 +345,11 @@ A single `DockerIsol8` instance reused across 5 runs. The first run is cold (poo
335
345
 
336
346
  | Runtime | Cold | Warm Avg | Warm Min | Speedup |
337
347
  |---------|------|----------|----------|---------|
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 |
348
+ | Python | 198ms | 56ms | 49ms | 4.1x |
349
+ | Node.js | 145ms | 69ms | 60ms | 2.4x |
350
+ | Bun | 152ms | 51ms | 45ms | 3.4x |
351
+ | Deno | 128ms | 62ms | 54ms | 2.4x |
352
+ | Bash | 124ms | 43ms | 38ms | 3.3x |
343
353
 
344
354
  ### Execution Phase Breakdown
345
355
 
@@ -347,10 +357,10 @@ Where time is spent in the container lifecycle (raw Docker API, no pool):
347
357
 
348
358
  | Runtime | Create | Start | Write | Exec Setup | Run | Cleanup | Total |
349
359
  |---------|--------|-------|-------|------------|-----|---------|-------|
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 |
360
+ | Python | 69ms | 52ms | 19ms | 1ms | 22ms | 51ms | 213ms |
361
+ | Node.js | 47ms | 41ms | 15ms | 1ms | 30ms | 36ms | 169ms |
362
+ | Bun | 55ms | 42ms | 15ms | 1ms | 18ms | 37ms | 166ms |
363
+ | Bash | 50ms | 50ms | 14ms | 1ms | 13ms | 43ms | 172ms |
354
364
 
355
365
  Run benchmarks yourself:
356
366
 
@@ -365,11 +375,12 @@ bun run bench:detailed # Phase breakdown
365
375
  | Layer | Protection |
366
376
  |-------|-----------|
367
377
  | **Filesystem** | Read-only root, writable `/sandbox` (tmpfs, 512MB, exec allowed), writable `/tmp` (tmpfs, 256MB, noexec) |
368
- | **Processes** | PID limit (default 64), `no-new-privileges` |
378
+ | **Processes** | PID limit (default 64), `no-new-privileges`, non-root `sandbox` user, all user processes killed between pool reuses |
369
379
  | **Resources** | CPU (1 core), memory (512MB), execution timeout (30s) |
370
380
  | **Network** | Disabled by default; optional proxy-based filtering |
371
381
  | **Output** | Truncated at 1MB; secrets masked from stdout/stderr |
372
382
  | **Isolation** | Each execution in its own container (ephemeral) or exec (persistent) |
383
+ | **Seccomp** | Default "safety" profile blocks dangerous syscalls (mount, swap, ptrace) but allows others for compatibility; configurable via `security.seccomp` |
373
384
 
374
385
  ### Container Filesystem
375
386
 
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.7.0",
55962
56029
  description: "Secure code execution engine for AI agents",
55963
56030
  author: "Illusion47586",
55964
56031
  license: "MIT",
@@ -56019,6 +56086,8 @@ var init_package = __esm(() => {
56019
56086
  },
56020
56087
  devDependencies: {
56021
56088
  "@biomejs/biome": "^2.3.15",
56089
+ "@commitlint/cli": "^20.4.1",
56090
+ "@commitlint/config-conventional": "^20.4.1",
56022
56091
  "@semantic-release/changelog": "^6.0.3",
56023
56092
  "@semantic-release/exec": "^7.1.0",
56024
56093
  "@semantic-release/git": "^10.0.1",
@@ -56051,7 +56120,8 @@ var init_package = __esm(() => {
56051
56120
  }
56052
56121
  ],
56053
56122
  "simple-git-hooks": {
56054
- "pre-commit": "bun run lint-staged"
56123
+ "pre-commit": "bun run lint-staged",
56124
+ "commit-msg": "bunx commitlint --edit $1"
56055
56125
  },
56056
56126
  "lint-staged": {
56057
56127
  "*.{ts,tsx}": [
@@ -56061,6 +56131,9 @@ var init_package = __esm(() => {
56061
56131
  "src/types.ts": [
56062
56132
  "bash -c 'bun run schema'",
56063
56133
  "git add schema/isol8.config.schema.json"
56134
+ ],
56135
+ "*.{yaml,yml,json}": [
56136
+ "ultracite fix"
56064
56137
  ]
56065
56138
  }
56066
56139
  };
@@ -57881,9 +57954,9 @@ var init_server = __esm(() => {
57881
57954
  // src/cli.ts
57882
57955
  import {
57883
57956
  chmodSync,
57884
- existsSync as existsSync3,
57957
+ existsSync as existsSync4,
57885
57958
  mkdirSync,
57886
- readFileSync as readFileSync2,
57959
+ readFileSync as readFileSync3,
57887
57960
  renameSync,
57888
57961
  unlinkSync,
57889
57962
  writeFileSync
@@ -61283,10 +61356,10 @@ init_docker();
61283
61356
 
61284
61357
  // src/engine/image-builder.ts
61285
61358
  init_runtime();
61286
- import { existsSync as existsSync2 } from "node:fs";
61359
+ import { existsSync as existsSync3 } from "node:fs";
61287
61360
  function resolveDockerDir() {
61288
61361
  const fromBundled = new URL("../docker", import.meta.url).pathname;
61289
- if (existsSync2(fromBundled)) {
61362
+ if (existsSync3(fromBundled)) {
61290
61363
  return fromBundled;
61291
61364
  }
61292
61365
  return new URL("../../docker", import.meta.url).pathname;
@@ -61638,7 +61711,7 @@ function getServerBinaryName() {
61638
61711
  return `isol8-server-${resolvedOs}-${resolvedArch}`;
61639
61712
  }
61640
61713
  async function getServerBinaryVersion(binaryPath) {
61641
- if (!existsSync3(binaryPath)) {
61714
+ if (!existsSync4(binaryPath)) {
61642
61715
  logger.debug(`[Serve] No binary found at ${binaryPath}`);
61643
61716
  return null;
61644
61717
  }
@@ -61683,7 +61756,7 @@ async function downloadServerBinary(binaryPath) {
61683
61756
  } catch (err) {
61684
61757
  spinner.fail("Failed to download server binary");
61685
61758
  const tmpPath = `${binaryPath}.tmp`;
61686
- if (existsSync3(tmpPath)) {
61759
+ if (existsSync4(tmpPath)) {
61687
61760
  unlinkSync(tmpPath);
61688
61761
  }
61689
61762
  throw err;
@@ -61737,7 +61810,7 @@ program2.command("config").description("Show the resolved isol8 configuration").
61737
61810
  join2(resolve2(process.cwd()), "isol8.config.json"),
61738
61811
  join2(homedir2(), ".isol8", "config.json")
61739
61812
  ];
61740
- const loadedFrom = searchPaths.find((p) => existsSync3(p));
61813
+ const loadedFrom = searchPaths.find((p) => existsSync4(p));
61741
61814
  logger.debug(`[Config] Config source: ${loadedFrom ?? "defaults"}`);
61742
61815
  logger.debug(`[Config] Resolved config: ${JSON.stringify(config)}`);
61743
61816
  if (opts.json) {
@@ -61872,11 +61945,11 @@ async function resolveRunInput(file, opts) {
61872
61945
  } else if (file) {
61873
61946
  const filePath = resolve2(file);
61874
61947
  logger.debug(`[Run] Reading file: ${filePath}`);
61875
- if (!existsSync3(filePath)) {
61948
+ if (!existsSync4(filePath)) {
61876
61949
  console.error(`[ERR] File not found: ${file}`);
61877
61950
  process.exit(1);
61878
61951
  }
61879
- code = readFileSync2(filePath, "utf-8");
61952
+ code = readFileSync3(filePath, "utf-8");
61880
61953
  if (opts.runtime) {
61881
61954
  runtime = opts.runtime;
61882
61955
  logger.debug(`[Run] Runtime specified: ${runtime}`);
@@ -61959,4 +62032,4 @@ if (!process.argv.slice(2).length) {
61959
62032
  }
61960
62033
  program2.parse();
61961
62034
 
61962
- //# debugId=21709D38E9A7C3B264756E2164756E21
62035
+ //# debugId=BD6BAC9840A8A53E64756E2164756E21
@@ -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.7.0",
1335
1397
  description: "Secure code execution engine for AI agents",
1336
1398
  author: "Illusion47586",
1337
1399
  license: "MIT",
@@ -1392,6 +1454,8 @@ var package_default = {
1392
1454
  },
1393
1455
  devDependencies: {
1394
1456
  "@biomejs/biome": "^2.3.15",
1457
+ "@commitlint/cli": "^20.4.1",
1458
+ "@commitlint/config-conventional": "^20.4.1",
1395
1459
  "@semantic-release/changelog": "^6.0.3",
1396
1460
  "@semantic-release/exec": "^7.1.0",
1397
1461
  "@semantic-release/git": "^10.0.1",
@@ -1424,7 +1488,8 @@ var package_default = {
1424
1488
  }
1425
1489
  ],
1426
1490
  "simple-git-hooks": {
1427
- "pre-commit": "bun run lint-staged"
1491
+ "pre-commit": "bun run lint-staged",
1492
+ "commit-msg": "bunx commitlint --edit $1"
1428
1493
  },
1429
1494
  "lint-staged": {
1430
1495
  "*.{ts,tsx}": [
@@ -1434,6 +1499,9 @@ var package_default = {
1434
1499
  "src/types.ts": [
1435
1500
  "bash -c 'bun run schema'",
1436
1501
  "git add schema/isol8.config.schema.json"
1502
+ ],
1503
+ "*.{yaml,yml,json}": [
1504
+ "ultracite fix"
1437
1505
  ]
1438
1506
  }
1439
1507
  };
@@ -1660,4 +1728,4 @@ export {
1660
1728
  BunAdapter
1661
1729
  };
1662
1730
 
1663
- //# debugId=042AB36FB522926664756E2164756E21
1731
+ //# debugId=94A90BFCC4E9D3A764756E2164756E21
@@ -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.8.0",
4
4
  "description": "Secure code execution engine for AI agents",
5
5
  "author": "Illusion47586",
6
6
  "license": "MIT",
@@ -61,6 +61,8 @@
61
61
  },
62
62
  "devDependencies": {
63
63
  "@biomejs/biome": "^2.3.15",
64
+ "@commitlint/cli": "^20.4.1",
65
+ "@commitlint/config-conventional": "^20.4.1",
64
66
  "@semantic-release/changelog": "^6.0.3",
65
67
  "@semantic-release/exec": "^7.1.0",
66
68
  "@semantic-release/git": "^10.0.1",
@@ -93,7 +95,8 @@
93
95
  }
94
96
  ],
95
97
  "simple-git-hooks": {
96
- "pre-commit": "bun run lint-staged"
98
+ "pre-commit": "bun run lint-staged",
99
+ "commit-msg": "bunx commitlint --edit $1"
97
100
  },
98
101
  "lint-staged": {
99
102
  "*.{ts,tsx}": [
@@ -103,6 +106,9 @@
103
106
  "src/types.ts": [
104
107
  "bash -c 'bun run schema'",
105
108
  "git add schema/isol8.config.schema.json"
109
+ ],
110
+ "*.{yaml,yml,json}": [
111
+ "ultracite fix"
106
112
  ]
107
113
  }
108
114
  }
@@ -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
  }