From c71ffbaa8b8515317b4994aa284c8f46c3bb2b68 Mon Sep 17 00:00:00 2001 From: Rul1an Date: Tue, 28 Jul 2026 22:21:59 +0200 Subject: [PATCH 1/2] fix(json): reject the Unicode noncharacters in every string literal suiteRevision 6 makes the RFC 7493 section 2.1 exclusion normative: the sixty-six noncharacters, U+FDD0 through U+FDEF and U+nFFFE and U+nFFFF in each of the seventeen planes, are malformed wherever a string literal appears, at any depth and in member-name as well as value position. This checker admitted them, and the reason is worth recording because it was not an oversight. The earlier text scoped its MUST to string literals being well-formed sequences of Unicode scalar values, and a noncharacter is a scalar value, so the narrower rule was implemented faithfully. What the revision changes is the rule, not the reading: the strict-I-JSON label above that MUST had always implied the wider RFC 7493 exclusion, and the revision closes the gap between the label and the rule underneath it. Both routes into a string body are covered, because the exclusion is over code points and a producer reaches them either way: the raw UTF-8 byte, and the escape including a surrogate pair resolving into a plane-end noncharacter. The plane-end pairs differ only in their lowest bit, so one mask covers all thirty-four, and a test walks the whole code space to confirm the predicate selects exactly sixty-six. Refs in-toto/attestation#570. Co-Authored-By: Claude Opus 5 (1M context) --- src/json.rs | 81 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 7 deletions(-) diff --git a/src/json.rs b/src/json.rs index 2e91b79..f86063d 100644 --- a/src/json.rs +++ b/src/json.rs @@ -281,15 +281,15 @@ impl<'a> Parser<'a> { return Err(ParseError("invalid surrogate pair".into())); } let c = 0x10000 + ((cu as u32 - 0xD800) << 10) + (lo as u32 - 0xDC00); - out.push(char::from_u32(c).ok_or_else(|| { - ParseError("invalid surrogate pair".into()) - })?); + let c = char::from_u32(c) + .ok_or_else(|| ParseError("invalid surrogate pair".into()))?; + Self::push_scalar(&mut out, c)?; } else if (0xDC00..0xE000).contains(&cu) { return Err(ParseError("lone low surrogate".into())); } else { - out.push(char::from_u32(cu as u32).ok_or_else(|| { - ParseError("invalid \\u escape".into()) - })?); + let c = char::from_u32(cu as u32) + .ok_or_else(|| ParseError("invalid \\u escape".into()))?; + Self::push_scalar(&mut out, c)?; } } _ => return Err(ParseError("invalid escape".into())), @@ -301,13 +301,30 @@ impl<'a> Parser<'a> { let s = std::str::from_utf8(&self.bytes[self.pos..]) .map_err(|_| ParseError("invalid UTF-8".into()))?; let c = s.chars().next().unwrap(); - out.push(c); + Self::push_scalar(&mut out, c)?; self.pos += c.len_utf8(); } } } } + /// Append one resolved scalar value to a string being parsed, rejecting the + /// Unicode noncharacters. + /// + /// Both routes into a string body pass through here, the escape and the raw + /// UTF-8 byte, because the exclusion is over code points and a producer can + /// reach any of them either way. + fn push_scalar(out: &mut String, c: char) -> Result<(), ParseError> { + if is_noncharacter(c) { + return Err(ParseError(format!( + "Unicode noncharacter U+{:04X} in string", + c as u32 + ))); + } + out.push(c); + Ok(()) + } + fn parse_hex4(&mut self) -> Result { if self.pos + 4 > self.bytes.len() { return Err(ParseError("truncated \\u escape".into())); @@ -376,6 +393,21 @@ pub fn utf16_units(s: &str) -> Vec { s.encode_utf16().collect() } +/// True for the sixty-six Unicode noncharacters: U+FDD0 through U+FDEF, and +/// U+nFFFE and U+nFFFF in each of the seventeen planes. +/// +/// These are valid Unicode scalar values, so unlike an ill-formed sequence +/// nothing substitutes for them and no decoder splits on them. RFC 7493 +/// section 2.1 forbids them in the same sentence as surrogates, and the +/// predicate excludes them wherever a string literal appears so that a verifier +/// implementing the I-JSON label does not reject a record another verifier +/// accepts. The plane-end pairs differ only in their lowest bit, so one mask +/// covers all thirty-four of them. +pub fn is_noncharacter(c: char) -> bool { + let u = c as u32; + (0xFDD0..=0xFDEF).contains(&u) || (u & 0xFFFE) == 0xFFFE +} + /// True when every code point of `s` is in the Basic Multilingual Plane. pub fn is_bmp_only(s: &str) -> bool { s.chars().all(|c| (c as u32) <= 0xFFFF) @@ -579,6 +611,41 @@ mod tests { assert!(parse(too_deep_array.as_bytes()).is_err()); } + #[test] + fn noncharacter_set_is_exactly_sixty_six() { + let n = (0..=0x10FFFFu32) + .filter_map(char::from_u32) + .filter(|c| is_noncharacter(*c)) + .count(); + assert_eq!(n, 66); + // The two shapes, and the code points on either side of each boundary. + assert!(is_noncharacter('\u{FDD0}') && is_noncharacter('\u{FDEF}')); + assert!(!is_noncharacter('\u{FDCF}') && !is_noncharacter('\u{FDF0}')); + assert!(is_noncharacter('\u{FFFE}') && is_noncharacter('\u{FFFF}')); + assert!(is_noncharacter('\u{10FFFE}') && is_noncharacter('\u{10FFFF}')); + assert!(!is_noncharacter('\u{FFFD}') && !is_noncharacter('\u{10000}')); + } + + #[test] + fn noncharacters_rejected_by_either_route() { + // Raw UTF-8 in a value, in a member name, and nested. + assert!(parse("{\"a\":\"x\u{FFFF}y\"}".as_bytes()).is_err()); + assert!(parse("{\"a\u{FDD0}b\":1}".as_bytes()).is_err()); + assert!(parse("{\"a\":[{\"b\":\"\u{1FFFE}\"}]}".as_bytes()).is_err()); + // The same code points as escapes, including via a surrogate pair, + // since the exclusion is over code points and not over spelling. + assert!(parse(br#"{"a":"\uFFFF"}"#).is_err()); + assert!(parse(br#"{"a":"\uFDD0"}"#).is_err()); + assert!(parse(br#"{"a":"\uD83F\uDFFE"}"#).is_err()); // U+1FFFE via a surrogate pair + assert!(parse(br#"{"a":"\uFDEF"}"#).is_err()); + // Immediate neighbours still parse, so this rejects the noncharacters + // rather than the neighbourhood they sit in. + assert!(parse(br#"{"a":"\uFFFD"}"#).is_ok()); + assert!(parse(br#"{"a":"\uFDCF"}"#).is_ok()); + assert!(parse(br#"{"a":"\uFDF0"}"#).is_ok()); + assert!(parse(br#"{"a":"\uD83D\uDE00"}"#).is_ok()); // U+1F600 + } + #[test] fn scalars_do_not_consume_depth() { // Breadth is not depth: a shallow object with many scalar members must From 61120330a5c61c9221b1c06322de0b9e40d820f1 Mon Sep 17 00:00:00 2001 From: Rul1an Date: Tue, 28 Jul 2026 22:21:59 +0200 Subject: [PATCH 2/2] feat: record suiteRevision 6 at 153/153 and repin CI The unchanged revision-5 checker scored 151/153. The depth-boundary pair ok-036 and bad-742 passed on the container-branch counter already in place; bad-743 and bad-744 did not, and those two are what the previous commit fixes. The record says plainly that this run is directed, and more so than revision 2 was: the rule was written and the vectors named before this checker ran, so what it shows is that the corrected rule is implementable from the text, not that an outside reader found something. Revision 5 is retired from continuous verification and keeps its checkerCommit, 88c37d1, so its provenance stays checkable after the pin moves. The workflow follows: suite pin, spec pin, the compared report, and the parity string the corpus step greps for. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/conformance.yml | 12 +-- NOTES.md | 10 +- README.md | 8 +- reports/INDEX.json | 16 ++- reports/suite-revision-6.json | 155 ++++++++++++++++++++++++++++++ 5 files changed, 187 insertions(+), 14 deletions(-) create mode 100644 reports/suite-revision-6.json diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index 416975c..4d82ca7 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -1,7 +1,7 @@ name: conformance # The parity number in the README is only worth what a third party can re-run. -# This pins the suite commit and the spec digest, demands the full 149/149, and +# This pins the suite commit and the spec digest, demands the full 153/153, and # compares a fresh run against the checked-in evidence, so the repository cannot # drift away from its own claim. on: @@ -14,8 +14,8 @@ permissions: contents: read env: - SUITE_COMMIT: ea25a1e218e94843e018dffc0eae4f3fcab1749e - SPEC_DIGEST: 39233b27b7f27b94ed727a3852030c69c7a64e5706b73519848a2b02f244e661 + SUITE_COMMIT: 7098f4e6b7d04c8394969ed81b4025d4d9038324 + SPEC_DIGEST: 606215de629d5f5eda9e62826cf511733b1ec0b9ca8ed07662a5c8bfe181d0b9 jobs: parity: @@ -67,11 +67,11 @@ jobs: # something is already wrong, so it gets held shut here. run: python3 tests/test_compare_report.py - - name: Full corpus, 149/149 required + - name: Full corpus, 153/153 required run: | set -euo pipefail cargo run --locked --release -- aee-conformance/vectors --json fresh.json | tee run.txt - grep -q 'parity: accepts 35/35, rejects 114/114' run.txt + grep -q 'parity: accepts 36/36, rejects 117/117' run.txt - name: Fresh run must match the checked-in evidence - run: python3 scripts/compare-report.py fresh.json reports/suite-revision-5.json + run: python3 scripts/compare-report.py fresh.json reports/suite-revision-6.json diff --git a/NOTES.md b/NOTES.md index 459efab..db426e3 100644 --- a/NOTES.md +++ b/NOTES.md @@ -9,6 +9,7 @@ | 3 | `cf0d5402327ae5a451efebc914852d1c687753ca` | `d3872a02875b2da8de0263e93fb92ca6f5ab0fd75f07ed3762a1b18b0c1712a3` (unchanged) | 140 | 140/140 | | 4 | `b886c0a` | — | — | not run here | | 5 | `ea25a1e218e94843e018dffc0eae4f3fcab1749e` | `39233b27b7f27b94ed727a3852030c69c7a64e5706b73519848a2b02f244e661` | 149 | 149/149 (148/149 unchanged) | +| 6 | `7098f4e6b7d04c8394969ed81b4025d4d9038324` | `606215de629d5f5eda9e62826cf511733b1ec0b9ca8ed07662a5c8bfe181d0b9` | 153 | 153/153 (151/153 unchanged) | Revision 4 vendored the new encoding and nesting rules into the spec and this checker was never run against it, so there is no record for it and the table @@ -45,10 +46,11 @@ reads as 129 to a per-value counter and 128 to a per-container one; at 129 both reject, and at 128 with an empty-container leaf both accept. The boundary therefore lives in `src/json.rs`'s own tests. -All five are inspectable and reproducible by hand from those pins; the -revision-5 run at 149/149 is the one re-verified continuously by CI, which -follows the current suite pin. Revision 3 was continuously verified until -revision 5 replaced it and remains reproducible from its own pins. +All six are inspectable and reproducible by hand from those pins; the +revision-6 run at 153/153 is the one re-verified continuously by CI, which +follows the current suite pin. Each earlier record was continuously verified +until the next replaced it, and each remains reproducible from its own pins: +the fixed build still reproduces the revision-5 record exactly. ## Vendored spec vs branch head diff --git a/README.md b/README.md index 16f067c..e6a9bf9 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ An independent validity-gate checker for the **Adversarial Execution Evidence (A **suiteRevision 5: 149/149** (35/35, 114/114) after a parser fix. The unchanged revision-3 build scored **148/149** against it, and the single miss is worth stating plainly because the causation runs the other way this time: the revision pins a nesting bound the earlier text did not state, this checker had picked 256, and the new `bad-741` vector found it. Not blind, and not a case of the two meeting. The bound was only the visible half. The revision also states the counting rule, and this parser had been incrementing per parsed value rather than per open container, which read exactly one level deeper than the spec rule on **every document in the corpus** — all 149 statements and every record payload inside them, measured on the raw bytes so the deliberately ill-formed vectors are covered too — because every deepest path in the corpus ends in a scalar. Changing only the constant scores 149/149 as well, and still rejects a statement at depth 128 that the spec calls valid. What keeps the corpus from telling the two fixes apart is not its maximum depth, since `bad-741`'s payload sits at 130, but that nothing in it sits at 128, the one depth where the two readings disagree: a scalar leaf inside 128 open containers reads as 129 to a per-value counter and 128 to a per-container one, and at 129 both reject. That boundary is pinned in this parser's own tests instead. The revision's other half, the encoding rules, needed no change here: this checker rejected ill-formed UTF-8, CESU-8, overlong forms and unpaired surrogate escapes from the first build. +**suiteRevision 6: 153/153** (36/36, 117/117) after implementing the noncharacter exclusion. The unchanged revision-5 build scored **151/153**. Two of the four new vectors are the depth-boundary pair, `ok-036` and `bad-742`, and the container-branch counter already handled both; the other two, `bad-743` and `bad-744`, carry Unicode noncharacters in a vocabulary label and a payload value, which this checker admitted. It admitted them because the earlier text scoped its MUST to well-formed sequences of Unicode scalar values, and a noncharacter is one; the revision widens the rule to the RFC 7493 section 2.1 exclusion the strict-I-JSON label had always implied. **This one is directed, and more so than revision 2 was:** the rule was written and the vectors named before this checker ran, so what it demonstrates is that the corrected rule is implementable from the text, not that an independent reader found it. + [PARITY-REPORT.md](PARITY-REPORT.md) carries the scores, the interpretation decisions the spec text forced, the four formerly-open corners and how each was closed, and the from-spec discipline attestation listing exactly what was and was not read for each revision. [NOTES.md](NOTES.md) compares the vendored spec against the branch-head spec. No dependency on the reference implementation: this crate carries its own strict I-JSON parser, RFC 8785 canonicalization with ECMAScript number formatting, RFC 6962 domain-separated Merkle root over DSSE PAE bytes, run-binding derivation, and Ed25519 tier verification against the suite's seed-derived test key. @@ -18,13 +20,13 @@ No dependency on the reference implementation: this crate carries its own strict ``` git clone https://github.com/astrogilda/aee-conformance -git -C aee-conformance checkout ea25a1e218e94843e018dffc0eae4f3fcab1749e +git -C aee-conformance checkout 7098f4e6b7d04c8394969ed81b4025d4d9038324 cargo run --locked --release -- aee-conformance/vectors --json fresh.json -python3 scripts/compare-report.py fresh.json reports/suite-revision-5.json +python3 scripts/compare-report.py fresh.json reports/suite-revision-6.json ``` The checkout is pinned deliberately. `main` moves, and a later revision would run -a different corpus against the 149/149 claim on this page, which is the one thing +a different corpus against the 153/153 claim on this page, which is the one thing a reproduction recipe must not do quietly. Earlier revisions are reproducible the same way by taking their suite pin and checker commit from [`reports/INDEX.json`](reports/INDEX.json). diff --git a/reports/INDEX.json b/reports/INDEX.json index f9875d5..ce05cce 100644 --- a/reports/INDEX.json +++ b/reports/INDEX.json @@ -66,8 +66,22 @@ "vectors": 149, "acceptParity": "35/35", "rejectParity": "114/114", + "continuouslyVerified": false, + "note": "Revision 5 pins the two things the v0.6 text left open, encoding and nesting depth. The unchanged revision-3 checker scored 148/149 against it, missing only bad-741: this implementation had picked 256 where the text now says 128, and counted depth per parsed value where the text now says per open container. Both halves are fixed here. The constant alone would also have scored 149/149, which is why the boundary the corpus does not reach is pinned in the parser's own tests instead.", + "checkerCommit": "88c37d19c63854341778fd40fb31108d74975ce1" + }, + { + "file": "suite-revision-6.json", + "reportSha256": "sha256:0362e1768849e56f2e2df3b5ce188ffcead28cebfc41511ec03530ee7552fd87", + "checkerSourceDigest": "sha256:1c3e2e7843fc021e20c33d3bdc726fbb704ad0438654a0444fa7a06d6613aaba", + "suiteRevision": 6, + "suiteCommit": "7098f4e6b7d04c8394969ed81b4025d4d9038324", + "specDigest": "sha256:606215de629d5f5eda9e62826cf511733b1ec0b9ca8ed07662a5c8bfe181d0b9", + "vectors": 153, + "acceptParity": "36/36", + "rejectParity": "117/117", "continuouslyVerified": true, - "note": "Revision 5 pins the two things the v0.6 text left open, encoding and nesting depth. The unchanged revision-3 checker scored 148/149 against it, missing only bad-741: this implementation had picked 256 where the text now says 128, and counted depth per parsed value where the text now says per open container. Both halves are fixed here. The constant alone would also have scored 149/149, which is why the boundary the corpus does not reach is pinned in the parser's own tests instead." + "note": "Revision 6 adds the depth boundary pair and the noncharacter pair. The unchanged revision-5 checker scored 151/153 against it: ok-036 and bad-742 passed on the container-branch counter already in place, and bad-743 and bad-744 did not, because this checker did not implement the RFC 7493 section 2.1 noncharacter exclusion the revision makes normative. A directed fix, not a blind run: the rule was stated before this checker was run." } ] } diff --git a/reports/suite-revision-6.json b/reports/suite-revision-6.json new file mode 100644 index 0000000..ac0f93d --- /dev/null +++ b/reports/suite-revision-6.json @@ -0,0 +1,155 @@ +{"suite":"aee-conformance","acceptParity":"36/36","rejectParity":"117/117","vectors":[ +{"id":"ok-001-caught-intercepted-fail","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-002-clean-pass-armed-sealed","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-003-clean-pass-bounded-drops","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-004-degraded-out-of-scope","verdict":"valid","result":"degraded","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-005-degraded-routed-elsewhere","verdict":"valid","result":"degraded","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-006-clean-reconstructed","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-007-artifact-only-recordless","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["declared"],"tiersWithoutKey":["declared"],"parity":true}, +{"id":"ok-008-artifact-fail-closed-method","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["declared"],"tiersWithoutKey":["declared"],"parity":true}, +{"id":"ok-009-artifact-oov-label-fail","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["declared"],"tiersWithoutKey":["declared"],"parity":true}, +{"id":"ok-010-artifact-retired-basis-fail","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["declared"],"tiersWithoutKey":["declared"],"parity":true}, +{"id":"ok-011-shared-run-records","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["attested","attested"],"tiersWithoutKey":["unattested","unattested"],"parity":true}, +{"id":"ok-012-selectors-present","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-013-unknown-kind-extra-record","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-014-three-record-odd-split","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["attested","attested"],"tiersWithoutKey":["unattested","unattested"],"parity":true}, +{"id":"ok-015-four-record-tree","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["attested","attested","attested"],"tiersWithoutKey":["unattested","unattested","unattested"],"parity":true}, +{"id":"ok-016-caught-actuallayer-none","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-017-method-weakening-allowed","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-018-aee-prefix-ignored","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-019-wrong-keyid-sig-verifies","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-020-non-pae-signature","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["unattested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-021-producer-extra-members","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-022-two-arming-records","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-023-no-tofu-embedded-key","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-024-mixed-basis-rows","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["attested","unattested","declared"],"tiersWithoutKey":["unattested","unattested","declared"],"parity":true}, +{"id":"ok-025-does-not-assert-present","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-026-five-record-tree","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["attested","attested","attested","attested"],"tiersWithoutKey":["unattested","unattested","unattested","unattested"],"parity":true}, +{"id":"ok-027-artifact-missing-method","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["declared"],"tiersWithoutKey":["declared"],"parity":true}, +{"id":"ok-028-empty-caught-pass","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-029-artifact-with-records","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["declared"],"tiersWithoutKey":["declared"],"parity":true}, +{"id":"ok-030-method-min-multirecord","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-031-caught-reconstructed","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-032-method-inferred-retired","verdict":"valid","result":"fail","reason":null,"tiersWithPinnedKey":["declared"],"tiersWithoutKey":["declared"],"parity":true}, +{"id":"ok-033-artifact-degraded","verdict":"valid","result":"degraded","reason":null,"tiersWithPinnedKey":["declared"],"tiersWithoutKey":["declared"],"parity":true}, +{"id":"ok-034-arming-chain-genesis","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-035-unknown-kind-excluded-from-cap","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"ok-036-payload-nesting-at-bound","verdict":"valid","result":"pass","reason":null,"tiersWithPinnedKey":["attested"],"tiersWithoutKey":["unattested"],"parity":true}, +{"id":"bad-001-result-uppercase","verdict":"invalid","result":null,"reason":"carried result \"PASS\" does not match the recomputed result \"pass\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-002-result-mismatch-caught","verdict":"invalid","result":null,"reason":"carried result \"pass\" does not match the recomputed result \"fail\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-003-result-mismatch-oov-label","verdict":"invalid","result":null,"reason":"carried result \"pass\" does not match the recomputed result \"fail\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-004-result-mismatch-failclosed","verdict":"invalid","result":null,"reason":"carried result \"pass\" does not match the recomputed result \"fail\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-005-result-mismatch-coverage-gap","verdict":"invalid","result":null,"reason":"carried result \"pass\" does not match the recomputed result \"degraded\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-006-result-fail-on-pass","verdict":"invalid","result":null,"reason":"carried result \"fail\" does not match the recomputed result \"pass\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-007-result-degraded-on-pass","verdict":"invalid","result":null,"reason":"carried result \"degraded\" does not match the recomputed result \"pass\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-008-result-unknown-token","verdict":"invalid","result":null,"reason":"carried result \"error\" does not match the recomputed result \"pass\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-101-refs-empty","verdict":"invalid","result":null,"reason":"attackResults[0] is a substrate row with empty observationRefs","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-102-ref-out-of-range","verdict":"invalid","result":null,"reason":"attackResults[0].observationRefs index 7 is out of range for observationRecords","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-103-ref-negative","verdict":"invalid","result":null,"reason":"attackResults[0].observationRefs index -1 is out of range for observationRecords","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-104-caught-refs-arming-only","verdict":"invalid","result":null,"reason":"attackResults[0] is a caught intercepted row with no covering interception record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-105-reconstructed-refs-interception","verdict":"invalid","result":null,"reason":"attackResults[0] is a reconstructed row with no covering examination record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-106-clean-missing-sealed","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering sealed record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-107-clean-missing-arming","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering arming record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-108-ref-non-integer","verdict":"invalid","result":null,"reason":"attackResults[0].observationRefs[1] is not an integer index","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-201-payload-unsorted-keys","verdict":"invalid","result":null,"reason":"observationRecords[0] covers a substrate row but its payload is not a canonical I-JSON object: payload bytes are not in RFC 8785 canonical form","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-202-payload-bignum","verdict":"invalid","result":null,"reason":"observationRecords[0] covers a substrate row but its payload is not a canonical I-JSON object: integer 9007199254740993 is outside the I-JSON safe range","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-203-payload-duplicate-member","verdict":"invalid","result":null,"reason":"observationRecords[0] covers a substrate row but its payload is not a canonical I-JSON object: payload does not parse as JSON: duplicate object member \"aeeMethod\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-204-payload-media-type","verdict":"invalid","result":null,"reason":"observationRecords[0] covers a substrate row but its payloadType does not end in +json","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-208-payload-member-non-bmp","verdict":"invalid","result":null,"reason":"observationRecords[0] covers a substrate row but its payload is not a canonical I-JSON object: member name \"zz😀\" carries a code point above U+FFFF","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-205-payload-missing-runbinding","verdict":"invalid","result":null,"reason":"observationRecords[0] payload is missing required member \"aeeRunBinding\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-206-payload-missing-kind","verdict":"invalid","result":null,"reason":"observationRecords[0] payload is missing required member \"aeeKind\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-207-payload-missing-method","verdict":"invalid","result":null,"reason":"observationRecords[0] payload is missing required member \"aeeMethod\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-301-run-binding-splice","verdict":"invalid","result":null,"reason":"observationRecords[0] payload aeeRunBinding does not equal the run binding derived from this statement","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-302-method-inflation","verdict":"invalid","result":null,"reason":"attackResults[0] claims method intercepted but a covering record is signed aeeMethod reconstructed","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-303-binding-version-2","verdict":"invalid","result":null,"reason":"observationRecords[0] payload aeeRunBinding does not equal the run binding derived from this statement","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-726-arming-binding-version-carried","verdict":"invalid","result":null,"reason":"observationRecords[0] payload declares a run-binding version this verifier does not implement","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-304-method-cap-multirecord","verdict":"invalid","result":null,"reason":"attackResults[0] claims method intercepted but a covering record is signed aeeMethod reconstructed","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-401-records-no-batchroot","verdict":"invalid","result":null,"reason":"observationRecords is non-empty but batchRoot is missing","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-402-root-no-domain-separation","verdict":"invalid","result":null,"reason":"batchRoot does not recompute over the carried observation records","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-403-root-bitcoin-padding","verdict":"invalid","result":null,"reason":"batchRoot does not recompute over the carried observation records","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-404-root-leaf-order-swapped","verdict":"invalid","result":null,"reason":"batchRoot does not recompute over the carried observation records","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-405-duplicate-records","verdict":"invalid","result":null,"reason":"observationRecords[0] and observationRecords[2] are duplicates of the same record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-406-root-hex-tamper","verdict":"invalid","result":null,"reason":"batchRoot does not recompute over the carried observation records","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-407-substrate-row-no-records","verdict":"invalid","result":null,"reason":"attackResults[0].observationRefs index 0 is out of range for observationRecords","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-408-batchroot-without-records","verdict":"invalid","result":null,"reason":"batchRoot is carried but observationRecords is empty or absent","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-409-artifact-records-bad-root","verdict":"invalid","result":null,"reason":"batchRoot does not recompute over the carried observation records","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-501-substrate-unknown-method","verdict":"invalid","result":null,"reason":"attackResults[0] is a substrate row with a missing or out-of-vocabulary method","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-502-missing-actual-layer","verdict":"invalid","result":null,"reason":"attackResults[0] is missing the required actualLayer member","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-503-clean-row-layer-not-none","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean row but actualLayer is \"policy.egress_sinkhole\", not the literal \"none\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-818-artifact-clean-row-layer-not-none","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean row but actualLayer is \"policy.egress_sinkhole\", not the literal \"none\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-504-substrate-oov-label","verdict":"invalid","result":null,"reason":"attackResults[0] is a substrate row whose label \"example_label_a\" is outside the carried vocabulary","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-505-substrate-missing-method","verdict":"invalid","result":null,"reason":"attackResults[0] is a substrate row with a missing or out-of-vocabulary method","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-506-actuallayer-json-number","verdict":"invalid","result":null,"reason":"attackResults[0].actualLayer is not a JSON string","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-601-vocabulary-absent","verdict":"invalid","result":null,"reason":"observationEnvironment is missing required member \"observationVocabulary\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-602-caught-not-subset","verdict":"invalid","result":null,"reason":"observationVocabulary.caught entry \"example_label_x\" is not in labels","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-603-labels-unsorted","verdict":"invalid","result":null,"reason":"observationVocabulary.labels is not strictly ascending by UTF-16 code unit at index 1","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-604-caught-duplicate","verdict":"invalid","result":null,"reason":"observationVocabulary.caught is not strictly ascending by UTF-16 code unit at index 1","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-605-vocabulary-digest-mismatch","verdict":"invalid","result":null,"reason":"observationVocabulary.digest does not re-derive from the carried labels and caught arrays","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-606-missing-runentropy","verdict":"invalid","result":null,"reason":"statement carries substrate rows but observationEnvironment.runEntropy is missing","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-607-two-subjects-substrate","verdict":"invalid","result":null,"reason":"statement carries 2 subjects; exactly one is required on a statement of any basis","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-608-digest-uppercase","verdict":"invalid","result":null,"reason":"runEntropy digest is not lowercase 64-hex, so the run binding cannot derive","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-609-digest-truncated","verdict":"invalid","result":null,"reason":"substrate digest is not lowercase 64-hex, so the run binding cannot derive","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-610-empty-labels-substrate","verdict":"invalid","result":null,"reason":"attackResults[0] is a substrate row whose label \"egress_captured\" is outside the carried vocabulary","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-611-subject-no-sha256","verdict":"invalid","result":null,"reason":"subject[0].digest carries no sha256 entry","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-612-labels-non-bmp","verdict":"invalid","result":null,"reason":"observationVocabulary.labels entry \"😀\" carries a code point above U+FFFF","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-701-arming-missing-armedat","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering arming record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-702-armedat-after-issuedat","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering arming record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-703-arming-posture-mismatch","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering arming record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-704-arming-method-reconstructed","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering arming record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-705-sealed-missing-dropcount","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering sealed record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-706-stillarmed-non-boolean","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering sealed record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-707-sealed-stillarmed-false","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering sealed record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-708-sealed-drops-no-bound","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering sealed record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-709-sealed-drops-exceed-bound","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering sealed record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-710-sealed-posture-mismatch","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering sealed record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-712-examination-method-intercepted","verdict":"invalid","result":null,"reason":"attackResults[0] is a reconstructed row with no covering examination record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-713-only-sealed-ref-noncovering","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering sealed record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-714-unknown-kind-sole-cover","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering arming record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-715-sealed-missing-stillarmed","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering sealed record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-716-sealed-missing-posture","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering sealed record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-717-arming-missing-posture","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering arming record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-727-armedat-non-utc-offset","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering arming record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-728-artifact-two-subjects","verdict":"invalid","result":null,"reason":"statement carries 2 subjects; exactly one is required on a statement of any basis","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-729-duplicate-attackid-rows","verdict":"invalid","result":null,"reason":"attackResults rows 0 and 1 carry the same attackId \"XA-EXAMPLE-1\"; one row per executed attack","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-730-coverage-class-overlap","verdict":"invalid","result":null,"reason":"manifest class \"XA\" appears in more than one of assessedClasses, outOfScope, or routedElsewhere; the three are a disjoint partition","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-718-chain-runseq-zero","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering arming record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-719-chain-missing-scope","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering arming record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-720-chain-prev-not-hex","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering arming record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-721-chain-scope-not-array","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering arming record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-722-chain-scope-unknown-dimension","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering arming record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-723-chain-scope-not-canonical","verdict":"invalid","result":null,"reason":"attackResults[0] is a clean intercepted row with no covering arming record","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-724-artifact-ref-out-of-range","verdict":"invalid","result":null,"reason":"attackResults[0].observationRefs index 99 is out of range for observationRecords","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-725-statement-duplicate-member","verdict":"invalid","result":null,"reason":"statement does not parse as strict JSON: duplicate object member \"predicateType\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-801-wrong-predicatetype","verdict":"invalid","result":null,"reason":"predicateType is not https://in-toto.io/attestation/adversarial-execution-evidence/v0.6","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-802-missing-catchpolicy","verdict":"invalid","result":null,"reason":"observationEnvironment is missing required member \"catchPolicy\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-803-corpus-digest-mismatch","verdict":"invalid","result":null,"reason":"corpus.digest does not re-derive from the embedded manifest","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-804-attackid-two-classes","verdict":"invalid","result":null,"reason":"attackId \"XA-EXAMPLE-1\" appears under more than one manifest class","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-805-row-unknown-attackid","verdict":"invalid","result":null,"reason":"attackResults[0].attackId \"XA-EXAMPLE-9\" does not appear in the corpus manifest","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-806-coverage-attack-omitted","verdict":"invalid","result":null,"reason":"manifest attack \"XA-EXAMPLE-2\" in an assessed class has no attackResults row","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-807-coverage-attack-superset","verdict":"invalid","result":null,"reason":"attackResults row \"XB-EXAMPLE-1\" is outside the assessed classes' manifest attacks","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-816-coverage-class-dropped","verdict":"invalid","result":null,"reason":"manifest class \"XB\" appears in none of assessedClasses, outOfScope, or routedElsewhere","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-819-assessed-class-not-in-manifest","verdict":"invalid","result":null,"reason":"assessed class \"XZ\" does not exist in the corpus manifest","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-731-outofscope-unknown-class","verdict":"invalid","result":null,"reason":"outOfScope class \"XZ\" does not exist in the corpus manifest","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-732-routedelsewhere-unknown-class","verdict":"invalid","result":null,"reason":"routedElsewhere class \"XZ\" does not exist in the corpus manifest","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-733-statement-lone-high-surrogate-escape","verdict":"invalid","result":null,"reason":"statement does not parse as strict JSON: lone high surrogate","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-734-statement-lone-low-surrogate-escape","verdict":"invalid","result":null,"reason":"statement does not parse as strict JSON: lone low surrogate","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-735-statement-reversed-surrogate-pair","verdict":"invalid","result":null,"reason":"statement does not parse as strict JSON: lone low surrogate","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-736-statement-cesu8-vocabulary-label","verdict":"invalid","result":null,"reason":"statement does not parse as strict JSON: input is not valid UTF-8","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-737-statement-overlong-utf8","verdict":"invalid","result":null,"reason":"statement does not parse as strict JSON: input is not valid UTF-8","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-738-statement-raw-control-character","verdict":"invalid","result":null,"reason":"statement does not parse as strict JSON: raw control character in string","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-739-payload-lone-surrogate-escape","verdict":"invalid","result":null,"reason":"observationRecords[0] covers a substrate row but its payload is not a canonical I-JSON object: payload does not parse as JSON: lone high surrogate","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-740-payload-cesu8","verdict":"invalid","result":null,"reason":"observationRecords[0] covers a substrate row but its payload is not a canonical I-JSON object: payload does not parse as JSON: input is not valid UTF-8","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-741-payload-nesting-exceeds-max-depth","verdict":"invalid","result":null,"reason":"observationRecords[0] covers a substrate row but its payload is not a canonical I-JSON object: payload does not parse as JSON: nesting too deep","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-742-payload-nesting-empty-container-leaf","verdict":"invalid","result":null,"reason":"observationRecords[0] covers a substrate row but its payload is not a canonical I-JSON object: payload does not parse as JSON: nesting too deep","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-743-statement-noncharacter-vocabulary-label","verdict":"invalid","result":null,"reason":"statement does not parse as strict JSON: Unicode noncharacter U+FFFF in string","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-744-payload-noncharacter","verdict":"invalid","result":null,"reason":"observationRecords[0] covers a substrate row but its payload is not a canonical I-JSON object: payload does not parse as JSON: Unicode noncharacter U+FFFF in string","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-817-payload-noncanonical-base64","verdict":"invalid","result":null,"reason":"observationRecords[0].payload is not valid base64","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-808-coverage-absent","verdict":"invalid","result":null,"reason":"predicate is missing required member \"coverage\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-809-snake-case-doesnotassert","verdict":"invalid","result":null,"reason":"predicate carries the retired snake_case does_not_assert spelling","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-810-missing-issuedat","verdict":"invalid","result":null,"reason":"predicate is missing required member \"issuedAt\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-811-issuedat-not-rfc3339","verdict":"invalid","result":null,"reason":"issuedAt is not an RFC 3339 timestamp","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-812-missing-networkposture","verdict":"invalid","result":null,"reason":"observationEnvironment is missing required member \"networkPosture\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-813-missing-corpus","verdict":"invalid","result":null,"reason":"observationEnvironment is missing required member \"corpus\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-814-missing-substrate","verdict":"invalid","result":null,"reason":"observationEnvironment is missing required member \"substrate\"","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true}, +{"id":"bad-815-wrong-statement-type","verdict":"invalid","result":null,"reason":"statement _type is not https://in-toto.io/Statement/v1","tiersWithPinnedKey":null,"tiersWithoutKey":null,"parity":true} +]}