Skip to content

fs-safe 0.13.0

Choose a tag to compare

@github-actions github-actions released this 16 Sep 17:59
· 540 commits to main since this release
v0.13.0
b1987ff

Highlights

  • Stronger protection against filesystem replacement races: bind Root reads, metadata, writes, moves, and cleanup to exact file and directory identities; use atomic native rename for no-clobber moves.
  • Less overhead in guarded writes and archives: avoid repeated path and mutation-policy work on eligible routes, reuse validated archive paths, and size native result buffers to bounded member sizes.
  • Safer Windows paths and writes: reject NTFS stream and directory-index aliases before filesystem access, and retain destination handles through compatibility writes and verification.
  • New tools for prospective paths: add resolvePathPrefixSync() and probePathSuffixAliasesSync() for existing-prefix traversal and bounded observations of missing suffix aliases.
  • Opt-in bounded temporary-file cleanup: add retained-directory cleanup ownership to tempFile() and strengthen temporary-workspace admission and permission repair.

Compatibility and upgrade notes

  • No-clobber Root.move() now requires usable native support. With overwrite omitted or false, native-off mode, missing bindings, or unavailable safe parent/rename support fail with helper-unavailable; there is no JavaScript check-and-replace fallback. Keep the matching native package installed for these moves. Directory moves still require overwrite: true, which retains guarded JavaScript support; use it only when replacement is intended. Post-operation verification can report an error after a rename has completed.
  • Windows alternate-data-stream and directory-index aliases now reject across guarded APIs before I/O. Supported rooted and extended-drive paths retain their handling, as do released drive-relative forms in trusted-path atomic, store/queue, move, publication, and lock APIs. Existing Root destination restrictions remain distinct; ordinary colon-bearing POSIX names keep their established rules.
  • POSIX secure-file ownership checks now use the process's effective user ID and fail closed when required identity facts are unavailable. Public Stats values remain numeric; exact writable-file verification uses private bigint receipts.
  • tempFile({ cleanupSafety: "require-bounded" }) is opt-in and requires an existing supplied root plus supported retained-parent cleanup. Unsupported admission fails before child creation. "compatible" remains the default; cleanup callbacks and error-suppression behavior are preserved. Bounded cleanup retains the documented POSIX final-entry unlink limitation.
  • The two new path helpers are observations, not permission to access a path. Prefix resolution is read-only but is not a pinned or consistent snapshot. Suffix probing can create and remove directories under an approved writable parent, returns undefined when unresolved, and may preserve artifacts whose ownership cannot be verified; its budgets limit work counts and path sizes, not elapsed time.

Root boundaries and mutation performance

  • Fence Root content reads, metadata observations, directory entries, and low-level file opens with exact captured-root, parent, and final-path identities. Admit supported native Windows root spellings without relaxing symlink or replacement rejection.
  • Apply denyMutations and mutation-symlink policy to the actual retained parent used by Root.write, Root.create, Root.copyIn, Root.openWritable, Root.append, and Root.mkdir, including Windows buffer fallbacks. Admit missing components before creating them, and re-authorize followed final-link destinations before open, truncation, staging, and publication.
  • Reuse operation-local policy observations, canonical parent guards, post-create receipts, and immutable suffix offsets for eligible Node.js mutation paths. This avoids repeated resolver work and depth-quadratic segment copies; collisions, callbacks, aliases, ambiguous routes, incomplete identity observations, and final open/publication/cleanup checks retain full admission.
  • Bound repeated resolver work during deep missing-parent creation on eligible Windows and POSIX JavaScript paths. Advance only through owned directory-creation receipts, and let Root.mkdir reuse an exact existing-parent proof for its single missing child.
  • Reuse an already admitted parent guard for private producer Roots while preserving isolated handoff, including legacy Windows delete-pending and read-only restoration behavior.
  • Bind nonrecursive removal to its admitted parent and revalidate native move endpoints and explicit parent-symlink rejection before dispatch. Recheck copied-directory identities after child cleanup so concurrent replacements are preserved.

Credentials, permissions, and temporary files

  • Snapshot secure-read, secret-reader, traversal, and borrowed-transfer policies before asynchronous work, including size/link limits, trusted directories, and selected environment values. In-flight admission can no longer be relaxed by changing shared options.
  • Preserve single-read pathname and authority accessors on Node.js 22, along with callback receivers, cancellation signals, and progress callbacks across JSON, durable directory/queue, sibling-staging, and borrowed-handle operations. Windows temp admission remains active with platform adapters, and canonical prefixes are checked before inspection.
  • Bind secure temporary-directory and synchronous store-directory mode repairs to no-follow descriptors and exact current identities, including concurrent mode changes during the matching-mode fast path.
  • Admit temporary-workspace roots and children before use, preserve existing permissions, and bind initialization and cleanup to retained identities. Opt-in bounded temporary-file admission closes descriptors on failure.
  • Retain Windows destination descriptors through buffered compatibility-write locking, content verification, mode changes, sync, and final identity checks.
  • Validate descriptor-bound macOS clone ACLs before admission and publication, including absent ACLs. Once payload bytes exist, normalization or security failures are terminal EIO errors rather than a reason to retry with an ordinary copy.

