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 +27 -16
- package/dist/cli.js +94 -21
- package/dist/docker/Dockerfile +4 -2
- package/dist/docker/seccomp-profile.json +67 -0
- package/dist/index.js +79 -11
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/engine/docker.d.ts +3 -0
- package/dist/src/engine/docker.d.ts.map +1 -1
- package/dist/src/engine/pool.d.ts +3 -2
- package/dist/src/engine/pool.d.ts.map +1 -1
- package/dist/src/types.d.ts +20 -0
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +8 -2
- package/schema/isol8.config.schema.json +20 -0
package/README.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# isol8
|
|
2
2
|
|
|
3
|
+
[](https://github.com/Illusion47586/isol8/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/Illusion47586/isol8/actions)
|
|
5
|
+
[](https://www.npmjs.com/package/isol8)
|
|
6
|
+
[](./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); // ~
|
|
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 |
|
|
327
|
-
| Node.js |
|
|
328
|
-
| Bun |
|
|
329
|
-
| Deno |
|
|
330
|
-
| Bash |
|
|
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 |
|
|
339
|
-
| Node.js |
|
|
340
|
-
| Bun |
|
|
341
|
-
| Deno |
|
|
342
|
-
| Bash |
|
|
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 |
|
|
351
|
-
| Node.js |
|
|
352
|
-
| Bun |
|
|
353
|
-
| Bash |
|
|
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 = (
|
|
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:
|
|
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.
|
|
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
|
|
57957
|
+
existsSync as existsSync4,
|
|
57885
57958
|
mkdirSync,
|
|
57886
|
-
readFileSync as
|
|
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
|
|
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 (
|
|
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 (!
|
|
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 (
|
|
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) =>
|
|
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 (!
|
|
61948
|
+
if (!existsSync4(filePath)) {
|
|
61876
61949
|
console.error(`[ERR] File not found: ${file}`);
|
|
61877
61950
|
process.exit(1);
|
|
61878
61951
|
}
|
|
61879
|
-
code =
|
|
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=
|
|
62035
|
+
//# debugId=BD6BAC9840A8A53E64756E2164756E21
|
package/dist/docker/Dockerfile
CHANGED
|
@@ -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:
|
|
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.
|
|
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=
|
|
1731
|
+
//# debugId=94A90BFCC4E9D3A764756E2164756E21
|
package/dist/src/config.d.ts.map
CHANGED
|
@@ -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,
|
|
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;
|
|
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.
|
|
41
|
-
*
|
|
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
|
|
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"}
|
package/dist/src/types.d.ts
CHANGED
|
@@ -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
|
package/dist/src/types.d.ts.map
CHANGED
|
@@ -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.
|
|
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
|
}
|