Skip to content

fix: fall back to blind signing when clear signing not supported by Ledger device#41017

Merged
gantunesr merged 4 commits intomainfrom
dr/fix-blind-sign
Mar 19, 2026
Merged

fix: fall back to blind signing when clear signing not supported by Ledger device#41017
gantunesr merged 4 commits intomainfrom
dr/fix-blind-sign

Conversation

@danroc
Copy link
Contributor

@danroc danroc commented Mar 18, 2026

Description

signTypedData previously used only signEIP712Message (clear signing), which is not supported on Ledger Nano S. This change adds a fallback: if the device returns INS_NOT_SUPPORTED, it computes the EIP-712 domain separator and message struct hashes and calls signEIP712HashedMessage (blind signing) instead. This mirrors Ledger Live's approach and restores EIP-712 signing compatibility with Ledger Nano S.

Open in GitHub Codespaces

Changelog

CHANGELOG entry: Fixed EIP-712 typed data signing for Ledger Nano S devices

Related issues

Fixes: #39983

Manual testing steps

  1. Connect a Ledger Nano S and attempt to sign EIP-712 typed data (e.g. a permit signature)
  2. Confirm signing completes successfully using the blind signing fallback
  3. Connect a Ledger Nano X or Stax and confirm clear signing still works as before

Screenshots/Recordings

Before

Screen.Recording.2026-03-18.at.17.44.13.mov

After

Screen.Recording.2026-03-18.at.17.42.07.mov

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Note

Medium Risk
Changes EIP-712 signing behavior for Ledger devices by adding a clear-signing fallback path that computes hashes locally and uses signEIP712HashedMessage; incorrect hash computation or error classification could cause signature failures on some devices.

Overview
Restores EIP-712 typed-data signing on Ledger devices that don’t support clear signing by catching INS_NOT_SUPPORTED from signEIP712Message and falling back to signEIP712HashedMessage using locally computed domain/message struct hashes.

Adds helpers in app/offscreen/ledger.ts to detect the specific Ledger error and compute EIP-712 hashes via @metamask/eth-sig-util, and expands ledger.test.ts to cover clear-sign success, the INS_NOT_SUPPORTED fallback, and non-fallback error propagation.

Written by Cursor Bugbot for commit 10515dd. This will update automatically on new commits. Configure here.

Add INS_NOT_SUPPORTED fallback in signTypedData: try clear signing
(signEIP712Message) first; if the device doesn't support it, compute
EIP-712 domain and message hashes and use signEIP712HashedMessage
instead. Mirrors Ledger Live's approach and restores compatibility
with Ledger Nano S.
@github-actions
Copy link
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Mar 18, 2026

Builds ready [6d556cc]
⚡ Performance Benchmarks
👆 Interaction Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account2812752866286286
total2812752866286286
Confirm Txconfirm_tx601360096017360156017
total601360096017360156017
Bridge User Actionsbridge_load_page25922330729275307
bridge_load_asset_picker24021426618255266
bridge_search_token76673880022767800
total1255122712932412521293
🔌 Startup Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Standard HomeuiStartup15091241194511715941700
load12621043161011213541459
domContentLoaded12551038160211013391441
domInteractive2816121212487
firstPaint1707243287233309
backgroundConnect22020125610225240
firstReactRender18133542025
initialActions1010123
loadScripts1050836138310911361230
setupStore1383951522
numNetworkReqs393183163480
Power User HomeuiStartup5609212815077243065399085
load13441146188014513681663
domContentLoaded13231130187312913431596
domInteractive46225346334136
firstPaint2148864295292343
backgroundConnect215229212058207129025469
firstReactRender3317294422935
initialActions107114
loadScripts1086923161711611041293
setupStore18681121840
numNetworkReqs1396827843144245
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2212192221222222
srpButtonToSrpForm95949619696
confirmSrpToPwForm22222302323
pwFormToMetricsScreen15151601516
metricsToWalletReadyScreen16161601616
doneButtonToHomeScreen63359468840675688
openAccountMenuToAccountListLoaded293929372941229412941
total3944387640195840084019
Onboarding New WalletcreateWalletToSocialScreen2292262322231232
srpButtonToPwForm1341321372137137
createPwToRecoveryScreen11101211112
skipBackupToMetricsScreen45434724747
agreeButtonToOnboardingSuccess24203142531
doneButtonToAssetList55053156613553566
total99797410131410051013
Asset DetailsassetClickToPriceChart655185137685
total655185137685
Solana Asset DetailsassetClickToPriceChart1589919643195196
total1589919643195196
Import Srp HomeloginToHomeScreen2312222823955623362395
openAccountMenuAfterLogin59586116161
homeAfterImportWithNewWallet2252220123023822692302
total4604455546845246184684
Send TransactionsopenSendPageFromHome29253433034
selectTokenToSendFormLoaded38284674546
reviewTransactionToConfirmationPage1273868159131215831591
total1348923169832916701698
SwapopenSwapPageFromHome12711213710134137
fetchAndDisplaySwapQuotes2697268627101027072710
total282228202825228252825
🌐 Dapp Page Load Benchmarks

