Skip to content

guardFilesystemBackend

guardFilesystemBackend(backend, options?): BackendProtocolV2

Defined in: _worktrees/docs-release/gaunt-sloth/packages/agent/src/core/deepAgentPermissions.ts:272

Wrap a deepagents filesystem backend so every read/write/edit/ls/glob/grep call is additionally checked for a REALPATH (symlink-resolved) escape from the sandbox root(s) — closes EXT-14.

deepagents’ own permission layer (enforcePermissionvalidatePathdecidePathAccess, permissions/enforce.ts) matches the RAW model-supplied path against the allow/deny globs and never resolves symlinks. A raw ../~ is rejected by validatePath, and a FINAL-component symlink is blocked by the backend’s own O_NOFOLLOW read — but an INTERMEDIATE symlinked directory inside cwd whose target is OUTSIDE cwd (cwd/linkdir -> /outside, then reading cwd/linkdir/secret.txt) matches the lexical allow cwd/** rule and reaches outside the sandbox. See deepAgentRealPathSandbox.spec.ts for the end-to-end proof.

This wraps the BACKEND — rather than adding a wrapToolCall middleware — because it is the ONE seam gsloth fully controls that also covers subagents: createDeepAgent builds a fresh createFilesystemMiddleware({ backend, permissions }) per subagent (and for the main agent) from the SAME backend reference, but each subagent gets its OWN middleware array that does NOT include gsloth’s middleware param — so a wrapToolCall guard would only cover the top-level agent’s tool calls, not a subagent’s. Wrapping the shared backend closes the gap for both.

Deliberately does NOT re-implement deepagents’ glob/permission matching (aiignore, read-only mode, etc. all stay correctly enforced, unchanged, by the existing lexical checks inside the wrapped backend’s tools) — this is a second, independent containment gate layered in front of them. TOCTOU: the realpath resolution here and the real fs op that follows inside the wrapped backend are not atomic; racing a symlink swap in that small window is an accepted risk (out of scope — this closes the deterministic, non-racing escape described above).

BackendProtocolV2

RealpathGuardOptions = {}

BackendProtocolV2