torsandbox
v0.1.1
Published
Isolated sandbox executor with Tor SOCKS5 routing — no external deps
Downloads
261
Maintainers
Readme
torbox
Isolated sandbox executor with optional Tor SOCKS5 routing.
Zero runtime dependencies — uses bubblewrap or firejail available on the host.
Install
# System deps (one of)
sudo apt install bubblewrap # recommended
sudo apt install firejail
# Optional: Tor
sudo apt install tor && sudo systemctl start tor
# Module
npm install torboxQuick start
import { Sandbox } from "torbox";
// Basic sandbox — no Tor
const sb = new Sandbox();
const result = await sb.run({
lang: "python3",
code: `
import os, socket
print("hostname:", socket.gethostname())
print("user:", os.getenv("USER", "none"))
`,
});
console.log(result.stdout);
// hostname: sandbox
// user: none
// With Tor routing
const tor = new Sandbox({
tor: { host: "127.0.0.1", port: 9050 },
});
const check = await tor.run({
lang: "python3",
code: `
import urllib.request, json
res = urllib.request.urlopen("https://check.torproject.org/api/ip", timeout=15)
print(json.load(res))
`,
});
console.log(check.stdout); // { IP: "...", IsTor: true }API
new Sandbox(opts?)
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| backend | "bwrap" \| "firejail" \| "auto" | "auto" | Isolation backend |
| tor | TorOptions | — | Enables Tor routing |
| tor.host | string | "127.0.0.1" | SOCKS5 host |
| tor.port | number | 9050 | SOCKS5 port |
| tor.verify | boolean | true | Check Tor is reachable on init |
| fs.roBind | Array<{host, guest}> | [] | Extra read-only bind mounts |
| fs.rwBind | Array<{host, guest}> | [] | Extra read-write bind mounts |
| timeout | number | 30000 | Max execution time (ms) |
| env | Record<string,string> | {} | Extra env vars |
| cwd | string | "/tmp" | Working dir inside sandbox |
sandbox.run(opts): Promise<ExecResult>
| Option | Type | Description |
|--------|------|-------------|
| lang | "node" \| "python3" \| "bash" \| "sh" | Interpreter |
| code | string | Script source |
| stdin | string | Optional stdin |
| env | Record<string,string> | Per-run env override |
| timeout | number | Per-run timeout override |
Returns ExecResult:
{
exitCode: number;
stdout: string;
stderr: string;
durationMs: number;
backend: "bwrap" | "firejail";
torEnabled: boolean;
}sandbox.probe(): Promise<{ backend, binPath }>
Resolves config and returns the active backend without executing anything.
sandbox.checkTor(): Promise<void>
Verifies Tor SOCKS5 is reachable. Throws if not.
Isolation model
bubblewrap (bwrap) — recommended
- New user, PID, UTS, IPC namespaces
- Read-only bind of
/usr,/lib,/bin,/sbin tmpfson/tmpand/home- Network namespace not isolated by default (needed for
127.0.0.1:9050) seccompvia bwrap defaults
firejail
- All capabilities dropped
seccompdefault profile- Private
/tmp - No new privileges
Tor routing
When tor is set, the sandbox receives:
ALL_PROXY=socks5h://127.0.0.1:9050
HTTPS_PROXY=socks5h://127.0.0.1:9050
HTTP_PROXY=socks5h://127.0.0.1:9050socks5h:// — the h means DNS is also resolved through Tor (no local DNS leaks).
Advanced: full network isolation with veth pair
For complete network isolation (sandbox can only reach Tor, nothing else), see the veth POC.
Limitations
- Linux only (namespaces are a Linux kernel feature)
- The process running the sandbox needs permission to use
bwrap(usually fine on modern distros) - Tor must be started separately (
systemctl start tor) - No Node.js
vmmodule isolation — this is OS-level, not JS-level