Current Commit: 6d556cc | Date: 3/18/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.05s (±43ms) 🟡 | historical mean value: 1.04s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 740ms (±63ms) 🟢 | historical mean value: 729ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 92ms (±129ms) 🟢 | historical mean value: 83ms ⬆️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.05s 43ms 1.02s 1.37s 1.07s 1.37s
domContentLoaded 740ms 63ms 711ms 1.31s 752ms 1.31s
firstPaint 92ms 129ms 64ms 1.38s 88ms 1.38s
firstContentfulPaint 92ms 129ms 64ms 1.38s 88ms 1.38s
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs
  • background: 58 Bytes (0%)
  • ui: 5 Bytes (0%)
  • common: 20 Bytes (0%)

@danroc danroc marked this pull request as ready for review March 18, 2026 16:48
Test the INS_NOT_SUPPORTED fallback path in signTypedData that falls
back to signEIP712HashedMessage when clear signing is unsupported.
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Mar 19, 2026

Builds ready [6f4cd8c]
⚡ Performance Benchmarks
👆 Interaction Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account27826129213291292
total27826129213291292
Confirm Txconfirm_tx602560186031560266031
total602560186031560266031
Bridge User Actionsbridge_load_page2622522759266275
bridge_load_asset_picker17115418913174189
bridge_search_token71069673015726730
total1129109611562411461156
🔌 Startup Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Standard HomeuiStartup14611271180910314841676
load1208103216049612321387
domContentLoaded1200102315799312281377
domInteractive3018114222687
firstPaint1586643182213311
backgroundConnect21719842425216247
firstReactRender19133842125
initialActions104123
loadScripts99983113629210251170
setupStore1463751622
numNetworkReqs393186154076
Power User HomeuiStartup5670234514994215367908597
load13111115183914213431669
domContentLoaded12921110179913013151581
domInteractive44202714835168
firstPaint247891603197304409
backgroundConnect236833010518183133905274
firstReactRender26175062839
initialActions105113
loadScripts1067903148111810901352
setupStore1765791935
numNetworkReqs1435632138153213
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2192162243221224
srpButtonToSrpForm93929419394
confirmSrpToPwForm22222302223
pwFormToMetricsScreen15151601616
metricsToWalletReadyScreen16151601616
doneButtonToHomeScreen62458365733652657
openAccountMenuToAccountListLoaded30382900315510031013155
total40293849418013441164180
Onboarding New WalletcreateWalletToSocialScreen2202192200220220
srpButtonToPwForm1081071080108108
createPwToRecoveryScreen888088
skipBackupToMetricsScreen40374424244
agreeButtonToOnboardingSuccess16161601616
doneButtonToAssetList49747951714504517
total8828728959885895
Asset DetailsassetClickToPriceChart664687167687
total664687167687
Solana Asset DetailsassetClickToPriceChart81808218282
total81808218282
Import Srp HomeloginToHomeScreen2378233724263223772426
openAccountMenuAfterLogin633487217887
homeAfterImportWithNewWallet1591507233286422982332
total40652957475583047464755
Send TransactionsopenSendPageFromHome27262702727
selectTokenToSendFormLoaded34333513535
reviewTransactionToConfirmationPage91389392815928928
total9438141036819791036
SwapopenSwapPageFromHome13211715114140151
fetchAndDisplaySwapQuotes2706269027251227122725
total2828280728481528412848
🌐 Dapp Page Load Benchmarks

Current Commit: 6f4cd8c | Date: 3/19/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.04s (±39ms) 🟡 | historical mean value: 1.04s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 734ms (±37ms) 🟢 | historical mean value: 729ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 81ms (±13ms) 🟢 | historical mean value: 86ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.04s 39ms 1.02s 1.34s 1.06s 1.34s
domContentLoaded 734ms 37ms 711ms 1.02s 749ms 1.02s
firstPaint 81ms 13ms 64ms 196ms 84ms 196ms
firstContentfulPaint 81ms 13ms 64ms 196ms 84ms 196ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs
  • background: 58 Bytes (0%)
  • ui: 5 Bytes (0%)
  • common: 20 Bytes (0%)

