From c9d715ac08f81efcd180ad1e26962cd1813d7534 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Jul 2026 02:42:47 +0200 Subject: [PATCH 1/2] fix(M15): emit the import safety-backup once, only after the blob validates Co-Authored-By: Claude Opus 4.8 (1M context) --- serial/commands_backup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/serial/commands_backup.c b/serial/commands_backup.c index ea18467..e0fd05f 100644 --- a/serial/commands_backup.c +++ b/serial/commands_backup.c @@ -66,10 +66,10 @@ void cmd_import_keys(int argc, char **argv) { return; } - // Backup first - printf("backing up current keys...\r\n"); - cmd_export_keys(0, NULL); - + // M15: the safety-backup is emitted ONCE, later — only after the pasted blob + // has been received and base64-decoded (see "backing up current keys" below). + // The old unconditional backup here ran even when the import turned out to be + // empty/garbage, so it was removed. printf("paste import data, then send empty line:\r\n"); // Read base64 directly from serial into a large static buffer From f3669569b6dd3b7124c3f119f8d9a6d024e514f3 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 4 Aug 2026 20:26:42 +0200 Subject: [PATCH 2/2] fix(cmd_status): function-scope keys so the coverage/firmware build compiles Rebasing onto current master pulled in a latent build break: cmd_status declares `keys` inside the `if (commands_is_admin())` block but scrubs it via `secure_wipe(keys, sizeof(keys))` at function scope, so `keys` is undeclared there. asan_commands links serial/commands.c (not commands_system.c) so it never compiled this TU, but `make -C test coverage` compiles the whole first-party surface and fails here (`keys undeclared`) -- as does the real firmware build. Restore `keys` to function scope, matching the scrub's intent of always clearing the key DB from BSS (incl. the non-admin path where it stays zero-initialised). Same fix as PR #15 (M1). Co-Authored-By: Claude Opus 4.8 (1M context) --- serial/commands_system.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/serial/commands_system.c b/serial/commands_system.c index 4b92f9e..bdd3cac 100644 --- a/serial/commands_system.c +++ b/serial/commands_system.c @@ -64,11 +64,13 @@ void cmd_status(int argc, char **argv) { printf("ntp: not synced\r\n"); } - // Keys (admin only: key inventory is target-selection data) + // Keys (admin only: key inventory is target-selection data). Declared at + // function scope so the scrub below always runs, even on the non-admin path + // where the array stays zero-initialised. + static key_record_t keys[BACKUP_MAX_KEYS]; if (commands_is_admin()) { - static key_record_t keys[BACKUP_MAX_KEYS]; - int count = storage_key_list(keys, BACKUP_MAX_KEYS); - int enabled = 0, corrupt = 0; + int count = storage_key_list(keys, BACKUP_MAX_KEYS); + int enabled = 0, corrupt = 0; for (int i = 0; i < count; i++) { if (!keys[i].is_checksum_valid) corrupt++;