Skip to content

TR-ANC: Level 2 passes on any string that parses as an https URI #70

Description

@imran-siddique

What TR-ANC checks today

src/trace_tests/modules/tr_anc.py is the whole Level 2 anchoring gate:

  • transparency is present
  • it is a string
  • urlparse gives it an https scheme and a non-empty netloc

That is the complete test. The URI is never resolved, no receipt is parsed, and no inclusion proof is checked.

What the spec asks for

spec/trace-v0.2.md is specific about this field:

  • Section 3.2 claim table: transparency is an "Inclusion proof on append-only log", carried as a SCITT Receipt URI.
  • Section 3.3, step 6 of the verification sequence: "SCITT receipt resolves on the named transparency log."
  • Section 3.2.3 anchors record-signing key revocation to transparency-log entry ordering, so a receipt that resolves to nothing takes revocation semantics down with it.

So the suite currently passes a record at Level 2 on a property the spec does not care about, the string parsing, while testing none of the property it does care about.

Why it matters

Level 2 is the level an implementer cites to say their records are anchored. Today this passes:

"transparency": "https://example.invalid/nothing-here"

Run it:

trace-tests verify --record record-with-fake-uri.json --level 2

TR-ANC-001 PASS transparency is a valid URI

A verifier that trusted the badge would be relying on an anchor that does not exist. Any implementation can clear Level 2 by adding a well-formed string to a field, which makes the level unusable as a signal and, worse, misleading to whoever reads it.

Found while running the suite against a record with a real hardware measurement. The record honestly cannot reach Level 2, because it is not anchored, and the only thing standing between it and a Level 2 badge was our own decision not to type a URL into the field.

Options

Not proposing an implementation, since the right answer depends on how much the suite is willing to do at verification time.

  1. Structural only, offline. Require the receipt itself rather than a bare URI: parse it, check it names a log, carries a leaf and an audit path, and that the path length is plausible for the claimed tree size. Catches the empty-string-with-https-prefix case without any network.
  2. Verify the proof, offline. Take the receipt plus the claim and recompute the root, RFC 6962 leaf hashing and RFC 9162 inclusion verification. This is the check that actually means something, and it needs no callback, which preserves the offline-verification property section 3.3 is built on. agentrust-io/trace-registry already has both halves in tools/anchor.py and tools/verify_inclusion.py.
  3. Resolve the URI. Strongest, and it contradicts section 3.3 by putting a network dependency in the verification path. Probably belongs behind a flag, not in the default gate.

Option 2 looks like the one that matches what the spec says a Level 2 record is, and the code to do it already exists in the org.

Same family as #63: a field the spec treats as load-bearing, with a conformance module that does not hold it to that.

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