fix(clearsign): vendored firmware allowlist + LoadClearsignSigner train, replacing dead Pioneer /descriptors/sign#337
Merged
Conversation
…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
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
/descriptors/decode+/descriptors/signare 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 vendoredfirmwareClearSignsallowlist incalldata-decoder.tsmirroring the device's ownethereum_contractHandledpins (THOR/Maya router deposit, 0x proxy, standard ERC-20 transfer/approve, addLiquidityETH).needsBlindSigningis 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).POST /eth/clearsign/load-signerREST route → hdwalletloadClearsignSigner(feat(eth): add LoadClearsignSigner (msg 117) to KeepKey hdwallet hdwallet#52, merged) → device msg 117. A caller-suppliedtxMetadatablob 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.FirmwareDropZone/engine-controller): blocks flash until the device reportsbootloaderMode=true— flashing against a wallet-mode device previously stalled the HID read and looked like a freeze.SigningApproval:needsBlindSigningis now authoritative for the trust badge.Merge conflict resolution note
This branch was 20 commits behind
develop;develophad independently landed #326 (EVM_INSIGHTflag 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-sdkoffline parity gate — 51/51 catalog flows byte-match python-keepkey's reference blobskeepkey-sdk/tests/evm-clearsign/clearsign-signer-flows.js(self mode) — blocked on a Vault build with this branch's/eth/clearsign/load-signerroute (the currently-running dev build predates it)