feat(mobile): migrate emulator proxy transport to DMK WebSocket protocol#14865
feat(mobile): migrate emulator proxy transport to DMK WebSocket protocol#14865OlivierFreyssinet wants to merge 3 commits intodevelopfrom
Conversation
…protocol Replace the legacy HTTP proxy transport (hw-transport-http + express) with a DMK-based WebSocket proxy for Ledger Live Mobile emulator development. New package @ledgerhq/live-dmk-ws-proxy provides: - WsProxyTransport: DMK Transport with push-based device discovery - DeviceManagementKitWSProxyTransport: legacy hw-transport bridge - useWsProxyDevicesDiscovery: React hook for SelectDevice2 integration - Shared WS protocol types used by both CLI server and mobile client CLI proxy server rewritten to use DMK + nodeHidTransportFactory with WebSocket-only protocol (removed express/cors/body-parser deps). The legacy httpdebug transport module is preserved for Speculos E2E tests. LIVE-27000 Made-with: Cursor
Made-with: Cursor
| return; | ||
| } | ||
| console.log( | ||
| `${TAG} ← ${url}: ${msg.type}`, |
Check failure
Code scanning / CodeQL
Use of externally-controlled format string High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 19 hours ago
General approach: avoid putting untrusted data into the format string argument of any logging function that uses util.format semantics (console.log, console.error, or wrappers like log). Instead, pass a constant format string as the first argument and supply untrusted values as subsequent arguments, typically with a %s placeholder or just as additional arguments after a constant prefix.
Best concrete fix for WsProxyTransport.openConnection: change the console.log in ws.onmessage so that the first argument is a constant string and both url and msg.type are provided as separate arguments. This preserves the exact logged content while ensuring untrusted values aren’t part of the format string. For example:
console.log(
"%s ← %s: %s",
TAG,
url,
msg.type,
msg.type === "devices" ? `(${msg.devices.length} devices)` : "",
);This change is limited to the highlighted logging call around line 256–259 in libs/live-dmk-ws-proxy/src/transport/WsProxyTransport.ts. No new imports or helpers are required; we just adjust the argument structure of the existing console.log. This single change addresses all reported variants associated with this logging site (the variants are all about different taint sources reaching the same sink). The rest of the code in the shown snippets does not put untrusted data directly into format strings as the first argument, so no edits are necessary there.
| @@ -254,7 +254,10 @@ | ||
| return; | ||
| } | ||
| console.log( | ||
| `${TAG} ← ${url}: ${msg.type}`, | ||
| "%s ← %s: %s", | ||
| TAG, | ||
| url, | ||
| msg.type, | ||
| msg.type === "devices" ? `(${msg.devices.length} devices)` : "", | ||
| ); | ||
| this.handleMessage(conn, msg); |
CLI proxy (apps/cli): - Remove session-readiness wait that hangs with disabled refresher - Add APDU queue to serialize concurrent sendApdu calls - Add session cleanup on re-open to avoid stale sessions - Fix deviceModel field mappings (model/name instead of id/productName) - Improve error logging to stringify non-Error objects - Bump node-hid 2.1.2 → 3.3.0 for device-transport-kit-node-hid Mobile app (apps/ledger-live-mobile): - Rework DebugHttpTransport screen into WS Proxy configuration UI - Add @ledgerhq/live-dmk-ws-proxy dependency - Rename navigation entry from "HTTP Transport" to "WS Proxy" WS proxy transport lib (libs/live-dmk-ws-proxy): - Refactor WsProxyTransport to manage WS connections at instance level via eager URL manager, independent of subscriber lifecycle - Fix modelId mapping in useWsProxyDevicesDiscovery (model, not id) - Preserve WS connections on hook cleanup for active sessions - Add console.log tracing throughout transport and bridge Package fixes: - Fix live-dmk-speculos module resolution (main → lib/index.js, exports import → default for rspack CJS compat) Made-with: Cursor
ca8bbc2 to
cc3c52e
Compare
✅ Checklist
npx changesetwas attached.ledger-live proxycommand (rewritten to use DMK + WebSocket-only protocol)useWsProxyDevicesDiscoveryhook inSelectDevice2)@ledgerhq/live-dmk-ws-proxypackage (DMK transport, bridge, discovery hook, shared protocol types)httpdebugtransport module is preserved for Speculos E2E test compatibility📝 Description
Problem: The emulator proxy transport in Ledger Live Mobile relies on legacy LedgerJS packages (
@ledgerhq/hw-transport-http,@ledgerhq/hw-transport-node-hid) with an HTTP polling discovery model and aknownDevicesRedux hack. This prevents access to DMK features (session management, device actions) and doesn't align with the ongoing DMK migration.Solution: Introduce a new
@ledgerhq/live-dmk-ws-proxypackage that provides:WsProxyTransport: DMKTransportimplementation with push-based device discovery over WebSocket and APDU exchangeDeviceManagementKitWSProxyTransport: Bridge class extending legacyhw-transportthat exposessessionIdanddmkpropertiesuseWsProxyDevicesDiscovery: React hook forSelectDevice2integration, following the same pattern as BLE/HID discovery hooksprotocol.ts): Single source of truth for all message types, imported by both CLI server and mobile clientThe CLI proxy server (
ledger-live proxy) is rewritten to useDeviceManagementKitwithnodeHidTransportFactory, replacingexpress/cors/body-parserwith a leanhttp+wssetup. Device discovery is now push-based (server broadcasts device list changes to all connected clients).The proxy URL can be configured at build time via
DEVICE_PROXY_URLenv var or at runtime via the Debug HTTP Transport settings screen. Both sources are merged by the discovery hook through aBehaviorSubjectside-channel.The legacy
httpdebugtransport module andaddKnownDeviceflow are preserved for Speculos E2E test compatibility.❓ Context
🧐 Checklist for the PR Reviewers
Made with Cursor