sandboxedjs 0.1.34 → 0.1.35
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 +42 -0
- package/bin/sandboxedjs.mjs +3 -1
- package/dist/index.cjs +1130 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +238 -1
- package/dist/index.d.ts +238 -1
- package/dist/index.js +1125 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,6 +46,7 @@ Node 18.17+. Everything is pure JavaScript and WebAssembly — no compilation st
|
|
|
46
46
|
| **Coreutils** | 154 programs — `ls cat cp mv rm mkdir grep sed awk find head tail sort uniq wc cut tr tee xargs chmod chown ln du df ps tar gzip base64 sha256sum diff curl wget` and the rest — plus 54 shell builtins |
|
|
47
47
|
| **Node.js** | Its own module engine — `require` *and* `import`, live bindings, `exports` maps, top-level `await`, npm packages, `http`, `fs`, streams, `child_process` |
|
|
48
48
|
| **Python** | CPython 3.13 (Pyodide) on the *same* filesystem, with the real standard library |
|
|
49
|
+
| **WebAssembly** | A WASI (`preview1`) host — run any `wasm32-wasi` binary from clang, Rust, Zig or TinyGo as an ordinary process, on the same filesystem |
|
|
49
50
|
| **FFmpeg** | `ffmpeg` and `ffprobe` (FFmpeg 5.1) reading and writing container files directly — [optional install](#video-and-audio) |
|
|
50
51
|
| **`/proc`** | Live and synthesised — `ps`, `top`, `free` and `uptime` all read the same source |
|
|
51
52
|
| **Networking** | Virtual interfaces, `/etc/hosts` resolution, in-container HTTP servers, an optional bridge to a real host port |
|
|
@@ -359,6 +360,46 @@ The bundled standard library includes `json`, `re`, `os`, `sys`, `math`, `random
|
|
|
359
360
|
Real CPython, so `sqlite3`, `dataclasses`, `decimal` and `typing` all work. Packages must be built for WebAssembly: `micropip` installs pure-Python wheels, and Pyodide's own distribution covers the rest
|
|
360
361
|
(and only with outbound networking enabled).
|
|
361
362
|
|
|
363
|
+
### WebAssembly binaries
|
|
364
|
+
|
|
365
|
+
Anything compiled to `wasm32-wasi` runs as a normal container process — same filesystem, same
|
|
366
|
+
environment, same pipes:
|
|
367
|
+
|
|
368
|
+
```ts
|
|
369
|
+
await box.fs.writeFile("/usr/local/bin/tool", await readFile("tool.wasm"), { mode: 0o755 });
|
|
370
|
+
await box.exec("tool --version");
|
|
371
|
+
await box.exec("cat data.csv | tool summarise | sort");
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
An executable `.wasm` file is dispatched automatically, the way a `#!` script is — `./tool.wasm`
|
|
375
|
+
runs without naming an interpreter, and a binary installed into `$PATH` under a bare name is
|
|
376
|
+
found by its magic number. You can also invoke the interpreter directly:
|
|
377
|
+
|
|
378
|
+
```
|
|
379
|
+
wasi [--dir PATH] [--mapdir GUEST=PATH] [--env K=V] MODULE.wasm [args...]
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
By default the module sees the whole filesystem. `--dir` and `--mapdir` replace that with exactly
|
|
383
|
+
what you list, and a path that climbs out of a preopened directory is refused with `ENOTCAPABLE`.
|
|
384
|
+
|
|
385
|
+
Building one, with any wasi-sdk clang:
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
clang --target=wasm32-wasip1 --sysroot="$WASI_SYSROOT" -O2 tool.c -o tool.wasm
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
Two things to know, both of which match how `wasmtime` behaves:
|
|
392
|
+
|
|
393
|
+
- **A WASI program has no working directory.** wasi-libc fixes its own at `/`, so a guest's
|
|
394
|
+
relative path resolves from the root. Pass absolute paths.
|
|
395
|
+
- **Sockets report `ENOTSUP`.** This container's network is an HTTP router rather than a packet
|
|
396
|
+
path, so a guest that wants to `bind()` cannot. Files, clocks, randomness, arguments,
|
|
397
|
+
environment and standard I/O all work.
|
|
398
|
+
|
|
399
|
+
Standard input is drained before the module starts, because WASI's `fd_read` is synchronous and
|
|
400
|
+
the container's streams are not — so piping and redirection work, but a wasm program reading a
|
|
401
|
+
live terminal sees end-of-file.
|
|
402
|
+
|
|
362
403
|
### Filesystem from the host
|
|
363
404
|
|
|
364
405
|
```ts
|
|
@@ -422,6 +463,7 @@ sandboxedjs — a Linux-like container inside Node.js
|
|
|
422
463
|
node v22.12.0 npm, require, http servers
|
|
423
464
|
python3 CPython 3.13 only WebAssembly-built C extensions
|
|
424
465
|
ffmpeg 5.1.4 video and audio
|
|
466
|
+
wasi preview1 run wasm32-wasi binaries; ./tool.wasm works
|
|
425
467
|
network on npm install reaches the real registry
|
|
426
468
|
```
|
|
427
469
|
|
package/bin/sandboxedjs.mjs
CHANGED
|
@@ -171,10 +171,11 @@ async function printReplBanner(box, opts) {
|
|
|
171
171
|
}
|
|
172
172
|
};
|
|
173
173
|
|
|
174
|
-
const [node, python, ffmpeg] = await Promise.all([
|
|
174
|
+
const [node, python, ffmpeg, wasi] = await Promise.all([
|
|
175
175
|
probe("node -v", (out) => out.match(/v[\d.]+/)?.[0]),
|
|
176
176
|
probe("python3 -c \"import sys; print(sys.version.split()[0])\"", (out) => out),
|
|
177
177
|
probe("ffmpeg -version", (out) => out.match(/ffmpeg version (\S+)/)?.[1]),
|
|
178
|
+
probe("which wasi", () => "preview1"),
|
|
178
179
|
]);
|
|
179
180
|
|
|
180
181
|
const row = (name, value, note) =>
|
|
@@ -187,6 +188,7 @@ async function printReplBanner(box, opts) {
|
|
|
187
188
|
row("node", node, "npm, require, http servers"),
|
|
188
189
|
row("python3", python, "CPython via Pyodide; WebAssembly wheels only"),
|
|
189
190
|
row("ffmpeg", ffmpeg, ffmpeg ? "video and audio" : "npm install @ffmpeg/core"),
|
|
191
|
+
row("wasi", wasi, "run wasm32-wasi binaries; ./tool.wasm works"),
|
|
190
192
|
row(
|
|
191
193
|
"network",
|
|
192
194
|
opts.network ? "on" : "off",
|