Archive safety and performance

  • Bind physical ZIP entry names and file/directory kinds to decoder metadata before callbacks or member selection, rejecting ambiguous interpretations consistently.
  • Stop zstd and bzip2 compressed-input refills after cancellation while preserving decoded-output limits and complete archive validation.
  • Reuse canonical archive paths when no components are stripped and avoid temporary ZIP collision collections, retaining validation/filter order and checks of both raw and Unicode identities.
  • Reserve native archive result capacity from bounded member-size hints so small ZIP and compressed TAR reads do not allocate the caller's larger byte budget.

Path helpers and reliability

  • Add resolvePathPrefixSync() under @openclaw/fs-safe/advanced to traverse existing path prefixes while retaining the raw missing suffix, preserving dangling aliases and propagating ambiguous resolution failures.
  • Add probePathSuffixAliasesSync() under @openclaw/fs-safe/advanced, with fixed path, depth, creation, and observation budgets and conservative identity-checked cleanup.
  • Sanitize fallback filenames and validate completed sibling callback names before producers run, retaining length bounds and Windows device-name rejection. Reuse Windows namespace admission for unchanged ordinary rooted-drive paths while keeping full checks for relative, normalized, malformed, namespaced, and colon-bearing forms.
  • Pin asynchronous relative sidecar-lock paths and roots to their entry-time working directory through acquisition, reclaim, verification, and release. Close synchronous lock descriptors after metadata inspection failures while preserving the original error and unverified sidecar; retry vanished admitted successors under the existing identity checks and budgets.
  • Report actionable guarded-write errno diagnostics while preserving error codes, categories, original causes, and already-classified failures.
  • Tolerate concurrent guest parent-directory creation only after descriptor-relative no-follow admission; file and symlink competitors remain rejected. Thanks @vincentkoc.
  • Show only the moon icon in the docs light-theme picker and only the sun icon in dark mode.

Validation and tooling

  • Strengthen exact-identity, rounded-inode, Windows recovery, mutation-policy, and package-consumer regressions, with explicit test-hook provenance and bounded fixture lifetimes. Queue stress fixtures retain and drain outstanding writers before cleanup.
  • Separate manual method-audit harnesses from immutable candidate and baseline checkouts, validate dispatch inputs before fan-out, and support Node 22/24 plus rebuild and same-artifact controls. Versioned benchmark receipts bind source, harness, dependencies, artifacts, native addons, and runner metadata; they detect accidental drift and are not a sandbox for hostile code.
  • Expand benchmark coverage for filename sanitizers, all 17 profiles, shared mutation admission, temporary-workspace modes, and existing/missing roots at depths 4/8/32. Keep Windows-specific rows and observed-preservation claims distinct from JavaScript operation counts.
  • Isolate split-credential proof runners, authenticate official Node archives before checkout, and use private, identity-checked stages and tools. Fixtures remain traversable by both dropped identities while published receipts stay in a separately admitted container; the seven behavioral cases are unchanged.
  • Update development tooling to @napi-rs/cli 3.9.1, fast-check 4.10.0, and Vite 8.3.0 with verified registry integrity.

Published packages

Package Registry tarball Verified integrity Provenance
@openclaw/fs-safe-linux-x64-gnu@0.13.0 tgz sha512-tp3yQxmm9HFHCDGPgYsqVmtzPg7LovusfVtBK4Q/DlW4+JJc1NAzT4NfeOcxqYAYbXdHS9jidXNmrZHqXNz2fg== verified attestation
@openclaw/fs-safe-linux-x64-musl@0.13.0 tgz sha512-0S+i258RQh9mGZKIrs+vVGJEwM6fcOlUM7zvGjMEm5IDhb9FxwlI9iZncsBa88Ic4Sxt1hKjKT4L+J3W9/E44w== verified attestation
@openclaw/fs-safe-linux-arm64-gnu@0.13.0 tgz sha512-GAf5q5e65n/CU1JXo7ODbv0B90SUc9JvCwog2ZcQWEYCqumaA4T8qgcBF2GZcDiloNZ0GuUADPppujdDJoxPTg== verified attestation
@openclaw/fs-safe-linux-arm64-musl@0.13.0 tgz sha512-HiU0M8/pl3FCVi625v7fVuxHcgiLPNiQeY7bfEfUrvR4NcWkyjcg8L8jwfDeIm4MSnEjb0+hmL2MyrdRZDGDNg== verified attestation
@openclaw/fs-safe-darwin-x64@0.13.0 tgz sha512-7Gs3BY7/2kOQjJ1fo60SdwA/C1bHMKW6CUC9tJI/samfCRj7Am2PW4y83h3/0P9Otd9qV7KSyxeYJYyMbMN+7Q== verified attestation
@openclaw/fs-safe-darwin-arm64@0.13.0 tgz sha512-/rbWVk5YZcCP2LAfg0yGRie3W5mJuNvBphF8uzk8m4SUTXie20BwYFzeJFsQ+dLAivbosETc000UcCj8hWFS+Q== verified attestation
@openclaw/fs-safe-win32-x64-msvc@0.13.0 tgz sha512-SSCcih/vUV6fR/LU2eTFgzB6DIXH0dftpER4Oglfy+i88oq+HmLlTOJEDRGv2iUkF0+kRpEMEqSUuoOWCY8/ZA== verified attestation
@openclaw/fs-safe@0.13.0 tgz sha512-8dyH9wMH5PFsOZZocY/lb+EYFMVN3+BMaPo0z2a1YwaOrkwrEt6kLvhI2g0X2AAKeq75r99cS1aMvY+Tk3wa6g== verified attestation

Release proof: GitHub Actions run.