Copy link
Contributor

@montelaidev montelaidev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM code wise. I can't test because i don't have a nano

Copy link
Contributor

@ccharly ccharly left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (not tested)

@sonarqubecloud
Copy link

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Mar 19, 2026

Builds ready [10515dd]
⚡ Performance Benchmarks
👆 Interaction Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account2702602819278281
total2702602819278281
Confirm Txconfirm_tx6016600560331160256033
total6016600560331160256033
Bridge User Actionsbridge_load_page27020832145306321
bridge_load_asset_picker21717725930224259
bridge_search_token74873576611746766
total1260124312871712601287
🔌 Startup Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Standard HomeuiStartup14241195168910414701614
load118297414209212261331
domContentLoaded117796914119212221326
domInteractive2916118222488
firstPaint1466939677201291
backgroundConnect21219525411219233
firstReactRender20134762132
initialActions108215
loadScripts97877512008910191126
setupStore1465071726
numNetworkReqs393185163777
Power User HomeuiStartup57362089180363165664910808
load13001159168312413201619
domContentLoaded12821143165611613001562
domInteractive3721190333499
firstPaint237871575193287409
backgroundConnect220830814566274625346260
firstReactRender25165462836
initialActions105112
loadScripts1058936140210410831312
setupStore177128141742
numNetworkReqs2404853488303347
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2192182190219219
srpButtonToSrpForm95939519595
confirmSrpToPwForm22212312323
pwFormToMetricsScreen15151601616
metricsToWalletReadyScreen15151601616
doneButtonToHomeScreen74758510491778451049
openAccountMenuToAccountListLoaded27962496292917129272929
total3899388139271939053927
Onboarding New WalletcreateWalletToSocialScreen2182172201219220
srpButtonToPwForm1051031071106107
createPwToRecoveryScreen888088
skipBackupToMetricsScreen37363813738
agreeButtonToOnboardingSuccess16151601616
doneButtonToAssetList669465946181748946
total1053848132818111321328
Asset DetailsassetClickToPriceChart78541041686104
total78541041686104
Solana Asset DetailsassetClickToPriceChart1154417849158178
total1154417849158178
Import Srp HomeloginToHomeScreen2320229223352023352335
openAccountMenuAfterLogin503366136166
homeAfterImportWithNewWallet23562242251510323762515
total4728462848206847374820
Send TransactionsopenSendPageFromHome462361155761
selectTokenToSendFormLoaded36284264142
reviewTransactionToConfirmationPage1252716164831714501648
total1334812175132015361751
SwapopenSwapPageFromHome1241131308130130
fetchAndDisplaySwapQuotes269126882695326932695
total2824280328521828242852
🌐 Dapp Page Load Benchmarks

Current Commit: 10515dd | Date: 3/19/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.07s (±41ms) 🟡 | historical mean value: 1.03s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 757ms (±62ms) 🟢 | historical mean value: 721ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 96ms (±130ms) 🟢 | historical mean value: 84ms ⬆️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.07s 41ms 1.04s 1.39s 1.10s 1.39s
domContentLoaded 757ms 62ms 729ms 1.32s 781ms 1.32s
firstPaint 96ms 130ms 68ms 1.39s 92ms 1.39s
firstContentfulPaint 96ms 130ms 68ms 1.39s 92ms 1.39s
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs
  • background: 58 Bytes (0%)
  • ui: 5 Bytes (0%)
  • common: 20 Bytes (0%)

@seaona
Copy link
Member

seaona commented Mar 19, 2026

Test Dapp Sign Typed V4 and Permit

ledger-nano-s.mov

Uniswap signatures

nano-s-uniswap.mov

Copy link
Member

@gantunesr gantunesr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm and tested with Nano Gen5

@gantunesr gantunesr added this pull request to the merge queue Mar 19, 2026
Merged via the queue into main with commit 1173008 Mar 19, 2026
206 checks passed
@gantunesr gantunesr deleted the dr/fix-blind-sign branch March 19, 2026 13:17
@github-actions github-actions bot locked and limited conversation to collaborators Mar 19, 2026
@metamaskbot metamaskbot added the release-13.24.0 Issue or pull request that will be included in release 13.24.0 label Mar 19, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

hardware-ledger release-13.24.0 Issue or pull request that will be included in release 13.24.0 size-M team-accounts-framework Accounts team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Ledger Nano S : Unable to swap on dapps Uniswap and Pancakeswap

6 participants