Files
openclaw/docs/gateway/security/secure-file-operations.md
Peter Steinberger 0d7fb8eb39 refactor(fs): adopt fs-safe 0.5 core primitives (#113705)
* refactor(fs): unify exclusive file publication

* fix(fs): fence stale lock reclamation

* refactor(fs): bound wiki scans and secret reads

* chore(fs): finalize fs-safe 0.5 compatibility

* fix(fs): preserve publication ownership and legacy mode

* fix(fs): fail closed on unverifiable lock owners

* fix(fs): preserve concurrent backup publications

* refactor(fs): preserve ambiguous backup outputs

* fix(fs): preserve mixed-version lock coordination

* refactor(file-transfer): adopt fs-safe archive extraction

* refactor(fs): add bounded walk and secret seams

* refactor(auth): replace proper-lockfile with fs-safe

* fix(fs): honor Windows mode override casing

* refactor(snapshot): adopt fs-safe publication

* refactor(memory-wiki): adopt prunable root walks

* refactor(fleet): adopt bounded archive restore

* fix(fs): preserve post-publication ownership receipts

* refactor(fs): harvest final fs-safe primitives

* style(fs): clean harvest lint

* chore(plugin-sdk): refresh move helper API baseline

* refactor(snapshot): adopt native Windows ACL facts

* refactor(fs): adopt hardened atomic outputs

* fix(fs): scope lock reentrancy to logical owners

* chore(config): lower env var count budget

* fix(deps): adopt published fs-safe 0.5.0

* fix(ci): align SDK surface ratchets

* fix(ci): regenerate SDK API baseline after rebase

* fix(fs): preserve owner-scoped file lock nesting

* fix(ci): refresh SDK API baseline for file locks

* fix(fs): separate SQLite and file lock reentrancy

* fix(imessage): bound pinned attachment reads

* fix(agents): narrow session-key lock options

* fix(fs): preserve fs-safe 0.5 compatibility contracts

* fix(windows): retain private SQLite directory owner

* refactor(sqlite): centralize exclusive coordinator

* refactor(snapshot): isolate Windows ACL policy

* fix(windows): retain snapshot ACL inspector

* chore(config): realign env budget after rebase

* test(agents): accept canonical sandbox escape error

* docs(changelog): defer fs-safe release note
2026-07-28 03:41:47 -04:00

4.4 KiB

summary, read_when, title
summary read_when title
How OpenClaw handles local file access safely, and why optional fs-safe native acceleration is off by default
Changing file access, archive extraction, workspace storage, or plugin filesystem helpers
Secure file operations

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.

Default: JavaScript fallback

OpenClaw sets fs-safe's optional native helper to off by default:

  • native platform packages are optional and may be absent from minimal installs;
  • the guarded JavaScript paths support OpenClaw's normal filesystem operations;
  • disabling native loading keeps runtime behavior deterministic across desktop, Docker, CI, and bundled-app environments.

OpenClaw only changes the default. An explicit setting always wins:

# 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 also works: FS_SAFE_NATIVE_MODE.

fs-safe 0.5 temporarily maps the retired FS_SAFE_PYTHON_MODE and OPENCLAW_FS_SAFE_PYTHON_MODE values to native modes and emits a deprecation warning. Migrate those names before fs-safe 0.6; Python interpreter path settings are no longer used.

Use require (not auto) when native primitives are part of your security posture. auto uses the guarded JavaScript implementation when the platform binding is unavailable.

What stays protected without native acceleration

With the helper off, OpenClaw still gets fs-safe's Node-only guardrails:

  • rejects relative-path escapes (..), absolute paths, and path separators where only bare names are allowed;
  • resolves operations through a trusted root handle instead of ad-hoc path.resolve(...).startsWith(...) checks;
  • refuses symlink and hardlink patterns on APIs that require that policy;
  • opens files with identity checks where the API returns or consumes file contents;
  • writes state/config files via atomic sibling-temp + rename;
  • enforces byte limits for reads and archive extraction;
  • applies private file modes for secrets and state files where the API requires them.

This covers OpenClaw's normal threat model: trusted gateway code handling untrusted model/plugin/channel path input inside a single trusted operator boundary.

What native acceleration adds

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

The TypeScript layer still owns policy, validation, retries, cleanup, and fallback decisions. Native support narrows filesystem race windows; it does not turn fs-safe into a sandbox.

If your deployment requires those native primitives, install the matching optional platform package and set:

OPENCLAW_FS_SAFE_NATIVE_MODE=require

Plugin and core guidance

  • Plugin-facing file access should go through openclaw/plugin-sdk/* helpers, not raw fs, when a path comes from a message, model output, config, or plugin input.
  • Core code should use 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 size, entry-count, link, and destination limits.
  • 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, do not rely on fs-safe alone. Run separate gateways under separate OS users/hosts, or use sandboxing.

Related: Security, Sandboxing, Exec approvals, Secrets.