Skip to content

RFC: Anchored evidence for SAFE - #18

Open
imran-siddique wants to merge 2 commits into
OpenSecureAIAlliance:mainfrom
imran-siddique:rfc-anchored-evidence
Open

RFC: Anchored evidence for SAFE#18
imran-siddique wants to merge 2 commits into
OpenSecureAIAlliance:mainfrom
imran-siddique:rfc-anchored-evidence

Conversation

@imran-siddique

Copy link
Copy Markdown

Adds rfc-anchored-evidence.md, a proposed addition to the SAFE draft.

What it proposes

SAFE's Evidence Preservation section specifies what members must retain. It does not specify any property establishing when that evidence came into being. Every item on the list is produced by systems the reporting member owns, held in storage the member controls, and provided on a schedule running from four business days to ninety, during which the questions the review will ask become progressively clearer. A reviewer today cannot distinguish evidence recorded as an incident unfolded from evidence assembled afterwards.

The RFC proposes one property: a reviewer should be able to establish, without trusting the member under review, that an evidence item existed in its provided form at a stated time. It then describes an RFC 6962 (Certificate Transparency) construction that satisfies it, and proposes an anchored / unanchored / unavailable status field on Evidence Preservation. The requirement is that the status is stated, not that it is anchored, on the same logic the thread in #11 applied to declared gaps.

Why it fits SAFE rather than being a general transparency proposal

  • The notification timeline is itself the window. Anchoring on day zero fixes evidence before the member can know what the review will focus on.
  • A hash discloses nothing, so a member can anchor evidence during an incident they are legally barred from describing. SAFE's confidentiality model and independent verification stop being a tradeoff.
  • Near misses, which the Reporting Compact requires and which have the weakest preservation incentive, become free to record.

Limits, stated in the RFC

