Filesystem Isolation for AI Agents: Beyond Chroot
Filesystem isolation for AI agents means restricting which files and directories an agent can read, write, and execute — not just at the mount level, but at the path level within a workspace. SafeClaw by Authensor enforces filesystem boundaries through deny-by-default policies where every file operation is evaluated against path patterns before execution. Unlike chroot (which changes the apparent root directory), SafeClaw's path-level enforcement blocks traversal attacks, protects sensitive files within allowed directories, and provides granular read/write/delete separation.
Quick Start
npx @authensor/safeclaw
Why Chroot Is Insufficient
Chroot changes the filesystem root for a process, but it has well-documented limitations:
- Escape with root access: A root process can escape chroot via
mknod,pivot_root, or file descriptor tricks - No write granularity: Inside the chroot, the agent has full access to all files
- No path-level control: Cannot block specific files within the chroot boundary
- No audit trail: Chroot does not log which files were accessed
file.read, file.write, and file.delete action against path-matching rules before the operation reaches the filesystem.
Workspace Boundary Enforcement
Define a strict workspace boundary:
version: "1.0"
description: "Filesystem isolation policy"
rules:
# Workspace boundary — all access must be within /project
- action: file.read
path: "/project/src/**"
effect: allow
reason: "Read source code"
- action: file.write
path: "/project/src/**"
effect: allow
reason: "Write source code"
- action: file.read
path: "/project/docs/**"
effect: allow
reason: "Read documentation"
# Block everything outside workspace
- action: file.read
path: "/**"
effect: deny
reason: "Outside workspace boundary"
- action: file.write
path: "/**"
effect: deny
reason: "Outside workspace boundary"
- action: file.delete
path: "/**"
effect: deny
reason: "File deletion blocked globally"
Path Traversal Prevention
AI agents may attempt path traversal using .. sequences, symlinks, or encoded paths:
# Traversal attempts SafeClaw catches:
/project/src/../../etc/passwd → normalized to /etc/passwd → DENY
/project/src/../../../home/user/.ssh/ → normalized to /home/user/.ssh/ → DENY
/project/src/./../../root/ → normalized to /root/ → DENY
SafeClaw normalizes all paths before evaluation, resolving .., ., and duplicate slashes:
# Explicit traversal guard (redundant with normalization, but defense-in-depth)
- action: file.read
path: "/../"
effect: deny
reason: "Path traversal attempt blocked"
- action: file.write
path: "/../"
effect: deny
reason: "Path traversal attempt blocked"
Protecting Sensitive Files Within Workspace
Even within an allowed workspace, some files should be off-limits:
rules:
# Block sensitive files first (first-match-wins)
- action: file.read
path: "/project/*/.env"
effect: deny
reason: "Environment files contain secrets"
- action: file.read
path: "/project/*/credentials"
effect: deny
reason: "Credential files blocked"
- action: file.read
path: "/project/*/.pem"
effect: deny
reason: "Private key files blocked"
- action: file.read
path: "/project/*/.key"
effect: deny
reason: "Private key files blocked"
- action: file.read
path: "/project/*/config/secrets"
effect: deny
reason: "Secret configuration blocked"
# Then allow general workspace reads
- action: file.read
path: "/project/src/**"
effect: allow
reason: "Read source files (excluding sensitive patterns above)"
- action: "*"
effect: deny
Read/Write/Delete Separation
Different operations carry different risk levels. Separate them:
rules:
# Read: broad access
- action: file.read
path: "/project/**"
effect: allow
# Write: restricted to source and output
- action: file.write
path: "/project/src/**"
effect: allow
- action: file.write
path: "/project/output/**"
effect: allow
# Delete: very restricted
- action: file.delete
path: "/project/output/temp/**"
effect: allow
reason: "Only temp output files can be deleted"
- action: file.delete
path: "**"
effect: deny
reason: "Deletion blocked for all other paths"
System File Protection
Block access to critical system paths regardless of workspace configuration:
rules:
# System file protection (place before workspace allows)
- action: file.read
path: "/etc/shadow"
effect: deny
- action: file.read
path: "/etc/passwd"
effect: deny
- action: file.read
path: "/proc/**"
effect: deny
- action: file.read
path: "/sys/**"
effect: deny
- action: file.read
path: "/root/**"
effect: deny
- action: file.read
path: "/home//.ssh/*"
effect: deny
- action: file.read
path: "/home//.aws/*"
effect: deny
- action: file.read
path: "/home//.config/gcloud/*"
effect: deny
Mount Namespace Integration
For container deployments, combine SafeClaw policies with Linux mount namespaces:
# Mount workspace read-only at OS level
docker run -v $(pwd)/src:/workspace/src:ro ...
SafeClaw adds write control for specific paths inside container
This two-layer approach means:
- OS mount namespace enforces read-only at the mount level
- SafeClaw enforces path-level access within what is mounted
Auditing Filesystem Access
Track all file operations:
npx @authensor/safeclaw audit export \
--filter action=file.read,file.write,file.delete \
--format json \
--since "7 days"
Identify unauthorized access attempts:
npx @authensor/safeclaw audit export \
--filter effect=deny \
--filter action=file.read,file.write \
--since "24h"
Why SafeClaw
- 446 tests cover path normalization, traversal prevention, and glob matching
- Deny-by-default means no file access without an explicit allow rule
- Sub-millisecond evaluation makes per-file-operation checks imperceptible
- Hash-chained audit trail logs every file access decision
- Works with Claude AND OpenAI — filesystem isolation is provider-agnostic
- MIT licensed — no licensing overhead for file-level security
See Also
- Sandboxing AI Agents: Container Isolation Explained
- Process Isolation for AI Agents: Preventing Privilege Escalation
- Multi-Tenant AI Agent Safety: Isolating Customer Workloads
- Zero Trust Architecture for AI Agents
Try SafeClaw
Action-level gating for AI agents. Set it up in your browser in 60 seconds.
$ npx @authensor/safeclaw