kern-sandbox 0.1.7 → 0.1.9
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 +15 -8
- package/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
# kern-sandbox (Node.js / TypeScript)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**[kern](https://github.com/getkern/kern)** is a fast, rootless, daemonless Linux sandbox runtime: a real,
|
|
4
|
+
kernel-enforced box that starts in **~2 ms**, from one **~1.6 MB** binary, with no daemon. **kern-sandbox**
|
|
5
|
+
is its Node / TypeScript binding: run untrusted or agent-generated code in a fresh, isolated box, from Node.
|
|
6
|
+
|
|
7
|
+
On npm: [`npm install kern-sandbox`](https://www.npmjs.com/package/kern-sandbox). For Python, the same
|
|
8
|
+
package is on PyPI: [`kern-sandbox`](https://pypi.org/project/kern-sandbox/).
|
|
4
9
|
|
|
5
10
|
It is a thin, dependency-free wrapper around the [`kern`](https://github.com/getkern/kern) binary:
|
|
6
11
|
a fresh, isolated box per call, network off by default, hard resource caps, and a timeout the binding
|
|
7
|
-
itself enforces.
|
|
12
|
+
itself enforces. Kernel-enforced isolation (namespaces, cgroups v2, seccomp), local, about 1.6 MB, with no cloud, no account, no VM.
|
|
8
13
|
|
|
9
14
|
```js
|
|
10
15
|
const kern = require("kern-sandbox");
|
|
@@ -32,8 +37,8 @@ You also need the `kern` binary on `PATH` (or point `$KERN_BIN` at it). One line
|
|
|
32
37
|
curl -fsSL https://raw.githubusercontent.com/getkern/kern/main/install.sh | sh
|
|
33
38
|
```
|
|
34
39
|
|
|
35
|
-
kern needs a Linux kernel with unprivileged user namespaces + cgroup v2. On Windows it runs under WSL2
|
|
36
|
-
|
|
40
|
+
kern needs a Linux kernel with unprivileged user namespaces + cgroup v2. On Windows it runs under WSL2.
|
|
41
|
+
Node 18+.
|
|
37
42
|
|
|
38
43
|
## A session: files persist, processes are ephemeral
|
|
39
44
|
|
|
@@ -76,6 +81,7 @@ const r = await kern.runCode("console.log([1,2,3].map(x => x * x))", {
|
|
|
76
81
|
|---|---|
|
|
77
82
|
| `stdout`, `stderr` | captured output (each capped at `maxOutputBytes`) |
|
|
78
83
|
| `exitCode` | the process exit code |
|
|
84
|
+
| `durationMs` | wall-clock duration of the call, in ms |
|
|
79
85
|
| `success` | `true` iff `exitCode === 0` **and** no sandbox fault |
|
|
80
86
|
| `fault` | a sandbox event, or `null`. `{ type, message }` |
|
|
81
87
|
| `files` | files created/modified in the workspace this call |
|
|
@@ -147,7 +153,7 @@ Desktop / Cursor) ships in the Python package `kern-sandbox` (`pip install kern-
|
|
|
147
153
|
## Charts, rich results, live output, and checkpoints
|
|
148
154
|
|
|
149
155
|
**Rich results (the "code interpreter" pattern).** `runCode` runs Python by default, and like a
|
|
150
|
-
Jupyter
|
|
156
|
+
Jupyter cell it captures rich, mime-typed values into `result.results` (a list of `Result`) with
|
|
151
157
|
**no Jupyter kernel**: the value of the code's **last bare expression**, every **`display(obj)`** call,
|
|
152
158
|
and **every open matplotlib figure automatically** (no `savefig`). Accessors: `.png`/`.jpeg` (Buffer),
|
|
153
159
|
`.html`, `.svg`, `.markdown`, `.json`, `.text`.
|
|
@@ -167,7 +173,7 @@ Capture never touches `stdout`/`stderr`/`exitCode`; a statement returning `None`
|
|
|
167
173
|
can still WRITE an artifact to the workspace and `readFile` it if you prefer.
|
|
168
174
|
|
|
169
175
|
**Warm kernel (kill the interpreter boot).** Each `runCode` starts a **fresh** interpreter, paying the
|
|
170
|
-
CPython boot (~
|
|
176
|
+
CPython boot (~12 ms) every call. When you run many cells that share state (a REPL, a notebook, an
|
|
171
177
|
agent's tool loop), open a `kernel()`: ONE warm interpreter in a long-lived box, fed cells over a pipe.
|
|
172
178
|
In-memory state persists across cells and the per-cell cost drops from ~16 ms to **sub-millisecond**
|
|
173
179
|
(~300x). Same rich `results` capture as `runCode`.
|
|
@@ -205,8 +211,9 @@ clear error otherwise). The Python binding uses the stdlib `tarfile` and has no
|
|
|
205
211
|
|
|
206
212
|
kern is a **kernel-boundary** sandbox for **your own or semi-trusted** code (CI, dev, edge, your
|
|
207
213
|
agents' code). Its seccomp filter is a **denylist**: right for semi-trusted agent code, **not** a hard
|
|
208
|
-
boundary against deliberately hostile multi-tenant code. For that, reach for a microVM (Firecracker
|
|
209
|
-
gVisor. See the project's
|
|
214
|
+
boundary against deliberately hostile multi-tenant code. For that, reach for a microVM (Firecracker /
|
|
215
|
+
Kata) or gVisor. A deny-by-default allowlist mode is on the roadmap. See the project's
|
|
216
|
+
[SECURITY.md](https://github.com/getkern/kern/blob/main/SECURITY.md).
|
|
210
217
|
|
|
211
218
|
## License
|
|
212
219
|
|
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.1.
|
|
39
|
+
const VERSION = "0.1.8";
|
|
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
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kern-sandbox",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.9",
|
|
4
|
+
"description": "kern is a fast, rootless, daemonless Linux sandbox runtime; kern-sandbox is its Node/TypeScript binding. Run untrusted or agent-generated code (Python/JS/Bash) in a real, kernel-enforced box, ~2 ms, no cloud, no account, no VM.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sandbox",
|
|
7
7
|
"kern",
|