Inclusion proves the exact bytes provided were recorded at that timestamp and cannot be quietly un-recorded. It does not validate signatures against a producer key, does not make the evidence true, does not establish completeness (the point @bobleer raised in #11), and does not authenticate the recording environment. It narrows the window in which evidence can be shaped rather than closing it.

Contribution offer

The reference registry exists and works, and its central weakness is that we operate it. Its own roadmap names the three gaps: production volume from a producer other than ours, a mirror operated by someone with no incentive to cover for us, and maintainers from outside the originating company. Those are things a consortium supplies and a vendor cannot.

The RFC therefore offers the registry to the alliance: anchor format specification, reference tooling, schema and CI validation, mirroring documentation, and the operational pipeline. Code is Apache-2.0, registry data is CC BY 4.0. We do not require that operation stay with us. If the working group would rather specify the requirement and have members implement it independently, that is also a good outcome.

Relationship to open issues

Builds on #11, which established the gap and converged on three determinations without a mechanism for the third. Complements #14 (provenance grades) and #6 (signed tool-trust verdicts), both of which produce evidence that can be anchored. Does not address #4; an anchored record of a fail-open verification is still a fail-open verification.

Raising as a PR rather than an issue since it adds a document, per CONTRIBUTING. Happy to move the discussion to an issue if the working group prefers that first. Commit is DCO signed off.

Proposes that SAFE record an anchoring status for each preserved evidence
item, so that a reviewer can establish an item existed in its provided form
at a stated time without trusting the member under review.

Describes an RFC 6962 construction that satisfies the requirement, states
what inclusion does and does not prove, and offers the reference registry
to the alliance so it is operated by someone other than its largest producer.

Builds on the discussion in issue OpenSecureAIAlliance#11.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Imran Siddique <imran.siddique@opaque.co>
@lywinged

Copy link
Copy Markdown

This reads right to me, and asking for the status to be stated rather than requiring it be anchored is the part that makes it adoptable. Two things I got stuck on, both out of the canonicalization section.

The entry has ts, merkle_root, leaf_count, producer and batch_id, but nothing saying which canonicalization built its leaves. The RFC asks a verifier to use the rule declared for the context it is checking, and right now that is declared globally in docs/anchor-format.md, by revision. With one producer that is fine. With two, or after the format shifts, you can tell who produced a batch but not what rule they used, and entries from either side of the change are the same five fields meaning different things. A canonicalization field would cost one string. The repo is not public yet, so this may already be handled.

The other is excluding non-integer numbers. Since the leaf is the whole signed object, that is not really about how floats serialize, it means an evidence object containing one cannot be anchored. Evidence Preservation covers traces, tool calls and detection events, which carry latencies, costs and confidence scores, and the recommendations in From Lessons to Controls carry metrics. The workaround is rounding or stringifying before anchoring, and then the anchored bytes are not the bytes the reviewer holds.

On the reason given for it: RFC 8785 §3.2.2.3 does pin float serialization to ECMAScript Number::toString, and it is implementable. I have checked an implementation against a reference JCS library over a few hundred thousand values and they agree byte for byte, including where both refuse integers outside the safe range. Where it goes wrong is the exponent's leading zero and the thresholds where exponential form starts at each end. Happy to write those up as vectors if that is useful.

@zohebk8s

Copy link
Copy Markdown

Support this. The gap it names is real, and the sharpest version of it is the RFC's own reading of the Review Framework: the affected organization may correct factual errors but should not have veto power over learnings or recommendations, which assumes those facts can be established by someone other than the member holding them. Under the current draft they cannot be, and the proposal is scoped to that one property rather than to evidence handling in general.

Both points raised above look right to me, and I think they are the same point twice.

The RFC already says the two canonicalizations agree for records whose keys and strings are ASCII and whose numbers are integers, and that this is exactly what makes the divergence dangerous. Since the leaf is the whole signed object, putting the leaf on JCS as well follows that reasoning to its end: one rule instead of two, and the non-integer exclusion goes with it. That second part is the one that costs something today, because an evidence object carrying a latency or a confidence score cannot be anchored at all, and rounding or stringifying first breaks the property that the anchored bytes are the bytes the reviewer holds.

Naming the rule in the entry is worth doing whichever way that goes. A single rule still has revisions, and an entry cannot be reinterpreted after the fact, so the cheapest moment to record which rule built a batch is the moment the batch is written.

@qubeena07

Copy link
Copy Markdown

Both points make sense to me. On the canonicalization field, yeah, that's a gap. Right now the rule is just declared globally by doc revision, which is fine with one producer. But once you have two, or the format changes, you can't tell which rule built which entry just by looking at it. Adding one field to say which rule was used seems cheap compared to that risk.

The float thing is the one I keep thinking about though. Excluding non integer numbers isn't really solving a serialization problem, it's just saying certain evidence can't be anchored at all. And a lot of what this RFC covers, traces, tool calls, detection events, is going to have a score or a latency or a cost in it somewhere. If you have to round or stringify a number to get it anchored, then the thing you anchored isn't actually the thing you have anymore. That kind of defeats the point.

If RFC 8785 already handles this and the only real issues are small edge cases like exponent formatting, that sounds fixable rather than a reason to just ban floats. Would definitely want to see those test vectors if you write them up, that would make it a lot easier for people to just agree on the ECMAScript rule and move past this.

@CyberGuardian-XRSI

Copy link
Copy Markdown

The gap this addresses is real, and the timing argument is the sharpest version of it: the notification timeline is itself the shaping window, and anchoring on day zero fixes evidence before the member knows what the review will focus on. That is a stronger constraint than anything in the current draft.

The status-not-mandate framing is the right call and follows the same logic as declared gaps in #11: the requirement is that the state is stated, not that it is anchored. A member anchoring nothing has disclosed that, and a reviewer can weight it accordingly.

The near-miss point is undersold. Near misses have the weakest preservation incentive because nothing went wrong, so there is no trigger to preserve anything. A hash costs nothing and discloses nothing, which makes recording a near miss free. That connects directly to a gap in the Reporting Compact: near-miss reporting is required but there is no trigger that fires on one.

On the float exclusion, @lywinged and @zohebk8s have it right and it is the same problem twice. If an evidence object carrying a latency or confidence score cannot be anchored, and the workaround is rounding or stringifying before anchoring, then the anchored bytes are not the bytes the reviewer holds. That breaks the property the construction exists to provide, since Evidence Preservation explicitly covers traces, tool calls, and detection events, all of which carry non-integers. JCS on the leaf as well, as zohebk8s suggests, resolves both at once.

On independence: you have disclosed the central weakness clearly. The requirement should be specifiable independently of who operates the registry, so adoption does not depend on that governance question resolving first. The three gaps you name in the roadmap are the right three, and a consortium is the right structure to close them.

Disclosure: I am a technical contributor to the AARM specification, which produces tamper-evident receipts binding action, context, decision and outcome. I raise this as supporting comment rather than as advocacy for any particular implementation.

Reviewers on the PR converged on the same gap: the entry names who produced
a batch but not which rule built its leaves. Declaring the rule globally by
document revision holds with one producer and stops holding with two, or
after the rule is revised, because entries either side of the change carry
identical fields and mean different things.

Adds a `canonicalization` field to the entry, and points the verifier at it
rather than at the document revision in force when the batch was written.

Raised by @lywinged, seconded by @zohebk8s, @qubeena07 and @CyberGuardian-XRSI.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Imran Siddique <imran.siddique@opaque.co>
@imran-siddique

Copy link
Copy Markdown
Author

Thanks, all four of you. Taking the two points in the order they cost something.

The canonicalization field is in. @lywinged is right and @zohebk8s is right that it is worth doing whichever way the second question goes, because a single rule still has revisions and an entry cannot be reinterpreted after the fact. Pushed as a sixth field:

| canonicalization | string | Identifier of the rule that produced this batch's leaves |

The verifier now reads the rule off the batch instead of inferring it from the document revision in force when the batch was written. The repo is not public yet, so this was not already handled; it was a real gap.

On excluding non-integer numbers, you have all landed on the same thing and the reason stated in the RFC does not survive checking. I went to RFC 8785 rather than take it. Section 3.2.2.3 pins number serialization to ECMA-262 section 7.1.12.1 including the Note 2 rule, names V8 and Ryu as reference implementations, and Appendix B gives a sample set with the edge cases in it. The exponential-form threshold @lywinged names is visible there directly: 999999999999999900000 stays positional and the next value up serializes as 1e+21. So "cross-language float serialization is not canonical" is wrong as written, and the exclusion it justifies is doing real damage, because Evidence Preservation covers traces, tool calls and detection events and those carry latencies, costs and confidence scores. Rounding or stringifying first breaks the one property the construction exists to provide.

One correction, because it becomes a new trap if the leaf moves to JCS. @lywinged, JCS does not refuse integers outside the safe range. Appendix B note (1) says values meant as true integers SHOULD sit in -9007199254740991 to 9007199254740991 but adds that how numbers are used does not affect the algorithm, and note (2) has 2**68 serializing without complaint as 295147905179352830000. So an out-of-range integer canonicalizes cleanly and can lose precision on a round trip through a double, silently. That is the same failure class the RFC already flags: it passes every test the implementer writes and breaks when a second organization writes its own verifier. If the leaf goes to JCS the integer range has to be stated as a constraint on the evidence object, not left implicit.

@lywinged, yes to the vectors, please. Appendix B does not cover the exponent leading zero, and the thresholds at each end are the part everyone gets wrong independently. If you write them up I will run them against the reference verifier and put them in the repo as a conformance set, credited to you. That is more useful to this RFC than anything else on the list right now.

@CyberGuardian-XRSI on near misses, that is a better version of the point than the one I made. The Reporting Compact requires near-miss reporting and has no trigger that fires on one, and I had it as a benefit of anchoring rather than as a gap in the Compact. Worth raising separately from this PR since it stands whether or not anchoring is adopted.

What I am not doing unilaterally. Putting the leaf on JCS is the right direction and I am not going to pretend otherwise, but it changes every leaf hash the reference registry has already written, so it lands as a new rule identifier under the field above rather than as a rewrite. Existing entries keep saying which rule built them and stay verifiable; new batches move. I would rather the working group decide whether the RFC should specify JCS on the leaf now or state it as the intended revision pending the vectors, since that is a question about what SAFE requires and not about my implementation.

@zohebk8s, on the Review Framework reading: agreed, and that is the argument I should have led with. The clause says the affected organization may correct factual errors but has no veto over learnings, which only means something if those facts can be established by someone other than the member holding them.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants