Cyphrme / Cyphrme/Cyphr

A malformed witness report reads as "no equivocation" to every consumer

Open
#148 0 comments 0 reactions 0 assignees View on GitHub
security
Dominant language
Rust
Stars
3
Forks
0
Avg merge
1d 42m
Merged PRs (30d)
11

Description

Equivocation checking now returns a distinct verdict when a report fails to parse — deliberately, so that a malformed report can be told apart from an honest absence of conflict. **No consumer distinguishes it.** Every call site reduces the verdict to a proven-or-not test, so malformed lands in the same bucket as "these reports agree."

The distinction exists in the type and is discarded at all three consuming sites.

## Why it matters

A signer's goal in evading equivocation detection is simply that **no claim is raised**. Before the typed parse, that was achieved by presenting one logical value in two representations so the comparison saw two different states. The parse closes that — but if a malformed report also produces no claim, and nothing anywhere distinguishes the two outcomes, the evasion is relocated rather than closed. Making one report unparseable achieves what making it differently-encoded used to.

This is understood and is being closed from the other end: the witness sync path will refuse to ingest a report that fails to parse, so a malformed report never becomes a retained attestation in the first place. Until that lands, the distinct verdict is produced and thrown away.

## An interim regression worth stating plainly

A test previously asserted that a conflict between reports carrying atypical field types **must not** be dropped, and it passed — the system detected that equivocation. It now asserts that no claim is raised, because both reports are rejected as malformed before comparison.

On that input, the system detected an equivocation before this change and does not detect it now. The rejection is correct in itself; the consequence is that the detection is gone until the ingestion refusal lands.

Exposure is limited to development: the branch carrying this work reaches the release line only as a whole, with the ingestion refusal included.

## What resolving this involves

Either the consuming layer distinguishes the malformed verdict — surfacing it rather than folding it into no-conflict — or the ingestion refusal makes it unreachable and the verdict becomes a defensive assertion rather than a live path. The second is the planned route. This issue exists so the interim gap is visible rather than living in a comment, and so the deleted assertion is restored in whichever form ends up correct.

Related: #141, #146.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by tracing the three consuming sites that reduce the equivocation verdict to a proven-or-not result, then inspect the deleted regression assertion for atypical field types. Compare the two possible resolutions described in the issue: surface the malformed verdict, or make it unreachable through witness sync ingestion refusal; done means the malformed case is no longer silently treated as no conflict and the assertion is restored appropriately.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.