{"api_version":"1","generated_at":"2026-11-13T05:20:30+00:00","cve":"CVE-2026-16664","urls":{"html":"https://cve.report/CVE-2026-16664","api":"https://cve.report/api/cve/CVE-2026-16664.json","docs":"https://cve.report/api","cve_org":"https://www.cve.org/CVERecord?id=CVE-2026-16664","nvd":"https://nvd.nist.gov/vuln/detail/CVE-2026-16664"},"summary":{"title":"Unchecked serial-recovery image index causes out-of-bounds slot-table read in MCUboot Zephyr port","description":"MCUboot's Zephyr serial-recovery upload handler bs_upload() in boot/boot_serial/src/boot_serial.c decodes the host-supplied image field of an MCUmgr image-upload request into img_num (a full 32-bit value) and latches it on the off == 0 packet without any range check. It then passes img_num straight to flash_area_id_from_multi_image_slot(img_num, 0), which on the Zephyr port resolves to __flash_area_ids_for_slot() in boot/zephyr/include/sysflash/sysflash.h and indexes the static const int all_slots[] table as all_slots[img_num  2]. That table holds only MCUBOOT_IMAGE_NUMBER  2 entries, so any img_num >= MCUBOOT_IMAGE_NUMBER is an out-of-bounds read.\n\nThe path is reachable by anyone with access to the serial / SMP recovery console, which is unauthenticated by design, and the bad value is supplied before any image signature is verified. The defect is specific to the default non-direct upload path (MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD disabled) on the Zephyr port with the array-backed slot layout (not CONFIG_SINGLE_APPLICATION_SLOT). It is not gated on a multi-image configuration: MCUBOOT_IMAGE_NUMBER defaults to 1, so even a default single-image build is affected for any image >= 1. The MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD path is safe (its flash_area_id_from_direct_image() switch returns -EINVAL for unknown indices).\n\nflash_area_id_from_multi_image_slot() takes a signed int image_index while img_num is uint32_t, so the attacker controls the sign of the index as well as its magnitude: an image of 0xFFFFFFFF converts to -1 and reads all_slots[-2], off the front of the table, while large positive values read off the end (CWE-192). Either way the index multiply img * 2 is performed in int, so a wild offset yields a bus/hard fault, giving a reliable denial of service of the bootloader during recovery. For moderately out-of-range indices the read returns adjacent .rodata as a garbage flash-area id that is handed to flash_area_open(); this normally fails with MGMT_ERR_EINVAL, but if the garbage id happens to match a valid non-image partition, the subsequent erase/write can target a partition outside the image set (CWE-787). The attacker-supplied value is never echoed back, so there is no information disclosure. The fix is to reject img_num >= BOOT_IMAGE_NUMBER on the off == 0 packet, before the slot lookup. The comparison must be made on the unsigned img_num: an equivalent guard applied after the conversion to int would not reject the negative case above. __flash_area_ids_for_slot() should bounds-check its own arguments as defence in depth.\nThis vulnerability was reported independently twice: by NVIDIA Project Vanessa on 2026-06-22, and by Kai Phan (@kaimandalic) on 2026-07-19 as GHSA-8v33-88p6-jffj, which is closed as a duplicate of this advisory. Both original reports are reproduced in full below.","state":"PUBLISHED","assigner":"zephyr","published_at":"2026-11-13 02:18:57","updated_at":"2026-11-13 02:18:57"},"problem_types":["CWE-129","CWE-129 bounds"],"metrics":[{"version":"3.1","source":"vulnerabilities@zephyrproject.org","type":"Secondary","score":"5.1","severity":"MEDIUM","vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L","data":{"version":"3.1","vectorString":"CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L","baseScore":5.1,"baseSeverity":"MEDIUM","attackVector":"LOCAL","attackComplexity":"LOW","privilegesRequired":"NONE","userInteraction":"NONE","scope":"UNCHANGED","confidentialityImpact":"NONE","integrityImpact":"LOW","availabilityImpact":"LOW"}},{"version":"3.1","source":"CNA","type":"CVSS","score":"5.1","severity":"MEDIUM","vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L","data":{"baseScore":5.1,"baseSeverity":"MEDIUM","vectorString":"CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L","version":"3.1"}}],"references":[{"url":"https://github.com/mcu-tools/mcuboot/security/advisories/GHSA-8rcq-2mgr-fhp8","name":"https://github.com/mcu-tools/mcuboot/security/advisories/GHSA-8rcq-2mgr-fhp8","refsource":"vulnerabilities@zephyrproject.org","tags":[],"title":"","mime":"","httpstatus":"","archivestatus":"0"},{"url":"https://github.com/mcu-tools/mcuboot/commit/183a05f256bdbbac86edcb048958da59018f814e","name":"https://github.com/mcu-tools/mcuboot/commit/183a05f256bdbbac86edcb048958da59018f814e","refsource":"vulnerabilities@zephyrproject.org","tags":[],"title":"","mime":"","httpstatus":"","archivestatus":"0"},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-16664","name":"CVE Program record","refsource":"CVE.ORG","tags":["canonical"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-16664","name":"NVD vulnerability detail","refsource":"NVD","tags":["canonical","analysis"]}],"affected":[{"source":"CNA","vendor":"mcu-tools","product":"mcuboot","version":"affected 2.0.0 * semver","platforms":[]}],"timeline":[],"solutions":[],"workarounds":[],"exploits":[],"credits":[],"nvd_cpes":[],"vendor_comments":[],"enrichments":{"kev":null,"epss":null,"legacy_qids":[]},"source_records":{"cve_program":{"containers":{"cna":{"affected":[{"collectionURL":"https://github.com/mcu-tools/mcuboot","defaultStatus":"unaffected","packageName":"mcuboot","product":"mcuboot","programFiles":["boot/boot_serial/src/boot_serial.c","boot/zephyr/include/sysflash/sysflash.h"],"programRoutines":[{"name":"__flash_area_ids_for_slot"},{"name":"bs_upload"}],"vendor":"mcu-tools","versions":[{"lessThanOrEqual":"*","status":"affected","version":"2.0.0","versionType":"semver"}]}],"descriptions":[{"lang":"en","value":"MCUboot's Zephyr serial-recovery upload handler bs_upload() in boot/boot_serial/src/boot_serial.c decodes the host-supplied image field of an MCUmgr image-upload request into img_num (a full 32-bit value) and latches it on the off == 0 packet without any range check. It then passes img_num straight to flash_area_id_from_multi_image_slot(img_num, 0), which on the Zephyr port resolves to __flash_area_ids_for_slot() in boot/zephyr/include/sysflash/sysflash.h and indexes the static const int all_slots[] table as all_slots[img_num  2]. That table holds only MCUBOOT_IMAGE_NUMBER  2 entries, so any img_num >= MCUBOOT_IMAGE_NUMBER is an out-of-bounds read.\n\nThe path is reachable by anyone with access to the serial / SMP recovery console, which is unauthenticated by design, and the bad value is supplied before any image signature is verified. The defect is specific to the default non-direct upload path (MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD disabled) on the Zephyr port with the array-backed slot layout (not CONFIG_SINGLE_APPLICATION_SLOT). It is not gated on a multi-image configuration: MCUBOOT_IMAGE_NUMBER defaults to 1, so even a default single-image build is affected for any image >= 1. The MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD path is safe (its flash_area_id_from_direct_image() switch returns -EINVAL for unknown indices).\n\nflash_area_id_from_multi_image_slot() takes a signed int image_index while img_num is uint32_t, so the attacker controls the sign of the index as well as its magnitude: an image of 0xFFFFFFFF converts to -1 and reads all_slots[-2], off the front of the table, while large positive values read off the end (CWE-192). Either way the index multiply img * 2 is performed in int, so a wild offset yields a bus/hard fault, giving a reliable denial of service of the bootloader during recovery. For moderately out-of-range indices the read returns adjacent .rodata as a garbage flash-area id that is handed to flash_area_open(); this normally fails with MGMT_ERR_EINVAL, but if the garbage id happens to match a valid non-image partition, the subsequent erase/write can target a partition outside the image set (CWE-787). The attacker-supplied value is never echoed back, so there is no information disclosure. The fix is to reject img_num >= BOOT_IMAGE_NUMBER on the off == 0 packet, before the slot lookup. The comparison must be made on the unsigned img_num: an equivalent guard applied after the conversion to int would not reject the negative case above. __flash_area_ids_for_slot() should bounds-check its own arguments as defence in depth.\nThis vulnerability was reported independently twice: by NVIDIA Project Vanessa on 2026-06-22, and by Kai Phan (@kaimandalic) on 2026-07-19 as GHSA-8v33-88p6-jffj, which is closed as a duplicate of this advisory. Both original reports are reproduced in full below."}],"metrics":[{"cvssV3_1":{"baseScore":5.1,"baseSeverity":"MEDIUM","vectorString":"CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L","version":"3.1"},"format":"CVSS"}],"problemTypes":[{"descriptions":[{"cweId":"CWE-129","description":"bounds","lang":"en","type":"CWE"}]}],"providerMetadata":{"dateUpdated":"2026-11-13T00:23:05.652Z","orgId":"e2e69745-5e70-4e92-8431-deb5529a81ad","shortName":"zephyr"},"references":[{"name":"Fix commit","tags":["patch"],"url":"https://github.com/mcu-tools/mcuboot/commit/183a05f256bdbbac86edcb048958da59018f814e"},{"name":"GHSA-8rcq-2mgr-fhp8","url":"https://github.com/mcu-tools/mcuboot/security/advisories/GHSA-8rcq-2mgr-fhp8"}],"title":"Unchecked serial-recovery image index causes out-of-bounds slot-table read in MCUboot Zephyr port","x_generator":{"engine":"cvelib 1.8.0"}}},"cveMetadata":{"assignerOrgId":"e2e69745-5e70-4e92-8431-deb5529a81ad","assignerShortName":"zephyr","cveId":"CVE-2026-16664","datePublished":"2026-11-13T00:23:05.652Z","dateReserved":"2026-07-22T19:47:54.908Z","dateUpdated":"2026-11-13T00:23:05.652Z","state":"PUBLISHED"},"dataType":"CVE_RECORD","dataVersion":"5.2"},"nvd":{"publishedDate":"2026-11-13 02:18:57","lastModifiedDate":"2026-11-13 02:18:57","problem_types":["CWE-129","CWE-129 bounds"],"metrics":{"cvssMetricV31":[{"source":"vulnerabilities@zephyrproject.org","type":"Secondary","cvssData":{"version":"3.1","vectorString":"CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L","baseScore":5.1,"baseSeverity":"MEDIUM","attackVector":"LOCAL","attackComplexity":"LOW","privilegesRequired":"NONE","userInteraction":"NONE","scope":"UNCHANGED","confidentialityImpact":"NONE","integrityImpact":"LOW","availabilityImpact":"LOW"},"exploitabilityScore":2.5,"impactScore":2.5}]},"configurations":[]},"legacy_mitre":{"record":{"CveYear":"2026","CveId":"16664","Ordinal":"1","Title":"Unchecked serial-recovery image index causes out-of-bounds slot-","CVE":"CVE-2026-16664","Year":"2026"},"notes":[{"CveYear":"2026","CveId":"16664","Ordinal":"1","NoteData":"MCUboot's Zephyr serial-recovery upload handler bs_upload() in boot/boot_serial/src/boot_serial.c decodes the host-supplied image field of an MCUmgr image-upload request into img_num (a full 32-bit value) and latches it on the off == 0 packet without any range check. It then passes img_num straight to flash_area_id_from_multi_image_slot(img_num, 0), which on the Zephyr port resolves to __flash_area_ids_for_slot() in boot/zephyr/include/sysflash/sysflash.h and indexes the static const int all_slots[] table as all_slots[img_num  2]. That table holds only MCUBOOT_IMAGE_NUMBER  2 entries, so any img_num >= MCUBOOT_IMAGE_NUMBER is an out-of-bounds read.\n\nThe path is reachable by anyone with access to the serial / SMP recovery console, which is unauthenticated by design, and the bad value is supplied before any image signature is verified. The defect is specific to the default non-direct upload path (MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD disabled) on the Zephyr port with the array-backed slot layout (not CONFIG_SINGLE_APPLICATION_SLOT). It is not gated on a multi-image configuration: MCUBOOT_IMAGE_NUMBER defaults to 1, so even a default single-image build is affected for any image >= 1. The MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD path is safe (its flash_area_id_from_direct_image() switch returns -EINVAL for unknown indices).\n\nflash_area_id_from_multi_image_slot() takes a signed int image_index while img_num is uint32_t, so the attacker controls the sign of the index as well as its magnitude: an image of 0xFFFFFFFF converts to -1 and reads all_slots[-2], off the front of the table, while large positive values read off the end (CWE-192). Either way the index multiply img * 2 is performed in int, so a wild offset yields a bus/hard fault, giving a reliable denial of service of the bootloader during recovery. For moderately out-of-range indices the read returns adjacent .rodata as a garbage flash-area id that is handed to flash_area_open(); this normally fails with MGMT_ERR_EINVAL, but if the garbage id happens to match a valid non-image partition, the subsequent erase/write can target a partition outside the image set (CWE-787). The attacker-supplied value is never echoed back, so there is no information disclosure. The fix is to reject img_num >= BOOT_IMAGE_NUMBER on the off == 0 packet, before the slot lookup. The comparison must be made on the unsigned img_num: an equivalent guard applied after the conversion to int would not reject the negative case above. __flash_area_ids_for_slot() should bounds-check its own arguments as defence in depth.\nThis vulnerability was reported independently twice: by NVIDIA Project Vanessa on 2026-06-22, and by Kai Phan (@kaimandalic) on 2026-07-19 as GHSA-8v33-88p6-jffj, which is closed as a duplicate of this advisory. Both original reports are reproduced in full below.","Type":"Description","Title":"Unchecked serial-recovery image index causes out-of-bounds slot-"}]}}}