Secure File Operations: Default JavaScript Fallback and Native Mode

Learn how OpenClaw uses fs-safe for guarded file operations and why native acceleration is off by default. Essential for developers configuring secure local file handling.

Read this when

  • Changing file access, archive extraction, workspace storage, or plugin filesystem helpers

OpenClaw relies on @openclaw/fs-safe whenever local file work demands extra care: root-scoped reads and writes, atomic swaps, unpacking archives, scratch directories, JSON state, and anything touching secret files.

Think of it as a guardrail for trusted code, not a sandbox. It protects OpenClaw's own components when they receive untrusted path strings. The true blast radius stays defined by host permissions, OS accounts, containers, and the agent/tool policy.

Default: JavaScript fallback

By default, OpenClaw turns fs-safe's optional native helper off:

  • native platform packages are optional, so minimal installs may not include them;
  • the guarded JavaScript paths handle all of OpenClaw's standard filesystem needs;
  • with native loading disabled, runtime behavior stays predictable across desktop, Docker, CI, and bundled-app setups.

Only the default changes. Any explicit configuration takes precedence:

# Default OpenClaw behavior: guarded JavaScript fs-safe paths.
OPENCLAW_FS_SAFE_NATIVE_MODE=off

# Prefer native primitives when the platform package is installed.
OPENCLAW_FS_SAFE_NATIVE_MODE=auto

# Fail closed when an operation needs native support and the binding is unavailable.
OPENCLAW_FS_SAFE_NATIVE_MODE=require

The generic fs-safe environment name works as well: FS_SAFE_NATIVE_MODE.

In fs-safe 0.5, the retired FS_SAFE_PYTHON_MODE and OPENCLAW_FS_SAFE_PYTHON_MODE values are temporarily mapped to native modes, with a deprecation warning emitted. Rename those before fs-safe 0.6; Python interpreter path settings are no longer consulted.

When native primitives matter to your security stance, choose require over auto. If the platform binding is missing, auto falls back to the guarded JavaScript implementation.

What stays protected without native acceleration

Even with the helper off, OpenClaw keeps fs-safe's Node-only protections:

  • relative-path escapes (..), absolute paths, and separators are rejected where only bare names belong;
  • operations resolve through a trusted root handle rather than ad-hoc path.resolve(...).startsWith(...) checks;
  • symlink and hardlink patterns are refused on APIs that demand that policy;
  • identity checks run when files are opened for content return or consumption;
  • state and config files are written via atomic sibling-temp plus rename;
  • byte limits apply to reads and archive extraction;
  • private file modes are enforced for secrets and state where the API requires them.

That matches OpenClaw's usual threat model: trusted gateway code processing untrusted path input from models, plugins, or channels, all within a single trusted operator boundary.

What native acceleration adds

The optional platform package supplies policy-free filesystem primitives that fs-safe uses for create-only writes, guarded hard-link publication, asynchronous sidecar creation, and explicit no-replace rename publication. Linux relies on openat2 and renameat2; macOS uses descriptor-relative component checks and renameatx_np; Windows uses handle-relative operations and replacement-disabled rename.

Policy, validation, retries, cleanup, and fallback decisions all stay in the TypeScript layer. Native support narrows filesystem race windows, but it does not make fs-safe a sandbox.

If your deployment needs those native primitives, install the matching optional platform package and configure:

OPENCLAW_FS_SAFE_NATIVE_MODE=require

Plugin and core guidance

  • When a path arrives from a message, model output, config, or plugin input, plugin-facing file access should use openclaw/plugin-sdk/* helpers instead of raw fs.
  • Core code should go through the fs-safe wrappers under src/infra/* so OpenClaw's process policy applies consistently.
  • Archive extraction should use the fs-safe archive helpers, with explicit limits on size, entry count, links, and destination.
  • Secrets should use OpenClaw secret helpers or fs-safe secret/private-state helpers; do not hand-roll mode checks around fs.writeFile.
  • For hostile local-user isolation, fs-safe alone is not enough. Run separate gateways under separate OS users/hosts, or apply sandboxing.

Related: Security, Sandboxing, Exec approvals, Secrets.

572 words · updated Aug 3, 2026