Conversation
The `if let Ok(cert_count) = varint::get32(...)` pattern silently swallowed ALL error variants (including `WSError::ParseError` from malformed cert_count bytes), not just the EOF that signals backward compatibility with the pre-cert-chain format. An attacker who corrupted the cert_count bytes — e.g., five bytes each with MSB set; `get32` consumes all five and returns ParseError — could strip the certificate chain from a cert-based signature, downgrading it to a bare-key signature without the parser flagging the malformed input. Replace with an explicit `fill_buf` peek that distinguishes clean EOF (old format, no cert_count field at all) from malformed bytes (must error). All non-EOF error variants now propagate via `?`. Promotes the regression test to a regular `#[test]` (removes the `#[ignore]` attribute used during Mythos discovery) and renames it to `test_malformed_cert_count_is_rejected`. Deletes the `#[cfg(kani)] mod proofs` block: CBMC OOMs symbolically exercising `std::io::BufReader` + `Vec`, so Kani cannot serve as an oracle at this layer. Per AGENTS.md Kani-scope policy, the nearest primitive-layer proofs (`proof_get32_no_panic`, `proof_get32_no_overflow` in `src/lib/src/wasm_module/varint.rs`) cover `get32`'s error behavior on malformed symbolic bytes. Related class: wasmtime CVE-2026-27572 (panic on excessive `wasi:http/types.fields`) — same family of "parser reacts wrongly to malformed size field." Discovered by a Mythos delta pass on tier-5 file `sig_sections.rs`. Fixes: AS-37 Verifies: test_malformed_cert_count_is_rejected Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SignatureForHashes::deserializesilently swallowed parse errors on the cert_count field, downgrading cert-based signatures to bare-key signatures without flagging malformed inputif let Ok(cert_count) = varint::get32(...)pattern with an explicitfill_bufpeek that distinguishes clean EOF (backward-compat with the pre-cert-chain format) from malformed bytes (must error)#[test]and renames totest_malformed_cert_count_is_rejectedAS-37toartifacts/stpa/attack-scenarios.yaml,status: approved, linked to UCA-6 / DF-5 / TA-3 / H-9Finding details (AS-37)
Pre-fix code (sig_sections.rs, around line 87):
Exploit: Input
[0x80, 0x80, 0x80, 0x80, 0x80]after a valid signature prefix.get32consumes all 5 bytes and returnsWSError::ParseError. Theif let Ok(...)pattern treats this as "no certificate chain," returningOk(SignatureForHashes { certificate_chain: None, ... }). Any downstream validator that requirescertificate_chain.is_some()for cert-based trust is bypassed.Oracle status:
test_malformed_cert_count_is_rejected) — deterministic, passing after the fix, failing beforestd::io::BufReader+Vecwith this harness shape. Per the Kani-scope policy documented inAGENTS.md(merged in chore: add Mythos bug-hunt pipeline + AGENTS.md restructure #86), the nearest primitive-layer Kani proofs (proof_get32_no_panic,proof_get32_no_overflowinsrc/lib/src/wasm_module/varint.rs) coverget32's behavior on malformed symbolic bytes. The missing step Kani cannot reach is the high-level composition insidedeserialize.Related precedent
Same family as wasmtime CVE-2026-27572 (panic on excessive
wasi:http/types.fields) — parser reacting wrongly to malformed size field. In wasmtime's case the response was a panic; in ours it was a silent downgrade. Both require the same class of fix: validate size-field input before branching on the value.Methodology note — status: approved at emission
Normally
scripts/mythos/emit.mdmandatesstatus: drafton first emission, with human promotion toapproved. This PR emits asapprovedbecause the fix lands in the same commit — there is no window where aconfirmedfinding exists without a shipped fix. If reviewers disagree with the self-promotion, change todraftbefore merging.Test plan
cargo testpasses on both macOS and Linux (sig_sections tests confirmed green locally — 16 pass incl. the new one)wasm-signing.ymlend-to-end workflow passesfuzz.ymlpassesmemory.ymlpassesrivet validatedoes not report new errors on AS-37 (confirmed locally)status: approvedself-promotion or requests change todraft🤖 Generated with Claude Code