Skip to content

Eliminate remaining backup and bundle-cache TOCTOU races #212

Description

@ian-pascoe

Problem

Two residual file-lifecycle races remain:

  1. backup reads use separate stat/read opens, so replacement or growth between calls can bypass the 64 MiB bound; no-force destination checks use existsSync followed by rename, so a destination created in the race window may be overwritten;
  2. bundle-cache cleanup can delete generic .tmp-* directories created by another cache/process without proving staleness or ownership.

Acceptance criteria

  • Backup opens once, fstats and bounded-reads the same handle.
  • No-force publication uses an atomic no-replace primitive; force replacement remains explicit.
  • Bundle cleanup skips locally pending fingerprints and deletes only age-gated stale candidates.
  • Fault/concurrency tests cover replacement, growth, competing destination creation, and active materialization cleanup.

Evidence

Review anchors: packages/core/src/cli/storage.ts around backup read/publish (~812-849) and packages/core/src/storage/bundle-cache.ts around cleanup (~170).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions