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.
It is a library guardrail for trusted OpenClaw code that receives untrusted path names, not a sandbox. Host filesystem permissions, OS users, containers, and the agent/tool policy still define the real blast radius.
OpenClaw sets the fs-safe POSIX Python helper to off by default:
OpenClaw only changes the default. An explicit setting always wins:
# 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 path.
OPENCLAW_FS_SAFE_PYTHON=/usr/bin/python3
The generic fs-safe env names also work: FS_SAFE_PYTHON_MODE and FS_SAFE_PYTHON.
Use require (not auto) when the helper is part of your security posture; auto silently falls back to Node-only behavior if the helper cannot start.
With the helper off, OpenClaw still gets fs-safe's Node-only guardrails:
..), absolute paths, and path separators where only bare names are allowed;path.resolve(...).startsWith(...) checks;This covers OpenClaw's normal threat model: trusted gateway code handling untrusted model/plugin/channel path input inside a single trusted operator boundary.
On POSIX, the optional helper keeps one persistent Python process and uses fd-relative filesystem operations for parent-directory mutations: rename, remove, mkdir, stat/list, and some write paths.
That narrows same-UID race windows where another process swaps a parent directory between validation and mutation — defense in depth on hosts where untrusted local processes can modify the same directories OpenClaw operates in.
If your deployment has that risk and Python is guaranteed to exist, set:
OPENCLAW_FS_SAFE_PYTHON_MODE=require
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 applies consistently.fs.writeFile.Related: Security, Sandboxing, Exec approvals, Secrets.