Skip to content

security(attestation): pin sealed evidence root by descriptor across path swaps #2304

Open

Description

@seonghobae

Finding

The current scientific-validation verifier validates --evidence-root path components, enumerates that pathname, and then opens the evidence leaf by pathname. O_NOFOLLOW protects only the leaf component. If the validated root directory is renamed/replaced with a symlink between root validation/enumeration and leaf open, the subsequent leaf open can traverse the replaced ancestor and read a different directory.

This is a path-authority TOCTOU gap, distinct from #2302's same-leaf double-read defect and #2303's special-file blocking defect. The exact evidence bytes are still read once, but the directory authority used to select those bytes is not pinned for the duration of intake.

Required repair

  • Add a realistic hostile RED that swaps the validated root pathname to a symlink immediately before the evidence read. The predecessor should accept bytes from the replacement directory when the caller-supplied SHA matches those bytes.
  • Open the sealed root through directory descriptors without following symlink components and retain that descriptor through cardinality enumeration and leaf open.
  • Enumerate members from the pinned directory descriptor and open the sole evidence filename relative to that descriptor (dir_fd / openat semantics) with the existing O_NOFOLLOW | O_NONBLOCK leaf controls.
  • Preserve the one-byte-snapshot hash/parse semantics, strict schema/binding checks, and output-boundary rules.
  • Keep this an unsigned local-integrity control; do not describe it as provenance authentication or a signed attestation.
  • Add the hostile case to the existing exact-head 100% owned coverage gate.

Acceptance

A root-path replacement after the directory descriptor is acquired cannot redirect evidence selection. Exact-head hosted GREEN and independent review are still required before normal landing. No force push, gate weakening, or predecessor receipt reuse.

Refs #2299 #2300 #2302 #2303 ContextualWisdomLab/TEPP#637.

Activity

  1. seonghobae commented on Sep 20, 2026

    @seonghobae
    ContributorAuthor

    #2304 implemented ordinary-forward on the existing #2300 owner lane.

    Lineage:

    • source-level hostile RED: 50edf085aa6a12809e895ae9695fcaeb96666e80;
    • causal production repair: 85e2c07e2d3f49787d8d5b5eff0b08b862bd98ed;
    • symlink-component refusal / owned coverage follow-up: 7398c85ce01328782cb3b05d64d85947fc369ce2;
    • CHANGELOG: ee55b38ef349c114fdec9450d195b1f5382bf5ac;
    • doctoring/current exact head: 787d9a4f4f27eb5d81bb2cbb94d9e4a0a162cd07.

    The verifier now walks the sealed root component-by-component with O_DIRECTORY | O_NOFOLLOW, retains that directory descriptor across one-member enumeration, and opens the evidence filename relative to it. A post-validation root pathname replacement cannot redirect the evidence read. The existing O_NONBLOCK | O_NOFOLLOW leaf open and one-byte-snapshot hash/parse contract remain intact.

    This remains unsigned local filesystem-integrity hardening, not provenance authentication. Hosted exact-head checks are newly generated and non-terminal; no GREEN or independent approval is claimed, so this issue remains open pending acceptance.

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