Ledger Security Bulletin 023
Command interleaving during an on-screen review could desynchronise the display from the signature
27 August 2026: A host could submit a new APDU command while a previous one was still awaiting its reply, allowing signing parameters to be modified after they had been displayed to the user but before they were signed.
Summary
A vulnerability class was identified affecting applications for Ledger devices. The command reception path accepted and began processing a new APDU command while a previous command was still awaiting its reply; that is, while the user was reviewing an operation on screen. Because signing parameters are held in global state across that asynchronous review, an application that did not independently validate its own state machine on command entry could display one set of parameters and produce a signature covering different ones.
The defect is not in any single application, and it is not in the device operating system. It sits in the input and output event handling of the Ledger Secure SDK, the shared code that each application compiles into its own binary, which is why the correction reaches users as an application update rather than a firmware update.
The issue has been corrected in two stages. Affected applications were first hardened individually, so that every asynchronous entry point validates application state and rejects commands arriving during a pending review; the first of those releases was published and verified on 13 August 2026. The underlying opportunity was then removed for all applications at once in Ledger Secure SDK version v26.6.1, released on 21 August 2026, which rejects interleaved commands before they reach application code. Applications have since been rebuilt against the corrected SDK and re-published.
Description
Applications for Ledger devices process an APDU command, then hand control to the user interface and return IO_ASYNCH_REPLY without answering the host. The reply is sent later, from the approval or rejection callback. During that interval the device is showing a review screen, and the parameters that the callback will sign (derivation path, hashes, amounts, destination addresses) remain in global structures so that they survive until the user decides.
The SDK code that receives commands did not prevent the host from sending a further one during that interval. Each application was therefore individually responsible for rejecting commands that arrived while one of its own operations was pending. Applications that guarded every asynchronous entry point with an explicit state check behaved correctly. An application that omitted the check on any single entry point exposed a window in which the host could overwrite parameters that had already been presented to the user, and the subsequent approval would sign the modified values.
Two properties of the command interface made the window practical to exploit rather than merely theoretical.
First, several commands accept their payload in chunks. A handler typically parses leading fixed-position fields, such as a derivation path, as soon as the first chunk arrives, but only runs its main processing once the declared payload length has been received. An attacker could therefore send a first chunk that overwrote a leading field and then simply stop, withholding the remainder. The overwrite took effect while the fields that populate the display, which are written by the main processing step, retained their earlier values.
Second, because the interrupted command never completed, it produced no error and dismissed no screen. From the user’s point of view nothing happened at all; the original review remained on display, unchanged, and the confirmation they gave was for what they could see.
The result is a time-of-check to time-of-use condition (CWE-362). The check is the user reading the screen; the use is the signature produced when they confirm. In the worst case the two no longer describe the same operation, which defeats the trusted-display guarantee that a hardware wallet exists to provide.
Impact
Exploitation requires an adversary in control of the APDU exchange with the device: a malicious or compromised wallet application, a hostile page holding a WebHID or WebUSB connection, or malware on the connected computer.
Where an affected application was in use, a user could approve an operation the device described accurately and receive a signature over different parameters. The user’s confirmation is genuine, and no indication of the substitution appears on the device, so the failure is not detectable by the person approving it.
The reach of any individual instance is bounded by what the affected command can express and by whatever independent validation the application performs elsewhere. Ledger has no evidence that this issue was exploited against users.
Affected releases
The condition is a regression rather than a long-standing weakness. It was introduced in the course of August 2025; before that point the opportunity to interleave commands did not exist, and releases predating it are not affected.
Applications built against a Ledger Secure SDK from that point up to and including v26.6.0, released 11 August 2026, rely entirely on their own handlers to reject interleaved commands. Whether a particular application is exposed depends on whether every one of its asynchronous entry points validates application state on entry; applications that do so consistently are not affected.
Ledger has reviewed its first-party applications on that basis and rebuilt them against the corrected SDK. Developers of third-party applications should perform the same review of their own command handlers and rebuild against v26.6.1 or later.
The device operating system and its firmware are not affected. Exposure is determined by the SDK version an application was built against, and it is resolved by installing corrected applications.
Remediation
The issue was addressed in two stages: first in the applications themselves, then generically in the SDK.
Applications first. Affected applications were hardened so that each asynchronous entry point validates application state on entry and refuses to disturb an operation that is already pending. This covered signing commands, address and public-key verification, plugin registration, transaction-simulation and gating commands, preparatory metadata commands, and the privacy operation, which received a dedicated application state of its own. Approval callbacks were also changed to re-validate application state before acting, so that a callback cannot complete against a context that has been replaced since the screen was drawn. The guards are fail-closed: a command arriving at the wrong point in the state machine is rejected rather than serviced. The first application release carrying this work was published on 13 August 2026, and its corrections were verified the same morning.
Then the SDK. Application-level guards are only correct for as long as every entry point in every application is covered, so the opportunity was subsequently removed in the SDK’s input and output layer, before commands reach application code. That layer now maintains a latch, armed when a command is accepted and released when the application replies; while it is armed, an incoming command is answered directly with a refusal status and never reaches the application. The correction was released as Ledger Secure SDK v26.6.1 on 21 August 2026. v26.6.0 is the last SDK release without it.
Applications were rebuilt against v26.6.1 and re-published on 21 August 2026. Because the protection sits in shared SDK code, it applies to every application rebuilt against the corrected SDK, including those that had no state-validation defect of their own.
Users should update their applications through Ledger Live and verify the application version on the signer. Updating device firmware alone does not establish that the affected applications have been replaced.
Credit
Identified by Ledger’s internal continuous security review of the Ledger Secure SDK and of its first-party applications.
Ledger thanks the security researchers who continue to report state-machine and race-condition findings against its products through the Ledger Devices Bug Bounty programme.
Timeline
| Date | Action |
|---|---|
| August 2025 | The regression is introduced. Interleaving a command with a pending reply becomes possible. |
| 8 June 2026 | The SDK-level correction is authored. |
| 11 August 2026 | Ledger Secure SDK v26.6.0 is released. It is the last SDK release without the correction. |
| 13 August 2026 | Ethereum app 1.22.2 is published, the first application release carrying the application-level state guards. Its corrections are verified the same morning. |
| 21 August 2026 | The correction is released in Ledger Secure SDK v26.6.1. |
| 21 August 2026 | Applications are rebuilt against v26.6.1 and re-published. |
| 27 August 2026 | Security bulletin published. |