isol8 0.8.2 → 0.9.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/dist/cli.js +363 -44
- package/dist/docker/proxy-handler.sh +8 -0
- package/dist/docker/proxy.sh +3 -0
- package/dist/index.js +324 -13
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/engine/audit.d.ts +31 -0
- package/dist/src/engine/audit.d.ts.map +1 -0
- package/dist/src/engine/docker.d.ts +9 -0
- package/dist/src/engine/docker.d.ts.map +1 -1
- package/dist/src/engine/image-builder.d.ts.map +1 -1
- package/dist/src/engine/stats.d.ts +35 -0
- package/dist/src/engine/stats.d.ts.map +1 -0
- package/dist/src/engine/utils.d.ts +9 -0
- package/dist/src/engine/utils.d.ts.map +1 -1
- package/dist/src/server/index.d.ts.map +1 -1
- package/dist/src/types.d.ts +85 -0
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/schema/isol8.config.schema.json +47 -0
|
@@ -71,6 +71,10 @@ if [ "$method" = "CONNECT" ]; then
|
|
|
71
71
|
|
|
72
72
|
if ! is_allowed "$host"; then
|
|
73
73
|
msg="isol8: CONNECT to ${host} blocked by network filter"
|
|
74
|
+
# Log security event
|
|
75
|
+
if [ -d "/tmp/isol8-proxy" ]; then
|
|
76
|
+
printf '{"type":"network_blocked","timestamp":"%s","details":{"method":"CONNECT","host":"%s","reason":"filter_mismatch"}}\n' "$(date -Iseconds)" "$host" >> /tmp/isol8-proxy/security-events.jsonl
|
|
77
|
+
fi
|
|
74
78
|
printf "HTTP/1.1 403 Forbidden\r\nContent-Type: text/plain\r\nContent-Length: %d\r\n\r\n%s" \
|
|
75
79
|
"${#msg}" "$msg"
|
|
76
80
|
exit 0
|
|
@@ -96,6 +100,10 @@ port="${hostport##*:}"
|
|
|
96
100
|
|
|
97
101
|
if ! is_allowed "$host"; then
|
|
98
102
|
msg="isol8: request to ${host} blocked by network filter"
|
|
103
|
+
# Log security event
|
|
104
|
+
if [ -d "/tmp/isol8-proxy" ]; then
|
|
105
|
+
printf '{"type":"network_blocked","timestamp":"%s","details":{"method":"%s","host":"%s","reason":"filter_mismatch"}}\n' "$(date -Iseconds)" "$method" "$host" >> /tmp/isol8-proxy/security-events.jsonl
|
|
106
|
+
fi
|
|
99
107
|
printf "HTTP/1.1 403 Forbidden\r\nContent-Type: text/plain\r\nContent-Length: %d\r\n\r\n%s" \
|
|
100
108
|
"${#msg}" "$msg"
|
|
101
109
|
exit 0
|
package/dist/docker/proxy.sh
CHANGED
package/dist/index.js
CHANGED
|
@@ -198,6 +198,144 @@ var init_logger = __esm(() => {
|
|
|
198
198
|
logger = new Logger;
|
|
199
199
|
});
|
|
200
200
|
|
|
201
|
+
// src/engine/audit.ts
|
|
202
|
+
import { spawn } from "node:child_process";
|
|
203
|
+
import { appendFileSync, existsSync as existsSync2, mkdirSync, readdirSync, statSync, unlinkSync } from "node:fs";
|
|
204
|
+
import { join as join2 } from "node:path";
|
|
205
|
+
|
|
206
|
+
class AuditLogger {
|
|
207
|
+
config;
|
|
208
|
+
auditFile;
|
|
209
|
+
constructor(config) {
|
|
210
|
+
this.config = config;
|
|
211
|
+
const auditDir = config.logDir ?? process.env.ISOL8_AUDIT_DIR ?? join2(process.cwd(), "./.isol8_audit");
|
|
212
|
+
this.auditFile = join2(auditDir, "executions.log");
|
|
213
|
+
if (!existsSync2(auditDir)) {
|
|
214
|
+
try {
|
|
215
|
+
mkdirSync(auditDir, { recursive: true });
|
|
216
|
+
} catch (err) {
|
|
217
|
+
logger.error("Failed to create audit dir:", err);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
this.cleanupOldLogs();
|
|
221
|
+
}
|
|
222
|
+
cleanupOldLogs() {
|
|
223
|
+
if (!this.config.enabled || this.config.retentionDays <= 0) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
try {
|
|
227
|
+
const auditDir = join2(this.auditFile, "..");
|
|
228
|
+
if (!existsSync2(auditDir)) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const cutoffTime = Date.now() - this.config.retentionDays * 24 * 60 * 60 * 1000;
|
|
232
|
+
const files = readdirSync(auditDir);
|
|
233
|
+
let cleanedCount = 0;
|
|
234
|
+
for (const file of files) {
|
|
235
|
+
if (file.endsWith(".log") || file.endsWith(".jsonl")) {
|
|
236
|
+
const filePath = join2(auditDir, file);
|
|
237
|
+
try {
|
|
238
|
+
const stats = statSync(filePath);
|
|
239
|
+
if (stats.mtimeMs < cutoffTime) {
|
|
240
|
+
unlinkSync(filePath);
|
|
241
|
+
cleanedCount++;
|
|
242
|
+
logger.debug(`Cleaned up old audit log: ${file}`);
|
|
243
|
+
}
|
|
244
|
+
} catch (err) {
|
|
245
|
+
logger.debug(`Failed to check/remove old log file ${file}:`, err);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (cleanedCount > 0) {
|
|
250
|
+
logger.info(`Audit log cleanup: removed ${cleanedCount} old log files`);
|
|
251
|
+
}
|
|
252
|
+
} catch (err) {
|
|
253
|
+
logger.error("Failed to cleanup old audit logs:", err);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
record(audit) {
|
|
257
|
+
if (!this.config.enabled) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
try {
|
|
261
|
+
const filteredAudit = this.filterAuditData(audit);
|
|
262
|
+
const line = `${JSON.stringify(filteredAudit)}
|
|
263
|
+
`;
|
|
264
|
+
switch (this.config.destination) {
|
|
265
|
+
case "file":
|
|
266
|
+
case "filesystem":
|
|
267
|
+
appendFileSync(this.auditFile, line, { encoding: "utf-8" });
|
|
268
|
+
break;
|
|
269
|
+
case "stdout":
|
|
270
|
+
console.log("AUDIT_LOG:", filteredAudit);
|
|
271
|
+
break;
|
|
272
|
+
default:
|
|
273
|
+
logger.error(`Unsupported audit destination: ${this.config.destination}`);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
logger.debug("Audit record written:", audit.executionId);
|
|
277
|
+
if (this.config.postLogScript) {
|
|
278
|
+
this.runPostLogScript();
|
|
279
|
+
}
|
|
280
|
+
} catch (err) {
|
|
281
|
+
logger.error("Failed to write audit record:", err);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
runPostLogScript() {
|
|
285
|
+
if (!this.config.postLogScript) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
try {
|
|
289
|
+
const child = spawn(this.config.postLogScript, [this.auditFile], {
|
|
290
|
+
detached: true,
|
|
291
|
+
stdio: "ignore"
|
|
292
|
+
});
|
|
293
|
+
child.on("error", (err) => {
|
|
294
|
+
logger.error("Failed to run post-log script:", err);
|
|
295
|
+
});
|
|
296
|
+
child.unref();
|
|
297
|
+
} catch (err) {
|
|
298
|
+
logger.error("Failed to spawn post-log script:", err);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
filterAuditData(audit) {
|
|
302
|
+
const result = {
|
|
303
|
+
executionId: audit.executionId,
|
|
304
|
+
userId: audit.userId,
|
|
305
|
+
timestamp: audit.timestamp,
|
|
306
|
+
runtime: audit.runtime,
|
|
307
|
+
codeHash: audit.codeHash,
|
|
308
|
+
containerId: audit.containerId,
|
|
309
|
+
exitCode: audit.exitCode,
|
|
310
|
+
durationMs: audit.durationMs
|
|
311
|
+
};
|
|
312
|
+
if (audit.resourceUsage !== undefined) {
|
|
313
|
+
result.resourceUsage = audit.resourceUsage;
|
|
314
|
+
}
|
|
315
|
+
if (audit.securityEvents !== undefined) {
|
|
316
|
+
result.securityEvents = audit.securityEvents;
|
|
317
|
+
}
|
|
318
|
+
if (audit.metadata !== undefined) {
|
|
319
|
+
result.metadata = audit.metadata;
|
|
320
|
+
}
|
|
321
|
+
if (this.config.includeCode && audit.code !== undefined) {
|
|
322
|
+
result.code = audit.code;
|
|
323
|
+
}
|
|
324
|
+
if (this.config.includeOutput) {
|
|
325
|
+
if (audit.stdout !== undefined) {
|
|
326
|
+
result.stdout = audit.stdout;
|
|
327
|
+
}
|
|
328
|
+
if (audit.stderr !== undefined) {
|
|
329
|
+
result.stderr = audit.stderr;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return result;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
var init_audit = __esm(() => {
|
|
336
|
+
init_logger();
|
|
337
|
+
});
|
|
338
|
+
|
|
201
339
|
// src/engine/concurrency.ts
|
|
202
340
|
class Semaphore {
|
|
203
341
|
max;
|
|
@@ -356,6 +494,51 @@ var init_pool = __esm(() => {
|
|
|
356
494
|
init_logger();
|
|
357
495
|
});
|
|
358
496
|
|
|
497
|
+
// src/engine/stats.ts
|
|
498
|
+
function calculateCPUPercent(stats) {
|
|
499
|
+
const cpuDelta = stats.cpu_stats.cpu_usage.total_usage - stats.precpu_stats.cpu_usage.total_usage;
|
|
500
|
+
const systemDelta = stats.cpu_stats.system_cpu_usage - stats.precpu_stats.system_cpu_usage;
|
|
501
|
+
if (systemDelta === 0 || cpuDelta === 0) {
|
|
502
|
+
return 0;
|
|
503
|
+
}
|
|
504
|
+
const numCores = stats.cpu_stats.online_cpus ?? stats.cpu_stats.cpu_usage.percpu_usage?.length ?? 1;
|
|
505
|
+
return cpuDelta / systemDelta * numCores * 100;
|
|
506
|
+
}
|
|
507
|
+
function calculateNetworkStats(stats) {
|
|
508
|
+
if (!stats.networks) {
|
|
509
|
+
return { in: 0, out: 0 };
|
|
510
|
+
}
|
|
511
|
+
let rxBytes = 0;
|
|
512
|
+
let txBytes = 0;
|
|
513
|
+
for (const iface of Object.values(stats.networks)) {
|
|
514
|
+
rxBytes += iface.rx_bytes;
|
|
515
|
+
txBytes += iface.tx_bytes;
|
|
516
|
+
}
|
|
517
|
+
return { in: rxBytes, out: txBytes };
|
|
518
|
+
}
|
|
519
|
+
async function getContainerStats(container) {
|
|
520
|
+
const stats = await container.stats({
|
|
521
|
+
stream: false
|
|
522
|
+
});
|
|
523
|
+
const cpuPercent = calculateCPUPercent(stats);
|
|
524
|
+
const memoryBytes = stats.memory_stats.usage;
|
|
525
|
+
const network = calculateNetworkStats(stats);
|
|
526
|
+
return {
|
|
527
|
+
cpuPercent: Math.round(cpuPercent * 100) / 100,
|
|
528
|
+
memoryMB: Math.round(memoryBytes / (1024 * 1024)),
|
|
529
|
+
networkBytesIn: network.in,
|
|
530
|
+
networkBytesOut: network.out
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
function calculateResourceDelta(before, after) {
|
|
534
|
+
return {
|
|
535
|
+
cpuPercent: after.cpuPercent,
|
|
536
|
+
memoryMB: after.memoryMB,
|
|
537
|
+
networkBytesIn: after.networkBytesIn - before.networkBytesIn,
|
|
538
|
+
networkBytesOut: after.networkBytesOut - before.networkBytesOut
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
|
|
359
542
|
// src/engine/utils.ts
|
|
360
543
|
function parseMemoryLimit(limit) {
|
|
361
544
|
const match = limit.match(/^(\d+(?:\.\d+)?)\s*([kmgt]?)b?$/i);
|
|
@@ -451,15 +634,15 @@ var exports_docker = {};
|
|
|
451
634
|
__export(exports_docker, {
|
|
452
635
|
DockerIsol8: () => DockerIsol8
|
|
453
636
|
});
|
|
454
|
-
import { spawn } from "node:child_process";
|
|
637
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
455
638
|
import { randomUUID } from "node:crypto";
|
|
456
|
-
import { existsSync as
|
|
639
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "node:fs";
|
|
457
640
|
import { PassThrough } from "node:stream";
|
|
458
641
|
import Docker from "dockerode";
|
|
459
642
|
async function writeFileViaExec(container, filePath, content) {
|
|
460
643
|
const data = typeof content === "string" ? Buffer.from(content, "utf-8") : content;
|
|
461
644
|
return new Promise((resolve2, reject) => {
|
|
462
|
-
const child =
|
|
645
|
+
const child = spawn2("docker", ["exec", "-i", "-u", "sandbox", container.id, "sh", "-c", `cat > ${filePath}`], {
|
|
463
646
|
stdio: ["pipe", "ignore", "pipe"]
|
|
464
647
|
});
|
|
465
648
|
child.on("error", (err) => {
|
|
@@ -645,6 +828,7 @@ class DockerIsol8 {
|
|
|
645
828
|
tmpSize;
|
|
646
829
|
security;
|
|
647
830
|
persist;
|
|
831
|
+
auditLogger;
|
|
648
832
|
container = null;
|
|
649
833
|
persistentRuntime = null;
|
|
650
834
|
pool = null;
|
|
@@ -666,6 +850,9 @@ class DockerIsol8 {
|
|
|
666
850
|
this.tmpSize = options.tmpSize ?? "256m";
|
|
667
851
|
this.persist = options.persist ?? false;
|
|
668
852
|
this.security = options.security ?? { seccomp: "strict" };
|
|
853
|
+
if (options.audit) {
|
|
854
|
+
this.auditLogger = new AuditLogger(options.audit);
|
|
855
|
+
}
|
|
669
856
|
if (options.debug) {
|
|
670
857
|
logger.setDebug(true);
|
|
671
858
|
}
|
|
@@ -689,12 +876,79 @@ class DockerIsol8 {
|
|
|
689
876
|
}
|
|
690
877
|
async execute(req) {
|
|
691
878
|
await this.semaphore.acquire();
|
|
879
|
+
const startTime = Date.now();
|
|
692
880
|
try {
|
|
693
|
-
|
|
881
|
+
const result = this.mode === "persistent" ? await this.executePersistent(req, startTime) : await this.executeEphemeral(req, startTime);
|
|
882
|
+
return result;
|
|
694
883
|
} finally {
|
|
695
884
|
this.semaphore.release();
|
|
696
885
|
}
|
|
697
886
|
}
|
|
887
|
+
async recordAudit(req, result, startTime, container) {
|
|
888
|
+
try {
|
|
889
|
+
const enc = new TextEncoder;
|
|
890
|
+
const data = enc.encode(req.code);
|
|
891
|
+
const digest = await crypto.subtle.digest("SHA-256", data);
|
|
892
|
+
const codeHash = Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
893
|
+
let securityEvents;
|
|
894
|
+
if (container && this.network === "filtered") {
|
|
895
|
+
securityEvents = await this.collectSecurityEvents(container);
|
|
896
|
+
if (securityEvents.length === 0) {
|
|
897
|
+
securityEvents = undefined;
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
const audit = {
|
|
901
|
+
executionId: result.executionId,
|
|
902
|
+
userId: req.metadata?.userId || "",
|
|
903
|
+
timestamp: new Date(startTime).toISOString(),
|
|
904
|
+
runtime: result.runtime,
|
|
905
|
+
codeHash,
|
|
906
|
+
containerId: result.containerId || "",
|
|
907
|
+
exitCode: result.exitCode,
|
|
908
|
+
durationMs: result.durationMs,
|
|
909
|
+
resourceUsage: result.resourceUsage,
|
|
910
|
+
securityEvents,
|
|
911
|
+
metadata: req.metadata
|
|
912
|
+
};
|
|
913
|
+
this.auditLogger.record(audit);
|
|
914
|
+
} catch (err) {
|
|
915
|
+
logger.error("Failed to record audit log:", err);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
async collectSecurityEvents(container) {
|
|
919
|
+
const events = [];
|
|
920
|
+
try {
|
|
921
|
+
const exec = await container.exec({
|
|
922
|
+
Cmd: ["cat", "/tmp/isol8-proxy/security-events.jsonl"],
|
|
923
|
+
AttachStdout: true,
|
|
924
|
+
AttachStderr: false,
|
|
925
|
+
User: "root"
|
|
926
|
+
});
|
|
927
|
+
const stream = await exec.start({ Tty: false });
|
|
928
|
+
const chunks = [];
|
|
929
|
+
for await (const chunk of stream) {
|
|
930
|
+
chunks.push(chunk);
|
|
931
|
+
}
|
|
932
|
+
const output = Buffer.concat(chunks).toString("utf-8").trim();
|
|
933
|
+
if (output) {
|
|
934
|
+
for (const line of output.split(`
|
|
935
|
+
`)) {
|
|
936
|
+
if (line.trim()) {
|
|
937
|
+
try {
|
|
938
|
+
const event = JSON.parse(line);
|
|
939
|
+
events.push({
|
|
940
|
+
type: event.type || "unknown",
|
|
941
|
+
message: `Security event: ${event.type}`,
|
|
942
|
+
details: event.details || {},
|
|
943
|
+
timestamp: event.timestamp || new Date().toISOString()
|
|
944
|
+
});
|
|
945
|
+
} catch {}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
} catch {}
|
|
950
|
+
return events;
|
|
951
|
+
}
|
|
698
952
|
async putFile(path, content) {
|
|
699
953
|
if (!this.container) {
|
|
700
954
|
throw new Error("No active container. Call execute() first in persistent mode.");
|
|
@@ -802,7 +1056,7 @@ class DockerIsol8 {
|
|
|
802
1056
|
return adapter.image;
|
|
803
1057
|
}
|
|
804
1058
|
}
|
|
805
|
-
async executeEphemeral(req) {
|
|
1059
|
+
async executeEphemeral(req, startTime) {
|
|
806
1060
|
const adapter = this.getAdapter(req.runtime);
|
|
807
1061
|
const timeoutMs = req.timeoutMs ?? this.defaultTimeoutMs;
|
|
808
1062
|
const image = await this.resolveImage(adapter);
|
|
@@ -821,6 +1075,14 @@ class DockerIsol8 {
|
|
|
821
1075
|
});
|
|
822
1076
|
}
|
|
823
1077
|
const container = await this.pool.acquire(image);
|
|
1078
|
+
let startStats;
|
|
1079
|
+
if (this.auditLogger) {
|
|
1080
|
+
try {
|
|
1081
|
+
startStats = await getContainerStats(container);
|
|
1082
|
+
} catch (err) {
|
|
1083
|
+
logger.debug("Failed to collect baseline stats:", err);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
824
1086
|
try {
|
|
825
1087
|
if (this.network === "filtered") {
|
|
826
1088
|
await startProxy(container, this.networkFilter);
|
|
@@ -861,7 +1123,16 @@ class DockerIsol8 {
|
|
|
861
1123
|
const { stdout, stderr, truncated } = await this.collectExecOutput(execStream, container, timeoutMs);
|
|
862
1124
|
const durationMs = Math.round(performance.now() - start);
|
|
863
1125
|
const inspectResult = await exec.inspect();
|
|
864
|
-
|
|
1126
|
+
let resourceUsage;
|
|
1127
|
+
if (startStats) {
|
|
1128
|
+
try {
|
|
1129
|
+
const endStats = await getContainerStats(container);
|
|
1130
|
+
resourceUsage = calculateResourceDelta(startStats, endStats);
|
|
1131
|
+
} catch (err) {
|
|
1132
|
+
logger.debug("Failed to collect final stats:", err);
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
const result = {
|
|
865
1136
|
stdout: this.postProcessOutput(stdout, truncated),
|
|
866
1137
|
stderr: this.postProcessOutput(stderr, false),
|
|
867
1138
|
exitCode: inspectResult.ExitCode ?? 1,
|
|
@@ -871,8 +1142,13 @@ class DockerIsol8 {
|
|
|
871
1142
|
runtime: req.runtime,
|
|
872
1143
|
timestamp: new Date().toISOString(),
|
|
873
1144
|
containerId: container.id,
|
|
1145
|
+
...resourceUsage ? { resourceUsage } : {},
|
|
874
1146
|
...req.outputPaths ? { files: await this.retrieveFiles(container, req.outputPaths) } : {}
|
|
875
1147
|
};
|
|
1148
|
+
if (this.auditLogger) {
|
|
1149
|
+
await this.recordAudit(req, result, startTime, container);
|
|
1150
|
+
}
|
|
1151
|
+
return result;
|
|
876
1152
|
} finally {
|
|
877
1153
|
if (this.persist) {
|
|
878
1154
|
logger.debug(`[Persist] Leaving container running for inspection: ${container.id}`);
|
|
@@ -881,7 +1157,7 @@ class DockerIsol8 {
|
|
|
881
1157
|
}
|
|
882
1158
|
}
|
|
883
1159
|
}
|
|
884
|
-
async executePersistent(req) {
|
|
1160
|
+
async executePersistent(req, startTime) {
|
|
885
1161
|
const adapter = this.getAdapter(req.runtime);
|
|
886
1162
|
const timeoutMs = req.timeoutMs ?? this.defaultTimeoutMs;
|
|
887
1163
|
if (!this.container) {
|
|
@@ -935,7 +1211,21 @@ class DockerIsol8 {
|
|
|
935
1211
|
const { stdout, stderr, truncated } = await this.collectExecOutput(execStream, this.container, timeoutMs);
|
|
936
1212
|
const durationMs = Math.round(performance.now() - start);
|
|
937
1213
|
const inspectResult = await exec.inspect();
|
|
938
|
-
|
|
1214
|
+
let resourceUsage;
|
|
1215
|
+
if (this.auditLogger) {
|
|
1216
|
+
try {
|
|
1217
|
+
const endStats = await getContainerStats(this.container);
|
|
1218
|
+
resourceUsage = {
|
|
1219
|
+
cpuPercent: endStats.cpuPercent,
|
|
1220
|
+
memoryMB: endStats.memoryMB,
|
|
1221
|
+
networkBytesIn: endStats.networkBytesIn,
|
|
1222
|
+
networkBytesOut: endStats.networkBytesOut
|
|
1223
|
+
};
|
|
1224
|
+
} catch (err) {
|
|
1225
|
+
logger.debug("Failed to collect resource stats:", err);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
const result = {
|
|
939
1229
|
stdout: this.postProcessOutput(stdout, truncated),
|
|
940
1230
|
stderr: this.postProcessOutput(stderr, false),
|
|
941
1231
|
exitCode: inspectResult.ExitCode ?? 1,
|
|
@@ -945,8 +1235,13 @@ class DockerIsol8 {
|
|
|
945
1235
|
runtime: req.runtime,
|
|
946
1236
|
timestamp: new Date().toISOString(),
|
|
947
1237
|
containerId: this.container?.id,
|
|
1238
|
+
...resourceUsage ? { resourceUsage } : {},
|
|
948
1239
|
...req.outputPaths ? { files: await this.retrieveFiles(this.container, req.outputPaths) } : {}
|
|
949
1240
|
};
|
|
1241
|
+
if (this.auditLogger) {
|
|
1242
|
+
await this.recordAudit(req, result, startTime, this.container);
|
|
1243
|
+
}
|
|
1244
|
+
return result;
|
|
950
1245
|
}
|
|
951
1246
|
async retrieveFiles(container, paths) {
|
|
952
1247
|
const files = {};
|
|
@@ -1038,11 +1333,11 @@ class DockerIsol8 {
|
|
|
1038
1333
|
}
|
|
1039
1334
|
loadDefaultSeccompProfile() {
|
|
1040
1335
|
const devPath = new URL("../../docker/seccomp-profile.json", import.meta.url);
|
|
1041
|
-
if (
|
|
1336
|
+
if (existsSync3(devPath)) {
|
|
1042
1337
|
return readFileSync2(devPath, "utf-8");
|
|
1043
1338
|
}
|
|
1044
1339
|
const prodPath = new URL("./docker/seccomp-profile.json", import.meta.url);
|
|
1045
|
-
if (
|
|
1340
|
+
if (existsSync3(prodPath)) {
|
|
1046
1341
|
return readFileSync2(prodPath, "utf-8");
|
|
1047
1342
|
}
|
|
1048
1343
|
logger.warn("Could not locate default seccomp profile. Running without seccomp filter.");
|
|
@@ -1248,6 +1543,7 @@ var SANDBOX_WORKDIR = "/sandbox", MAX_OUTPUT_BYTES, PROXY_PORT = 8118, PROXY_STA
|
|
|
1248
1543
|
var init_docker = __esm(() => {
|
|
1249
1544
|
init_runtime();
|
|
1250
1545
|
init_logger();
|
|
1546
|
+
init_audit();
|
|
1251
1547
|
init_pool();
|
|
1252
1548
|
MAX_OUTPUT_BYTES = 1024 * 1024;
|
|
1253
1549
|
});
|
|
@@ -1404,6 +1700,16 @@ var DEFAULT_CONFIG = {
|
|
|
1404
1700
|
security: {
|
|
1405
1701
|
seccomp: "strict"
|
|
1406
1702
|
},
|
|
1703
|
+
audit: {
|
|
1704
|
+
enabled: false,
|
|
1705
|
+
destination: "filesystem",
|
|
1706
|
+
logDir: undefined,
|
|
1707
|
+
postLogScript: undefined,
|
|
1708
|
+
trackResources: true,
|
|
1709
|
+
retentionDays: 90,
|
|
1710
|
+
includeCode: false,
|
|
1711
|
+
includeOutput: false
|
|
1712
|
+
},
|
|
1407
1713
|
debug: false
|
|
1408
1714
|
};
|
|
1409
1715
|
function loadConfig(cwd) {
|
|
@@ -1443,6 +1749,10 @@ function mergeConfig(defaults, overrides) {
|
|
|
1443
1749
|
seccomp: overrides.security?.seccomp ?? defaults.security.seccomp,
|
|
1444
1750
|
customProfilePath: overrides.security?.customProfilePath ?? defaults.security.customProfilePath
|
|
1445
1751
|
},
|
|
1752
|
+
audit: {
|
|
1753
|
+
...defaults.audit,
|
|
1754
|
+
...overrides.audit
|
|
1755
|
+
},
|
|
1446
1756
|
debug: overrides.debug ?? defaults.debug
|
|
1447
1757
|
};
|
|
1448
1758
|
}
|
|
@@ -1457,7 +1767,7 @@ init_logger();
|
|
|
1457
1767
|
// package.json
|
|
1458
1768
|
var package_default = {
|
|
1459
1769
|
name: "isol8",
|
|
1460
|
-
version: "0.8.
|
|
1770
|
+
version: "0.8.3",
|
|
1461
1771
|
description: "Secure code execution engine for AI agents",
|
|
1462
1772
|
author: "Illusion47586",
|
|
1463
1773
|
license: "MIT",
|
|
@@ -1619,7 +1929,8 @@ async function createServer(options) {
|
|
|
1619
1929
|
sandboxSize: config.defaults.sandboxSize,
|
|
1620
1930
|
tmpSize: config.defaults.tmpSize,
|
|
1621
1931
|
...body.options,
|
|
1622
|
-
mode: body.sessionId ? "persistent" : "ephemeral"
|
|
1932
|
+
mode: body.sessionId ? "persistent" : "ephemeral",
|
|
1933
|
+
audit: config.audit
|
|
1623
1934
|
};
|
|
1624
1935
|
let engine;
|
|
1625
1936
|
if (body.sessionId) {
|
|
@@ -1792,4 +2103,4 @@ export {
|
|
|
1792
2103
|
BunAdapter
|
|
1793
2104
|
};
|
|
1794
2105
|
|
|
1795
|
-
//# debugId=
|
|
2106
|
+
//# debugId=B0E8FAABBC51985364756E2164756E21
|
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,WAiCrB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW,CAepD;AAuCD,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pluggable audit logger for execution provenance.
|
|
3
|
+
*
|
|
4
|
+
* Records ExecutionAudit objects to various destinations based on configuration.
|
|
5
|
+
* Supports filesystem and stdout logging, with extensibility for cloud services.
|
|
6
|
+
*/
|
|
7
|
+
import type { AuditConfig, ExecutionAudit } from "../types";
|
|
8
|
+
export declare class AuditLogger {
|
|
9
|
+
private readonly config;
|
|
10
|
+
private readonly auditFile;
|
|
11
|
+
constructor(config: AuditConfig);
|
|
12
|
+
/**
|
|
13
|
+
* Clean up audit log files older than retentionDays.
|
|
14
|
+
* Checks both the main executions.log and any rotated/archived logs.
|
|
15
|
+
*/
|
|
16
|
+
private cleanupOldLogs;
|
|
17
|
+
/**
|
|
18
|
+
* Record an audit entry based on the current configuration.
|
|
19
|
+
*/
|
|
20
|
+
record(audit: ExecutionAudit): void;
|
|
21
|
+
/**
|
|
22
|
+
* Run the configured post-log script.
|
|
23
|
+
* The script receives the audit file path as its first argument.
|
|
24
|
+
*/
|
|
25
|
+
private runPostLogScript;
|
|
26
|
+
/**
|
|
27
|
+
* Apply privacy filtering to audit data based on configuration.
|
|
28
|
+
*/
|
|
29
|
+
private filterAuditData;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../../src/engine/audit.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG5D,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,MAAM,EAAE,WAAW;IAqB/B;;;OAGG;IACH,OAAO,CAAC,cAAc;IAwCtB;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAoCnC;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAuBxB;;OAEG;IACH,OAAO,CAAC,eAAe;CAuCxB"}
|
|
@@ -45,6 +45,7 @@ export declare class DockerIsol8 implements Isol8Engine {
|
|
|
45
45
|
private readonly tmpSize;
|
|
46
46
|
private readonly security;
|
|
47
47
|
private readonly persist;
|
|
48
|
+
private readonly auditLogger?;
|
|
48
49
|
private container;
|
|
49
50
|
private persistentRuntime;
|
|
50
51
|
private pool;
|
|
@@ -65,6 +66,14 @@ export declare class DockerIsol8 implements Isol8Engine {
|
|
|
65
66
|
* the concurrency limit, then delegates to ephemeral or persistent execution.
|
|
66
67
|
*/
|
|
67
68
|
execute(req: ExecutionRequest): Promise<ExecutionResult>;
|
|
69
|
+
/**
|
|
70
|
+
* Record an audit entry for the execution.
|
|
71
|
+
*/
|
|
72
|
+
private recordAudit;
|
|
73
|
+
/**
|
|
74
|
+
* Collect security events from the container (e.g., network filter blocks).
|
|
75
|
+
*/
|
|
76
|
+
private collectSecurityEvents;
|
|
68
77
|
/**
|
|
69
78
|
* Upload a file into the running container via a tar archive.
|
|
70
79
|
* Only available in persistent mode after at least one `execute()` call.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../../src/engine/docker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,MAAM,MAAM,WAAW,CAAC;AAG/B,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,WAAW,EAEX,YAAY,EAIZ,WAAW,EACZ,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../../src/engine/docker.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-builder.d.ts","sourceRoot":"","sources":["../../../src/engine/image-builder.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,MAAM,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAmB5C,mDAAmD;AACnD,UAAU,aAAa;IACrB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC;IACtC,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,gBAAgB,GAAG,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;AAE1D;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,gBAAgB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,UAAU,CAAC,EAAE,gBAAgB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAkBf;
|
|
1
|
+
{"version":3,"file":"image-builder.d.ts","sourceRoot":"","sources":["../../../src/engine/image-builder.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,MAAM,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAmB5C,mDAAmD;AACnD,UAAU,aAAa;IACrB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC;IACtC,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,gBAAgB,GAAG,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;AAE1D;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,gBAAgB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,UAAU,CAAC,EAAE,gBAAgB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAkBf;AAgED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOrF;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAa/F"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module engine/stats
|
|
3
|
+
*
|
|
4
|
+
* Resource usage statistics collection from Docker containers.
|
|
5
|
+
* Uses dockerode's container.stats() API to get CPU, memory, and network metrics.
|
|
6
|
+
*/
|
|
7
|
+
import type Docker from "dockerode";
|
|
8
|
+
/**
|
|
9
|
+
* Resource usage metrics for a container execution.
|
|
10
|
+
*/
|
|
11
|
+
export interface ContainerResourceUsage {
|
|
12
|
+
/** CPU usage as percentage (0-100 * num_cores) */
|
|
13
|
+
cpuPercent: number;
|
|
14
|
+
/** Current memory usage in megabytes */
|
|
15
|
+
memoryMB: number;
|
|
16
|
+
/** Peak memory usage in megabytes (if tracked) */
|
|
17
|
+
peakMemoryMB?: number;
|
|
18
|
+
/** Bytes received during execution */
|
|
19
|
+
networkBytesIn: number;
|
|
20
|
+
/** Bytes sent during execution */
|
|
21
|
+
networkBytesOut: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get resource usage snapshot for a container.
|
|
25
|
+
*
|
|
26
|
+
* @param container - Docker container instance
|
|
27
|
+
* @returns Resource usage metrics
|
|
28
|
+
*/
|
|
29
|
+
export declare function getContainerStats(container: Docker.Container): Promise<ContainerResourceUsage>;
|
|
30
|
+
/**
|
|
31
|
+
* Calculate resource usage delta between two stat snapshots.
|
|
32
|
+
* Useful for getting per-execution metrics.
|
|
33
|
+
*/
|
|
34
|
+
export declare function calculateResourceDelta(before: ContainerResourceUsage, after: ContainerResourceUsage): ContainerResourceUsage;
|
|
35
|
+
//# sourceMappingURL=stats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../../src/engine/stats.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,MAAM,WAAW,CAAC;AAEpC;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,kCAAkC;IAClC,eAAe,EAAE,MAAM,CAAC;CACzB;AA+ED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,CAAC,SAAS,GAC1B,OAAO,CAAC,sBAAsB,CAAC,CAgBjC;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,sBAAsB,EAC9B,KAAK,EAAE,sBAAsB,GAC5B,sBAAsB,CAUxB"}
|
|
@@ -59,4 +59,13 @@ export declare function createTarBuffer(filePath: string, content: Buffer | stri
|
|
|
59
59
|
* @throws {Error} If the file is not found in the archive.
|
|
60
60
|
*/
|
|
61
61
|
export declare function extractFromTar(tarBuffer: Buffer, targetPath: string): Buffer;
|
|
62
|
+
/**
|
|
63
|
+
* Validates a package name to prevent command injection.
|
|
64
|
+
* allow alphanumeric, dash, underscore, dot, @, / (for scoped packages), and = (for versions)
|
|
65
|
+
*
|
|
66
|
+
* @param name - The package name to validate.
|
|
67
|
+
* @returns The name if valid.
|
|
68
|
+
* @throws {Error} If the name contains invalid characters.
|
|
69
|
+
*/
|
|
70
|
+
export declare function validatePackageName(name: string): string;
|
|
62
71
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/engine/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiBtD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAetC;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAQjF;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CA8ClF;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAoC5E"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/engine/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiBtD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAetC;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAQjF;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CA8ClF;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAoC5E;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQxD"}
|
|
@@ -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;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;;;;
|
|
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;;;;GAgPxD"}
|