Permissions
Workers run your task code, and the permission option controls what that code
can access at runtime. You can restrict file access, network connections,
environment variables, imports, and subprocesses.
Set the policy when you create the pool:
import { createPool, isMain, task } from "knitting";
export const work = task({ f: async (x: number) => x * 2,});
if (isMain) { using pool = createPool({ threads: 2, permission: { mode: "strict" }, })({ work });
console.log(await pool.call.work(21)); // 42}Choose a mode
Section titled “Choose a mode”There are three ways to configure permissions:
- Leave
permissionout. Knitting uses the strict defaults and allows imports, including web imports. - Use
permission: {}orpermission: { mode: "strict" }. Knitting uses the conservative strict defaults and lets you add only the access your tasks need. - Use
permission: "unsafe". Knitting disables runtime permission flags and removes inherited Node permission flags from the worker.
For most applications, keep strict mode and add a small allow-list. Use
"unsafe" only when a dependency needs access that the runtime cannot express
with the strict policy.
The console option controls whether worker console.* calls are forwarded to
the host. It defaults to false in strict mode and true in unsafe mode.
createPool({ permission: { mode: "strict", console: true } })({ work });createPool({ permission: "unsafe" })({ work });Grant only what the task needs
Section titled “Grant only what the task needs”Object mode lets you grant access one capability at a time. Anything you do not list stays denied:
createPool({ permission: { mode: "strict", allowImport: true, // allow task-module imports read: ["./data"], // path allow-list (or `true` for all) write: ["./out"], net: ["api.example.com"], // host allow-list (or `true` for all) env: { allow: ["NODE_ENV"] }, run: ["git"], // subprocess allow-list console: true, },})({ work });| Field | Controls |
|---|---|
read / write | Filesystem allow-lists. true means unrestricted access. |
denyRead / denyWrite | Explicit denials applied after the allow-list. |
net / denyNet | Network host allow- and deny-lists. |
allowImport | Modules the worker may import. true allows all imports. |
env | Environment access through { allow, deny, files }. |
run / denyRun | Subprocess execution allow- and deny-lists. |
console | Whether worker console.* output reaches the host. |
Knitting uses each runtime’s own permission mechanism, so the exact coverage varies by runtime (see how each runtime enforces it). Permissions are a guardrail, not a complete boundary for untrusted code. For stronger isolation, combine them with process workers.
What strict mode allows
Section titled “What strict mode allows”Strict mode starts with a conservative policy:
- reads and writes are limited to the current working directory (
cwd); - writes to
node_modulesare denied; - sensitive files and directories are denied, including
.env,.git,.npmrc,.docker,.secrets,~/.ssh,~/.gnupg,~/.aws,~/.azure,~/.config/gcloud, and~/.kube; - sensitive POSIX paths are denied, including
/proc,/sys,/dev, and/etc; deno.lockandbun.lock*can still be read.
permission: "unsafe" turns off runtime permission flags and removes inherited
Node permission flags from the worker’s execArgv.
How the runtimes enforce it
Section titled “How the runtimes enforce it”Knitting translates the same policy into each runtime’s native permission system. The result is slightly different on Node.js, Deno, and Bun.
Node.js workers
Section titled “Node.js workers”Node workers receive --permission or --experimental-permission, along with
the relevant allow flags:
--allow-fs-read--allow-fs-write--allow-worker--allow-child-process--allow-addons--allow-wasi
Node’s worker flags are allow-list based. That means Knitting cannot represent every protocol-level deny-list rule as a native Node flag.
Deno workers
Section titled “Deno workers”When enabled, Deno workers receive a Worker.deno.permissions policy.
Knitting applies it only when one of these is true:
- it detects
--unstable-worker-options(using a Linux/proccheck); or KNITTING_DENO_WORKER_PERMISSIONS=1is set.
Bun workers
Section titled “Bun workers”Bun does not currently provide worker permission flags. Knitting accepts the permission values for API compatibility, but Bun cannot enforce them through runtime flags yet.
Controlling subprocesses
Section titled “Controlling subprocesses”If a task needs to start another process, object mode also supports runtime-specific overrides:
node.allowChildProcess?: booleandeno.allowRun?: boolean— a legacy option, superseded by the top-levelrunallow-list.
Both default to false in strict mode. Prefer the top-level run allow-list
when you need to permit specific commands.