Skip to content

fix(clearsign): vendored firmware allowlist + LoadClearsignSigner train, replacing dead Pioneer /descriptors/sign#337

Merged
BitHighlander merged 3 commits into
developfrom
fix/clearsign-blob-base64-fulltx
Jul 8, 2026
Merged

fix(clearsign): vendored firmware allowlist + LoadClearsignSigner train, replacing dead Pioneer /descriptors/sign#337
BitHighlander merged 3 commits into
developfrom
fix/clearsign-blob-base64-fulltx

Conversation

@BitHighlander

Copy link
Copy Markdown
Collaborator

Summary

  • Pioneer's /descriptors/decode + /descriptors/sign are 404 in prod (confirmed live). Replaces the flag-gated Pioneer signed-blob fetch (EVM_INSIGHT, from feat(clearsign): EVM insight behind EVM_INSIGHT flag (default off, fw 7.15+) #326) with a vendored firmwareClearSigns allowlist in calldata-decoder.ts mirroring the device's own ethereum_contractHandled pins (THOR/Maya router deposit, 0x proxy, standard ERC-20 transfer/approve, addLiquidityETH). needsBlindSigning is now keyed off what the FIRMWARE clear-signs, not what the local decoder recognizes — a decoder-known contract the firmware still blind-signs reads "unknown" trust (closes the same drain vector release(v1.4.5): DeFi positions + wallet selector #261/fix(clear-sign): stop over-gating firmware-handled contracts into blind-signing #303 fixed).
  • Adds the full runtime clear-sign signer train: POST /eth/clearsign/load-signer REST route → hdwallet loadClearsignSigner (feat(eth): add LoadClearsignSigner (msg 117) to KeepKey hdwallet hdwallet#52, merged) → device msg 117. A caller-supplied txMetadata blob is honored at sign time — safe because the device cryptographically verifies it against a signer the user explicitly loaded and confirmed on-device, not because of a client-side flag.
  • Bootloader-gates firmware flash (FirmwareDropZone/engine-controller): blocks flash until the device reports bootloaderMode=true — flashing against a wallet-mode device previously stalled the HID read and looked like a freeze.
  • SigningApproval: needsBlindSigning is now authoritative for the trust badge.

Merge conflict resolution note

This branch was 20 commits behind develop; develop had independently landed #326 (EVM_INSIGHT flag gating the same dead Pioneer path, default off). Resolved in favor of this branch's full replacement — the vendored allowlist + device-side verification supersedes flag-gating a dead endpoint. EVM_INSIGHT/evmInsightEnabled() call sites removed as dead code; shared/flags.ts (the flag's home) is left in place, orphaned, low priority to clean up separately.

Test plan

  • __tests__/firmware-clearsign-gate.test.ts — 7/7, unit-tests the allowlist against pinned selectors (spoof guard, wrong-address rejection, etc.)
  • keepkey-sdk offline parity gate — 51/51 catalog flows byte-match python-keepkey's reference blobs
  • On-device: keepkey-sdk/tests/evm-clearsign/clearsign-signer-flows.js (self mode) — blocked on a Vault build with this branch's /eth/clearsign/load-signer route (the currently-running dev build predates it)
  • Real EVM swap (THOR/Maya router deposit) on hardware — CLEARSIGN WARNING + decoded args, no raw hex

BitHighlander and others added 3 commits July 2, 2026 21:36
…se64 blob, gate on VERIFIED

The committed pioneer clear-sign path fetched the signed blob with only
{chainId, contractAddress, data} and attached it as a hex string. Two bugs
surfaced on-device (rc3, R715rc3):

1. hdwallet's ethSignTx arrayify()s a STRING signedPayload as hex, but
   pioneer emits base64 → "invalid hexadecimal string" thrown before the
   device renders anything (looked like "nothing happens after approve").
   Fix: decode base64 → Uint8Array so hdwallet takes the bytes branch.

2. The blob's tx_hash binds the full sighash (nonce/gas/value/fees), so a
   3-field request can never produce a blob rc3 accepts. Fix: thread the
   real unsigned-tx fields (mirroring the ethSignTx msg construction exactly)
   into the /descriptors/sign request.

Also gate attach on classification === 'VERIFIED' — an OPAQUE/UNKNOWN blob
doesn't enable clear-sign (rc3 fail-closes) and attaching it would mask the
honest raw-hex/AdvancedMode path. Adds insightClassification to the type.

Device-verified: base64 fix lets the metadata reach the device and return an
ack; remaining MALFORMED verdict is a pioneer-insight serializer / firmware
format issue, tracked separately (not a vault bug).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sign allowlist, add LoadClearsignSigner endpoint

- FirmwareDropZone/engine-controller: block flash until device reports
  bootloaderMode=true — firmwareErase against a wallet-mode device stalls
  the HID read and looks like a freeze.
- calldata-decoder: Pioneer's /descriptors/decode + /descriptors/sign are
  gone (404). Replace with a vendored firmwareClearSigns allowlist mirroring
  the device's own ethereum_contractHandled pins, so needsBlindSigning is
  keyed off what the FIRMWARE clear-signs, not what our local decoder
  recognizes.
- rest-api/schemas: add POST /eth/clearsign/load-signer (LoadClearsignSigner)
  and honor a caller-supplied runtime-signer blob at sign time.
- SigningApproval: needsBlindSigning is authoritative for trust badge —
  a decoder-recognized contract the firmware still blind-signs must read
  'unknown', not 'known'.
- Bump hdwallet pointer for the paired ethLoadClearsignSigner transport call.
…-base64-fulltx

# Conflicts:
#	modules/hdwallet
#	projects/keepkey-vault/src/bun/calldata-decoder.ts
#	projects/keepkey-vault/src/bun/rest-api.ts
@BitHighlander BitHighlander requested a review from pastaghost as a code owner July 8, 2026 21:55
@BitHighlander BitHighlander merged commit d614559 into develop Jul 8, 2026
1 check passed
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