kern-sandbox 0.2.28 → 0.2.29
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/index.js +18 -1
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -36,7 +36,7 @@ const crypto = require("crypto");
|
|
|
36
36
|
const zlib = require("zlib");
|
|
37
37
|
const { spawn, spawnSync } = require("child_process");
|
|
38
38
|
|
|
39
|
-
const VERSION = "0.2.
|
|
39
|
+
const VERSION = "0.2.29";
|
|
40
40
|
|
|
41
41
|
const DEFAULT_IMAGE = "python:3.12-slim";
|
|
42
42
|
const WORKSPACE = "/workspace"; // where the persistent workspace is mounted inside every box
|
|
@@ -1489,6 +1489,22 @@ class Sandbox {
|
|
|
1489
1489
|
if (!Array.isArray(this.capDrop))
|
|
1490
1490
|
throw new SandboxError("capDrop must be an array of capability names");
|
|
1491
1491
|
this._capDropArgs = this.capDrop.flatMap((c) => ["--cap-drop", validateCap(c)]);
|
|
1492
|
+
// SKIP THE UID RANGE EXACTLY WHEN THE CAPABILITY IT SERVES IS BEING DROPPED ANYWAY, which is the
|
|
1493
|
+
// default and costs a quarter of a cold box. `kern box --image` maps a sub-uid RANGE by default
|
|
1494
|
+
// (so an image that degrades privilege in its entrypoint works), and mapping it forks two SETUID
|
|
1495
|
+
// HELPERS. MEASURED: `parent:idmap` 22 us single-uid against ~1048 us ranged, and the whole box
|
|
1496
|
+
// 3234 against 4298 us on this class's argv - paired, core-pinned, -1083 us (25%).
|
|
1497
|
+
//
|
|
1498
|
+
// IT BUYS THIS SANDBOX NOTHING when `ALL` is dropped, measured rather than argued: `setuid(1000)`
|
|
1499
|
+
// inside a cell is refused either way under `--cap-drop ALL` (EPERM with the range, EINVAL
|
|
1500
|
+
// without). WITHOUT it the range does work, so this is conditional: `capDrop: []` is a documented
|
|
1501
|
+
// choice and keeps both the capability and the range.
|
|
1502
|
+
//
|
|
1503
|
+
// KEPT IDENTICAL TO THE PYTHON BINDING, including the condition: two spellings of one rule drift,
|
|
1504
|
+
// and a caller who moved between the SDKs would meet a different box shape in each.
|
|
1505
|
+
this._singleUid = this.capDrop.some(
|
|
1506
|
+
(c) => String(c).toUpperCase().replace(/^CAP_/, "") === "ALL",
|
|
1507
|
+
);
|
|
1492
1508
|
this._profileArgs = (this.profiles || []).map(validateProfile);
|
|
1493
1509
|
this._egressAllow = (this.egressAllow || []).map(validateDomain);
|
|
1494
1510
|
if (this.apparmor !== null) validateApparmor(this.apparmor);
|
|
@@ -1633,6 +1649,7 @@ class Sandbox {
|
|
|
1633
1649
|
}
|
|
1634
1650
|
// kern's own --timeout is a tight BACKSTOP just beyond our deadline; OUR wait is the authority.
|
|
1635
1651
|
argv.push(...this._capDropArgs);
|
|
1652
|
+
if (this._singleUid) argv.push("--no-uid-range");
|
|
1636
1653
|
argv.push("--timeout", String(Math.floor(timeoutS) + 5));
|
|
1637
1654
|
if (this.memoryMb !== null) argv.push("--memory", `${this.memoryMb}m`);
|
|
1638
1655
|
if (this.cpus !== null) argv.push("--cpus", String(this.cpus));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kern-sandbox",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.29",
|
|
4
4
|
"description": "kern is a fast, rootless sandbox and virtual resource runtime for any workload, including untrusted and LLM-generated code; kern-sandbox is its Node/TypeScript binding. Run untrusted or agent-generated code (Python/JS/Bash) in a real, kernel-enforced box, one per call, with no cloud, no account and no VM.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sandbox",
|