Skip to content

security(attestation): isolate verifier outputs from sealed evidence and symlinked parents #2301

Open

Description

@seonghobae

Finding

The scientific-validation inert verifier in #2300 validates symlinks for the sealed evidence root and the final output path, but _atomic_json creates/uses path.parent without rejecting symlinked output ancestors. It also permits output_predicate == output_manifest and permits either output path to live inside the sealed evidence root.

Those cases are currently caller-controlled CLI values. A future credentialed #2299 signer is expected to treat the verifier outputs as trusted predicate/receipt material, so the verifier should make the filesystem authority boundary explicit before signer credentials are introduced.

Failure modes

  • A symlinked output parent can redirect trusted-looking verifier output outside the intended directory even though the leaf path itself is not a symlink.
  • Equal predicate/manifest paths cause the second atomic replace to overwrite the first while verification still returns success.
  • An output inside the sealed evidence root mutates the one-member evidence set after its bytes/cardinality were verified, weakening the sealed-artifact invariant for subsequent stages.

This is not a claim that current #2300 authenticates the caller; it is an owner-local filesystem integrity defect in the unsigned verifier boundary.

RED / repair

Add deterministic contracts that reject: (1) symlink ancestry in either output parent, (2) identical predicate and manifest paths, and (3) outputs located within the sealed evidence root. Then validate both output destinations before any publication and keep atomic replacement/temporary cleanup behavior unchanged.

Do not add signer/OIDC credentials here and do not weaken existing strict evidence parsing. Refs #2299 #2300 ContextualWisdomLab/TEPP#637.

Activity

  1. seonghobae commented on Sep 20, 2026

    @seonghobae
    ContributorAuthor

    Implemented on #2300 without adding signer credentials or changing the scientific predicate semantics.

    RED/repair lineage:

    • 2205025c99d2e195def5e8173d9c245e642f8548: hostile output-boundary contracts (symlinked output parent, predicate/manifest path collision, output inside sealed root).
    • 41fbde2e370bc5f7565bd5742060cf2cbcffa391: quality workflow includes the new contracts; predecessor verifier would fail them. No terminal hosted RED is claimed because repair followed immediately.
    • c2cc2c10875488632838b1b75540c7529319266c: production verifier validates output parent ancestry, separation from the sealed root, and distinct predicate/manifest destinations before publication.
    • c7bc60901a29eb5d16c793b08219fd6e7382e566 / 9e82de292772111dc4b4afa178150b9e10fe6cb4: CHANGELOG and doctoring currentization, including removal of closed codeql: preserve base/head configuration identity for PR differential analysis #2133 as a live blocker.

    Current exact head is 9e82de292772111dc4b4afa178150b9e10fe6cb4. Hosted quality/security jobs are non-terminal; the verifier-quality job has runner_id=null and steps=[], so this issue remains open pending exact-head GREEN/review rather than inheriting predecessor receipts.

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