isol8 0.6.1 → 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 +23 -16
- package/dist/cli.js +201 -34
- package/dist/docker/Dockerfile +4 -2
- package/dist/docker/seccomp-profile.json +67 -0
- package/dist/index.js +106 -10
- 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/server/index.d.ts +2 -0
- package/dist/src/server/index.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 +2 -1
- package/schema/isol8.config.schema.json +20 -0
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
|
}
|
|
@@ -1327,10 +1389,11 @@ init_runtime();
|
|
|
1327
1389
|
|
|
1328
1390
|
// src/server/index.ts
|
|
1329
1391
|
import { Hono } from "hono";
|
|
1392
|
+
init_logger();
|
|
1330
1393
|
// package.json
|
|
1331
1394
|
var package_default = {
|
|
1332
1395
|
name: "isol8",
|
|
1333
|
-
version: "0.6.
|
|
1396
|
+
version: "0.6.2",
|
|
1334
1397
|
description: "Secure code execution engine for AI agents",
|
|
1335
1398
|
author: "Illusion47586",
|
|
1336
1399
|
license: "MIT",
|
|
@@ -1392,6 +1455,7 @@ var package_default = {
|
|
|
1392
1455
|
devDependencies: {
|
|
1393
1456
|
"@biomejs/biome": "^2.3.15",
|
|
1394
1457
|
"@semantic-release/changelog": "^6.0.3",
|
|
1458
|
+
"@semantic-release/exec": "^7.1.0",
|
|
1395
1459
|
"@semantic-release/git": "^10.0.1",
|
|
1396
1460
|
"@semantic-release/github": "^12.0.6",
|
|
1397
1461
|
"@semantic-release/npm": "^13.1.4",
|
|
@@ -1462,13 +1526,21 @@ var sessions = new Map;
|
|
|
1462
1526
|
async function createServer(options) {
|
|
1463
1527
|
const { DockerIsol8: DockerIsol82 } = await Promise.resolve().then(() => (init_docker(), exports_docker));
|
|
1464
1528
|
await Promise.resolve().then(() => (init_runtime(), exports_runtime));
|
|
1529
|
+
if (options.debug) {
|
|
1530
|
+
logger.setDebug(true);
|
|
1531
|
+
}
|
|
1465
1532
|
const config = loadConfig();
|
|
1533
|
+
logger.debug("[Server] Config loaded");
|
|
1534
|
+
logger.debug(`[Server] Max concurrent: ${config.maxConcurrent}`);
|
|
1535
|
+
logger.debug(`[Server] Auto-prune: ${config.cleanup.autoPrune}`);
|
|
1466
1536
|
const app = new Hono;
|
|
1467
1537
|
const globalSemaphore = new Semaphore(config.maxConcurrent);
|
|
1468
1538
|
app.use("*", authMiddleware(options.apiKey));
|
|
1469
1539
|
app.get("/health", (c) => c.json({ status: "ok", version: VERSION }));
|
|
1470
1540
|
app.post("/execute", async (c) => {
|
|
1471
1541
|
const body = await c.req.json();
|
|
1542
|
+
logger.debug(`[Server] POST /execute runtime=${body.request.runtime} sessionId=${body.sessionId ?? "ephemeral"}`);
|
|
1543
|
+
logger.debug(`[Server] Code length: ${body.request.code.length} chars`);
|
|
1472
1544
|
const engineOptions = {
|
|
1473
1545
|
network: config.defaults.network,
|
|
1474
1546
|
memoryLimit: config.defaults.memoryLimit,
|
|
@@ -1483,36 +1555,45 @@ async function createServer(options) {
|
|
|
1483
1555
|
if (body.sessionId) {
|
|
1484
1556
|
const session = sessions.get(body.sessionId);
|
|
1485
1557
|
if (session) {
|
|
1558
|
+
logger.debug(`[Server] Reusing existing session: ${body.sessionId}`);
|
|
1486
1559
|
engine = session.engine;
|
|
1487
1560
|
session.lastAccessedAt = Date.now();
|
|
1488
1561
|
} else {
|
|
1562
|
+
logger.debug(`[Server] Creating new session: ${body.sessionId}`);
|
|
1489
1563
|
engine = new DockerIsol82(engineOptions, config.maxConcurrent);
|
|
1490
1564
|
await engine.start();
|
|
1491
1565
|
sessions.set(body.sessionId, { engine, lastAccessedAt: Date.now() });
|
|
1492
1566
|
}
|
|
1493
1567
|
} else {
|
|
1568
|
+
logger.debug("[Server] Creating ephemeral engine");
|
|
1494
1569
|
engine = new DockerIsol82(engineOptions, config.maxConcurrent);
|
|
1495
1570
|
await engine.start();
|
|
1496
1571
|
}
|
|
1497
1572
|
try {
|
|
1573
|
+
logger.debug("[Server] Acquiring semaphore for /execute");
|
|
1498
1574
|
await globalSemaphore.acquire();
|
|
1499
1575
|
try {
|
|
1500
1576
|
const result = await engine.execute(body.request);
|
|
1577
|
+
logger.debug(`[Server] Execution completed: exitCode=${result.exitCode} duration=${result.durationMs}ms`);
|
|
1501
1578
|
return c.json(result);
|
|
1502
1579
|
} finally {
|
|
1503
1580
|
globalSemaphore.release();
|
|
1504
1581
|
}
|
|
1505
1582
|
} catch (err) {
|
|
1506
1583
|
const message = err instanceof Error ? err.message : String(err);
|
|
1584
|
+
logger.debug(`[Server] Execution error: ${message}`);
|
|
1507
1585
|
return c.json({ error: message }, 500);
|
|
1508
1586
|
} finally {
|
|
1509
1587
|
if (!body.sessionId) {
|
|
1588
|
+
logger.debug("[Server] Cleaning up ephemeral engine");
|
|
1510
1589
|
await engine.stop();
|
|
1511
1590
|
}
|
|
1512
1591
|
}
|
|
1513
1592
|
});
|
|
1514
1593
|
app.post("/execute/stream", async (c) => {
|
|
1515
1594
|
const body = await c.req.json();
|
|
1595
|
+
logger.debug(`[Server] POST /execute/stream runtime=${body.request.runtime}`);
|
|
1596
|
+
logger.debug(`[Server] Code length: ${body.request.code.length} chars`);
|
|
1516
1597
|
const engineOptions = {
|
|
1517
1598
|
network: config.defaults.network,
|
|
1518
1599
|
memoryLimit: config.defaults.memoryLimit,
|
|
@@ -1529,6 +1610,7 @@ async function createServer(options) {
|
|
|
1529
1610
|
const stream = new ReadableStream({
|
|
1530
1611
|
async start(controller) {
|
|
1531
1612
|
try {
|
|
1613
|
+
logger.debug("[Server] Acquiring semaphore for /execute/stream");
|
|
1532
1614
|
await globalSemaphore.acquire();
|
|
1533
1615
|
try {
|
|
1534
1616
|
for await (const event of engine.executeStream(body.request)) {
|
|
@@ -1537,16 +1619,19 @@ async function createServer(options) {
|
|
|
1537
1619
|
`;
|
|
1538
1620
|
controller.enqueue(encoder.encode(line));
|
|
1539
1621
|
}
|
|
1622
|
+
logger.debug("[Server] Stream completed");
|
|
1540
1623
|
} finally {
|
|
1541
1624
|
globalSemaphore.release();
|
|
1542
1625
|
}
|
|
1543
1626
|
} catch (err) {
|
|
1544
1627
|
const message = err instanceof Error ? err.message : String(err);
|
|
1628
|
+
logger.debug(`[Server] Stream error: ${message}`);
|
|
1545
1629
|
const errorEvent = `data: ${JSON.stringify({ type: "error", data: message })}
|
|
1546
1630
|
|
|
1547
1631
|
`;
|
|
1548
1632
|
controller.enqueue(encoder.encode(errorEvent));
|
|
1549
1633
|
} finally {
|
|
1634
|
+
logger.debug("[Server] Cleaning up stream engine");
|
|
1550
1635
|
await engine.stop();
|
|
1551
1636
|
controller.close();
|
|
1552
1637
|
}
|
|
@@ -1562,35 +1647,45 @@ async function createServer(options) {
|
|
|
1562
1647
|
});
|
|
1563
1648
|
app.post("/file", async (c) => {
|
|
1564
1649
|
const body = await c.req.json();
|
|
1650
|
+
logger.debug(`[Server] POST /file sessionId=${body.sessionId} path=${body.path}`);
|
|
1565
1651
|
const session = sessions.get(body.sessionId);
|
|
1566
1652
|
if (!session) {
|
|
1653
|
+
logger.debug(`[Server] Session not found: ${body.sessionId}`);
|
|
1567
1654
|
return c.json({ error: "Session not found" }, 404);
|
|
1568
1655
|
}
|
|
1569
1656
|
session.lastAccessedAt = Date.now();
|
|
1570
1657
|
const content = Buffer.from(body.content, "base64");
|
|
1571
1658
|
await session.engine.putFile(body.path, content);
|
|
1659
|
+
logger.debug(`[Server] File uploaded: ${body.path} (${content.length} bytes)`);
|
|
1572
1660
|
return c.json({ ok: true });
|
|
1573
1661
|
});
|
|
1574
1662
|
app.get("/file", async (c) => {
|
|
1575
1663
|
const sessionId = c.req.query("sessionId");
|
|
1576
1664
|
const path = c.req.query("path");
|
|
1665
|
+
logger.debug(`[Server] GET /file sessionId=${sessionId} path=${path}`);
|
|
1577
1666
|
if (!(sessionId && path)) {
|
|
1578
1667
|
return c.json({ error: "Missing sessionId or path" }, 400);
|
|
1579
1668
|
}
|
|
1580
1669
|
const session = sessions.get(sessionId);
|
|
1581
1670
|
if (!session) {
|
|
1671
|
+
logger.debug(`[Server] Session not found: ${sessionId}`);
|
|
1582
1672
|
return c.json({ error: "Session not found" }, 404);
|
|
1583
1673
|
}
|
|
1584
1674
|
session.lastAccessedAt = Date.now();
|
|
1585
1675
|
const content = await session.engine.getFile(path);
|
|
1676
|
+
logger.debug(`[Server] File downloaded: ${path} (${content.length} bytes)`);
|
|
1586
1677
|
return c.json({ content: content.toString("base64") });
|
|
1587
1678
|
});
|
|
1588
1679
|
app.delete("/session/:id", async (c) => {
|
|
1589
1680
|
const id = c.req.param("id");
|
|
1681
|
+
logger.debug(`[Server] DELETE /session/${id}`);
|
|
1590
1682
|
const session = sessions.get(id);
|
|
1591
1683
|
if (session) {
|
|
1592
1684
|
await session.engine.stop();
|
|
1593
1685
|
sessions.delete(id);
|
|
1686
|
+
logger.debug(`[Server] Session destroyed: ${id}`);
|
|
1687
|
+
} else {
|
|
1688
|
+
logger.debug(`[Server] Session not found (already cleaned up): ${id}`);
|
|
1594
1689
|
}
|
|
1595
1690
|
return c.json({ ok: true });
|
|
1596
1691
|
});
|
|
@@ -1600,6 +1695,7 @@ async function createServer(options) {
|
|
|
1600
1695
|
const now = Date.now();
|
|
1601
1696
|
for (const [id, session] of sessions) {
|
|
1602
1697
|
if (now - session.lastAccessedAt > maxAge) {
|
|
1698
|
+
logger.debug(`[Server] Auto-pruning stale session: ${id}`);
|
|
1603
1699
|
await session.engine.stop();
|
|
1604
1700
|
sessions.delete(id);
|
|
1605
1701
|
}
|
|
@@ -1626,4 +1722,4 @@ export {
|
|
|
1626
1722
|
BunAdapter
|
|
1627
1723
|
};
|
|
1628
1724
|
|
|
1629
|
-
//# debugId=
|
|
1725
|
+
//# debugId=1AFCD54347509D5A64756E2164756E21
|
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"}
|
|
@@ -12,6 +12,8 @@ export interface ServerOptions {
|
|
|
12
12
|
port: number;
|
|
13
13
|
/** API key required for Bearer token authentication. */
|
|
14
14
|
apiKey: string;
|
|
15
|
+
/** Enable debug logging for internal server operations. */
|
|
16
|
+
debug?: boolean;
|
|
15
17
|
}
|
|
16
18
|
/**
|
|
17
19
|
* Creates and configures the isol8 HTTP server.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAS5B,+CAA+C;AAC/C,MAAM,WAAW,aAAa;IAC5B,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAWD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,aAAa;;;;GA+OxD"}
|
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.7.0",
|
|
4
4
|
"description": "Secure code execution engine for AI agents",
|
|
5
5
|
"author": "Illusion47586",
|
|
6
6
|
"license": "MIT",
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@biomejs/biome": "^2.3.15",
|
|
64
64
|
"@semantic-release/changelog": "^6.0.3",
|
|
65
|
+
"@semantic-release/exec": "^7.1.0",
|
|
65
66
|
"@semantic-release/git": "^10.0.1",
|
|
66
67
|
"@semantic-release/github": "^12.0.6",
|
|
67
68
|
"@semantic-release/npm": "^13.1.4",
|
|
@@ -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
|
}
|