Skip to content

Stop claiming no tampering was detected when nothing was compared - #222

Merged
droplister merged 1 commit into
mainfrom
fix/verification-status-honesty
Aug 3, 2026
Merged

Stop claiming no tampering was detected when nothing was compared#222
droplister merged 1 commit into
mainfrom
fix/verification-status-honesty

Conversation

@droplister

Copy link
Copy Markdown
Member

PRIORITIES.md item 3a. Small fix, removes a false assurance.

The problem

verifyProviderTransaction returns passed: true in two very different situations:

  • the local decode was compared against the API's decode and they agreed, or
  • there was no API decode to compare against at all:
// If no API message to compare against, local unpack success is enough
if (!apiMessage) {
  return { passed: true, mismatches: [], localUnpack };
}

(providerVerify.ts)

The second case happens whenever decodeCounterpartyMessage returns null — a network error, a non-200, or an error field in the response — and the caller swallows that exception (useSignTransactionRequest.ts). The approval screen rendered the same green shield for both:

🛡 Verified locally — no tampering detected

So the wallet's one affirmative security claim was made most confidently in the case where it had checked least, including when an attacker submits a payload our unpacker accepts but core rejects.

The change

The result now carries comparedAgainstApi, and the two cases render differently:

  • cross-checked and agreed → unchanged green shield, "Verified locally — no tampering detected"
  • decoded with nothing to compare against → neutral badge, "Decoded locally — no second source to check it against"

Signing behaviour is unchanged. Neither case was ever blocked, and this does not start blocking one — only the claim made to the user changes. Both approval screens default the flag to false when absent, so a path that forgets to report it understates rather than overstates.

Tests

  • New verification-status.test.tsx covers all four states, including that the "no tampering" text is absent when nothing was compared.
  • providerVerify.test.ts extended: comparedAgainstApi is false with no API message, false for non-Counterparty data, true only when a comparison ran.
  • 1795 unit tests pass across components/pages/counterparty; tsc --noEmit clean.
  • E2E: provider-transaction-signing.spec.ts 11/11 locally.

Not addressed here

The deeper issue behind this one is item 3: the raw-transaction approval screen renders from the API's decode rather than a local parse, so the "local" unpack is not independent of the API either. That is a larger change and is next.

https://claude.ai/code/session_01CcjnCrgosSeshymXLBxdGj

verifyProviderTransaction returns passed: true in two very different
situations: the local decode was compared against the API's and they
agreed, or there was no API decode to compare against at all. The
second happens whenever the endpoint errors, returns a non-200, or
rejects a payload our unpacker accepts -- and the approval screen
rendered the same green shield reading "Verified locally -- no
tampering detected" either way. The wallet's one affirmative security
claim was loudest exactly when it had checked least.

The result now carries comparedAgainstApi, and the two cases render
differently: a cross-checked pass keeps the shield, while a decode with
nothing to compare against gets a neutral badge saying so. Signing
behaviour is unchanged -- neither case was ever blocked, and this does
not start blocking one; only the claim made to the user changes.

Both approval screens default the flag to false when absent, so a path
that forgets to report it understates rather than overstates.

Claude-Session: https://claude.ai/code/session_01CcjnCrgosSeshymXLBxdGj
@droplister
droplister merged commit 43932af into main Aug 3, 2026
71 of 73 checks passed
@droplister
droplister deleted the fix/verification-status-honesty branch August 3, 2026 22:41
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.

1 participant