docs/gateway/security/secure-file-operations.md
OpenClaw uses @openclaw/fs-safe for security-sensitive local file operations: root-bounded reads/writes, atomic replacement, archive extraction, temp workspaces, JSON state, and secret-file handling.
The goal is a consistent library guardrail for trusted OpenClaw code that receives untrusted path names. It is not a sandbox. Host filesystem permissions, OS users, containers, and the agent/tool policy still define the real blast radius.
OpenClaw defaults the fs-safe POSIX Python helper to off.
Why:
OpenClaw only changes the default. If you explicitly set a mode, fs-safe honors it:
# Default OpenClaw behavior: Node-only fs-safe fallbacks.
OPENCLAW_FS_SAFE_PYTHON_MODE=off
# Opt into the helper when available, falling back if unavailable.
OPENCLAW_FS_SAFE_PYTHON_MODE=auto
# Fail closed if the helper cannot start.
OPENCLAW_FS_SAFE_PYTHON_MODE=require
# Optional explicit interpreter.
OPENCLAW_FS_SAFE_PYTHON=/usr/bin/python3
The generic fs-safe names also work: FS_SAFE_PYTHON_MODE and FS_SAFE_PYTHON.
With the helper off, OpenClaw still uses fs-safe's Node paths for:
.., absolute paths, and path separators where only names are allowed;path.resolve(...).startsWith(...) checks;These protections cover the normal OpenClaw threat model: trusted gateway code handling untrusted model/plugin/channel path input inside a single trusted operator boundary.
On POSIX, fs-safe's optional helper keeps one persistent Python process and uses fd-relative filesystem operations for parent-directory mutations such as rename, remove, mkdir, stat/list, and some write paths.
That narrows same-UID race windows where another process can swap a parent directory between validation and mutation. It is defense in depth for hosts where untrusted local processes can modify the same directories OpenClaw is operating in.
If your deployment has that risk and Python is guaranteed to exist, use:
OPENCLAW_FS_SAFE_PYTHON_MODE=require
Use require rather than auto when the helper is part of your security posture; auto intentionally falls back to Node-only behavior if the helper is unavailable.
openclaw/plugin-sdk/* helpers, not raw fs, when a path comes from a message, model output, config, or plugin input.src/infra/* so OpenClaw's process policy is applied consistently.fs.writeFile.Related: Security, Sandboxing, Exec approvals, Secrets.