Skip to main content

Example on GitHub

Runnable example for permission configuration.
All host capabilities are deny-by-default. Sandboxed code cannot access the filesystem, network, child processes, or environment variables unless you explicitly allow it.

Runnable example

import {
	NodeRuntime,
	createInMemoryFileSystem,
	createNodeDriver,
	createNodeRuntimeDriverFactory,
} from "../../../packages/secure-exec/src/index.ts";

const filesystem = createInMemoryFileSystem();
await filesystem.writeFile("/secret.txt", "top secret");
const runtime = new NodeRuntime({
	systemDriver: createNodeDriver({
		filesystem,
		permissions: {
			fs: (request) => ({ allow: request.path.startsWith("/workspace") }),
		},
	}),
	runtimeDriverFactory: createNodeRuntimeDriverFactory(),
});

const result = await runtime.run<{
	message: string;
	blocked: boolean;
}>(
	`
  const fs = require("node:fs");

  fs.mkdirSync("/workspace", { recursive: true });
  fs.writeFileSync("/workspace/message.txt", "hello from permissions");

  let blocked = false;
  try {
    fs.readFileSync("/secret.txt", "utf8");
  } catch (error) {
    blocked = error && error.code === "EACCES";
  }

  module.exports = {
    message: fs.readFileSync("/workspace/message.txt", "utf8"),
    blocked,
  };
`,
);

console.log(
	JSON.stringify({
		ok:
			result.code === 0 &&
			result.exports?.message === "hello from permissions" &&
			result.exports?.blocked === true,
		message: result.exports?.message,
		blocked: result.exports?.blocked,
		summary: "filesystem access was allowed for /workspace and denied for /secret.txt",
	}),
);
Source: examples/features/src/permissions.ts

Permission helpers

Quick presets for common configurations:
import {
  createNodeDriver,
  allowAll,
  allowAllFs,
  allowAllNetwork,
} from "secure-exec";

// Allow everything
const driver = createNodeDriver({ permissions: allowAll });

// Allow only filesystem and network
const selective = createNodeDriver({
  permissions: {
    ...allowAllFs,
    ...allowAllNetwork,
  },
});
ExportAllows
allowAllAll operations across all domains
allowAllFsAll filesystem reads and writes
allowAllNetworkAll network requests and DNS lookups
allowAllChildProcessAll child process spawning
allowAllEnvAll environment variable access

Function-based checks

Each permission field accepts a function that inspects the request and returns a decision:
const driver = createNodeDriver({
  permissions: {
    fs: (req) => ({ allow: req.op === "read" }),
    network: (req) => ({ allow: !req.hostname?.endsWith(".internal") }),
    childProcess: (req) => ({ allow: ["node", "python3"].includes(req.command) }),
    env: (req) => ({ allow: ["PATH", "HOME"].includes(req.key) }),
  },
});

Permissions type

type PermissionDecision = {
  allow: boolean;
  reason?: string;
};

type PermissionCheck<T> = (request: T) => PermissionDecision;

type Permissions = {
  fs?: PermissionCheck<FsAccessRequest>;
  network?: PermissionCheck<NetworkAccessRequest>;
  childProcess?: PermissionCheck<ChildProcessAccessRequest>;
  env?: PermissionCheck<EnvAccessRequest>;
};