Bump Speculos and Ledger Bitcoin app
What changed, and why it matters
This commit updates the versions of testing tools and Ledger Bitcoin app used in HWI's automated test environment. It does not change the actual HWI wallet-interaction code that users run. The changes are purely to keep CI/test simulations working with newer Ledger firmware and emulator releases.
No security action required. Treat as routine test-infrastructure maintenance. Reviewers may verify that the updated app and emulator still pass the existing Ledger test matrix.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff bumps the Speculos emulator from v0.25.10 to v0.26.9, the Ledger app-bitcoin test build from v2.4.1 to v2.5.0, and the ledger-app-builder container from 4.23.0 to 5.3.17. It also adjusts the test automation JSON to handle new UI prompts introduced by the updated app (e.g., ‘Security risk’, ‘High fees warning’, ‘External amounts’, ‘You spend’, etc.) and sets supports_arbitrary_keypool_paths based on legacy mode because app-bitcoin v2.5.0 enforces standard Ledger derivation paths. No production code paths are modified.
Changed components
HWI CI/test environmentLedger emulator test harnessSpeculos automation rulesInspect captured patch +28 / −9
diff --git a/.github/workflows/ledger-app-builder.yml b/.github/workflows/ledger-app-builder.yml
index e97f883..19cb9cd 100644
--- a/.github/workflows/ledger-app-builder.yml
+++ b/.github/workflows/ledger-app-builder.yml
@@ -11,14 +11,14 @@ jobs:
build:
name: Build Bitcoin App
runs-on: ${{ inputs.runs-on }}
- # Pin to 4.23.0 for SDK v25.9.0 compatibility with Speculos v0.25.10
- container: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:4.23.0
+ # app-bitcoin v2.5.0 targets SDK v26.5.0, provided by builder 5.3.17.
+ container: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:5.3.17
steps:
- run: |
- # Pin to v2.4.1 - last version that worked with HWI CI (PR #795 merged Sept 2025)
- git clone --branch 2.4.1 --depth 1 https://github.com/LedgerHQ/app-bitcoin.git
+ # Pin to v2.5.0
+ git clone --branch 2.5.0 --depth 1 https://github.com/LedgerHQ/app-bitcoin.git
cd app-bitcoin
- make DEBUG=1 BOLOS_SDK=$NANOX_SDK
+ make DEBUG=1 COIN=bitcoin_testnet BOLOS_SDK=$NANOX_SDK
- uses: actions/upload-artifact@v4
with:
name: ledger_app
diff --git a/.github/workflows/ledger-legacy-app-builder.yml b/.github/workflows/ledger-legacy-app-builder.yml
index d9c6179..28d7a2d 100644
--- a/.github/workflows/ledger-legacy-app-builder.yml
+++ b/.github/workflows/ledger-legacy-app-builder.yml
@@ -11,7 +11,7 @@ jobs:
build:
name: Build Bitcoin Legacy App
runs-on: ${{ inputs.runs-on }}
- # Pin to 4.23.0 for SDK v25.9.0 compatibility with Speculos v0.25.10
+ # Pin to 4.23.0 for SDK v25.9.0 compatibility with Speculos v0.26.9
container: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:4.23.0
steps:
- run: |
diff --git a/test/data/speculos-automation.json b/test/data/speculos-automation.json
index 31f69f7..bc16699 100644
--- a/test/data/speculos-automation.json
+++ b/test/data/speculos-automation.json
@@ -1,6 +1,13 @@
{
"version": 1,
"rules": [
+ {
+ "regexp": "^(Security risk|High fees warning).*",
+ "actions": [
+ [ "button", 2, true ],
+ [ "button", 2, false ]
+ ]
+ },
{
"text": "Confirm",
"x": 43, "y": 37,
@@ -11,6 +18,16 @@
[ "button", 2, false ]
]
},
+ {
+ "text": "Confirm",
+ "x": 41, "y": 34,
+ "actions": [
+ [ "button", 1, true ],
+ [ "button", 2, true ],
+ [ "button", 1, false ],
+ [ "button", 2, false ]
+ ]
+ },
{
"text": "Confirm account ",
"actions": [
@@ -28,7 +45,7 @@
]
},
{
- "regexp": "^(Address|Review|Amount|Fee|Confirm|The derivation|Derivation path|Reject if|The change path|Change path|Register wallet|Policy map|Key|Path|Public key|Spend from|Wallet name|Wallet policy|Descriptor template|Verify Bitcoin|Output|Warning).*",
+ "regexp": "^(Address|Review|Amount|External amounts|You spend|You receive|Fee|Confirm|The derivation|Derivation path|Reject if|The change path|Change path|Register wallet|Policy map|Key|Path|Public key|Our key|Their key|Unspendable key|Spend from|Spending policy|Primary spending path|Spending path|Transaction output|Wallet name|Wallet policy|Descriptor template|Verify [Bb]itcoin|Output|Warning).*",
"actions": [
[ "button", 2, true ],
[ "button", 2, false ]
diff --git a/test/setup_environment.sh b/test/setup_environment.sh
index 069b238..c9c2477 100755
--- a/test/setup_environment.sh
+++ b/test/setup_environment.sh
@@ -69,7 +69,7 @@ TREZOR_VERSION="core/v2.9.6"
BITBOX01_VERSION="v7.1.0"
BITBOX02_VERSION="firmware/v9.24.0"
KEEPKEY_VERSION="v7.10.0"
-SPECULOS_VERSION="v0.25.10" # v0.25.11+ requires Python >=3.10
+SPECULOS_VERSION="v0.26.9" # Requires Python >=3.10 (v0.25.11+)
JADE_VERSION="1.0.36"
# Keep COLDCARD_VERSION in sync with .github/actions/install-sim/action.yml
diff --git a/test/test_ledger.py b/test/test_ledger.py
index 6ab162e..00a0cee 100755
--- a/test/test_ledger.py
+++ b/test/test_ledger.py
@@ -47,12 +47,14 @@ class LedgerEmulator(DeviceEmulator):
self.include_xpubs = True
self.supports_device_multiple_multisig = True
self.supports_legacy = True
+ # Bitcoin app 2.5.0 enforces standard Ledger paths for xpub derivation.
+ self.supports_arbitrary_keypool_paths = legacy
def start(self):
super().start()
automation_path = os.path.abspath("data/speculos-automation.json")
app_path = f"./apps/btc-test{'-legacy' if self.legacy else ''}.elf"
- os.environ["SPECULOS_APPNAME"] = "Bitcoin Test:1.6.6" if self.legacy else "Bitcoin Test:2.4.1"
+ os.environ["SPECULOS_APPNAME"] = "Bitcoin Test:1.6.6" if self.legacy else "Bitcoin Test:2.5.0"
self.emulator_stderr = open('ledger-emulator.stderr', 'a')
# Start the emulator
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.