Skip to content

Bind guarded publication to the authorized directory #2360

Open

Description

@coderabbitai

Problem

At PR head 6093d2a07, createIfAbsent in src/core/tools/guardedWrite.ts checks the lock key and confirms that the authorized path is absent, then passes a canonical path string to safeWriteText in src/services/file-safety/safeWriteText.ts. The publisher resolves that path again. If an actor replaces a workspace ancestor with a symlink after the absence check, publication can resolve outside the authorized directory and overwrite an existing outside file. The advisory lock does not pin the directory.

replaceIfVersion also passes a path string to the publisher and should be assessed for the same authorization-to-publication boundary. The existing guarded-write tests mock the publisher and do not exercise this race.

Issue #2356 tracks lock-key identity for aliases. That does not by itself bind publication to the authorized directory after the absence check.

Required change

Bind authorization and publication to the same directory identity using directory handles and no-follow operations, or an equivalent atomic mechanism. Preserve the existing lock, absence-check, and version-check safeguards as applicable. Consider platform support and fail safely where the guarantee cannot be provided.

Acceptance criteria

  • Swapping an authorized directory or ancestor to an outside symlink after the absence check cannot redirect publication outside the authorized directory or overwrite the outside target.
  • Add a regression test that uses the real publisher, performs the swap after the absence check, and verifies that the write is rejected or lands in the originally authorized directory. Assert that the outside file remains unchanged.
  • Assess and cover the corresponding replaceIfVersion path where applicable.
  • Keep existing lock and guard regression tests passing.

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions