Nous.Tools.PathGuard (nous v0.15.4)
View SourcePath-traversal & symlink-escape protection for filesystem tools.
LLMs control the path argument to file tools. Without a guard, a single
prompt-injected document can read ~/.aws/credentials, write to
~/.ssh/authorized_keys, or globsweep /etc/. This module enforces
that every path resolves inside a configured workspace root.
Configuring the workspace root
Pass it via the agent's ctx.deps:
Agent.new("openai:gpt-4",
tools: [Nous.Tools.FileRead, Nous.Tools.FileWrite],
deps: %{workspace_root: "/srv/agent_workspace/#{user_id}"}
)When workspace_root is unset, the guard defaults to the current
working directory (File.cwd!/0). For multi-tenant deployments you
almost certainly want to set it explicitly per session.
What's blocked
- Paths that, after
Path.expand/1, escape the configured root - Symlinks whose target escapes the root
- Any path containing a NUL byte (defense-in-depth)
Summary
Functions
Resolve path against the configured workspace root and return either
{:ok, absolute_path} or {:error, reason} where reason is a
human-readable string suitable to surface back to the LLM.
Functions
@spec validate(String.t(), Nous.RunContext.t() | map() | nil) :: {:ok, String.t()} | {:error, String.t()}
Resolve path against the configured workspace root and return either
{:ok, absolute_path} or {:error, reason} where reason is a
human-readable string suitable to surface back to the LLM.