Skip to content

FileJail

Defined in: file/jail.ts:27

Confines file access to a configured root. Every requested path is resolved against the root and checked (after symlink resolution) to still be inside it. Defends against .. traversal and a symlink planted inside the jail pointing outside it.

Known limitation (TOCTOU): this is a check-then-use pattern, not a kernel-enforced boundary — there’s a window between a resolve* call’s realpath check and the caller’s actual readFile/writeFile on that same path where a concurrent filesystem change (e.g. something swaps a symlink into place) could in principle slip through. A fully closed version would operate on a file descriptor (openfstat/read) instead of a path, so there’s no gap between check and use; this package doesn’t do that yet. Matches the threat model this jail is scoped to (the model is the adversary, via tool-call arguments — not a concurrent local filesystem race) but is worth knowing if that threat model ever changes. A subprocess-level, kernel-enforced sandbox (e.g. Landlock, sandbox-exec) doesn’t have this gap; this jail does.

Platform support: tested on Linux and macOS only. Windows is untested and not currently supported — path.isAbsolute/path.relative/path.sep behave differently there (drive letters, UNC paths, case-insensitive-but-case-preserving filesystems), and none of that has been verified.

readonly root: string

Defined in: file/jail.ts:29

The jail root, resolved to an absolute path (not yet symlink-resolved).

resolveExisting(requestedPath): Promise<string>

Defined in: file/jail.ts:35

Resolve requestedPath (relative to the root) to an absolute, symlink-resolved path, for a file that must already exist. Throws AdlError("INVALID_INPUT", …) if the path is absolute, escapes the root, or doesn’t exist.

string

Promise<string>


resolveForWrite(requestedPath): Promise<string>

Defined in: file/jail.ts:42

Resolve requestedPath to an absolute, symlink-resolved path for a file that may not exist yet — the file itself isn’t symlink-resolved (it may not exist), but its parent directory is, and must already exist. Throws AdlError("INVALID_INPUT", …) if the path is absolute, escapes the root, or its parent directory doesn’t exist.

string

Promise<string>