{"id":"CVE-2026-90587","aliases":["EUVD-2026-120488","GHSA-9pxv-6992-2g24"],"status":"published","title":"NULL pointer dereference in the Zephyr USB host stack when a device reports zero configurations","description":"usbh_device_init() in subsys/usb/host/usbh_device.c rejects a device whose device descriptor advertises bNumConfigurations == 0, but it only logs the error and jumps to the cleanup label without setting the return code. At that point the local err is still 0 from the preceding successful descriptor read, so the function returns success while having skipped usbh_device_set_configuration() — the only place udev-\u003ecfg_desc is allocated. The device structure is zero-initialised by usbh_device_alloc(), so udev-\u003ecfg_desc remains NULL.\n\nusbh_device_connect() treats the zero return as a successful enumeration and calls usbh_class_probe_device(), which starts its descriptor walk from udev-\u003ecfg_desc. usbh_desc_get_next_function() passes that NULL pointer to usbh_desc_is_valid(), whose only guard compares the caller-supplied size, so head-\u003ebLength is read through a NULL pointer.\n\nThe condition is triggered entirely by the attached peripheral: attaching a USB device (or any USB gadget emulating one) that reports bNumConfigurations = 0 reaches the defect directly from the UHC_EVT_DEV_CONNECTED_FS/_HS event handler in subsys/usb/host/usbh_core.c, with no authentication and no user interaction beyond the physical attachment.\n\nOn targets where page zero is unmapped or CONFIG_NULL_POINTER_EXCEPTION_DETECTION is enabled this raises a fatal exception in the USB host thread, denying service to the host. Where address zero is readable, the descriptor walker instead parses low memory as a descriptor chain and can dispatch a class probe() with attacker-influenced values, causing further out-of-bounds reads through the still-NULL udev-\u003ecfg_desc in usbh_desc_get_iface(). No attacker-controlled write was identified, so the impact is availability plus a bounded out-of-bounds read. Note that CONFIG_USB_HOST_STACK is marked experimental.","severity":{"version":"3.1","score":4.6,"vector":"CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00178,"percentile":0.074,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":false},"cwes":["CWE-476"],"published":"2026-11-09T22:03:59Z","modified":"2026-11-11T02:49:07Z","products":[{"vendor":"zephyrproject","product":"zephyr"},{"vendor":"zephyrproject-rtos","product":"zephyr"}],"references":[{"url":"https://github.com/zephyrproject-rtos/zephyr/commit/04e4284b4c3d3cd41791d44d7c39361e268b4d02","tags":["patch","fix"]},{"url":"https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-9pxv-6992-2g24","tags":["advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/90xxx/CVE-2026-90587.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-90587","tags":["advisory"]},{"url":"https://github.com/zephyrproject-rtos/zephyr","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-90587","title":"NULL pointer dereference in the Zephyr USB host stack when a device reports zero configurations","description":"usbh_device_init() in subsys/usb/host/usbh_device.c rejects a device whose device descriptor advertises bNumConfigurations == 0, but it only logs the error and jumps to the cleanup label without setting the return code. At that point the local err is still 0 from the preceding successful descriptor read, so the function returns success while having skipped usbh_device_set_configuration() — the only place udev-\u003ecfg_desc is allocated. The device structure is zero-initialised by usbh_device_alloc(), so udev-\u003ecfg_desc remains NULL.\n\nusbh_device_connect() treats the zero return as a successful enumeration and calls usbh_class_probe_device(), which starts its descriptor walk from udev-\u003ecfg_desc. usbh_desc_get_next_function() passes that NULL pointer to usbh_desc_is_valid(), whose only guard compares the caller-supplied size, so head-\u003ebLength is read through a NULL pointer.\n\nThe condition is triggered entirely by the attached peripheral: attaching a USB device (or any USB gadget emulating one) that reports bNumConfigurations = 0 reaches the defect directly from the UHC_EVT_DEV_CONNECTED_FS/_HS event handler in subsys/usb/host/usbh_core.c, with no authentication and no user interaction beyond the physical attachment.\n\nOn targets where page zero is unmapped or CONFIG_NULL_POINTER_EXCEPTION_DETECTION is enabled this raises a fatal exception in the USB host thread, denying service to the host. Where address zero is readable, the descriptor walker instead parses low memory as a descriptor chain and can dispatch a class probe() with attacker-influenced values, causing further out-of-bounds reads through the still-NULL udev-\u003ecfg_desc in usbh_desc_get_iface(). No attacker-controlled write was identified, so the impact is availability plus a bounded out-of-bounds read. Note that CONFIG_USB_HOST_STACK is marked experimental.","status":"published","published":"2026-11-09T22:03:59.315Z","modified":"2026-11-09T22:03:59.315Z","cvss":[{"version":"3.1","score":4.6,"vector":"CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"medium","assessor":"cna"}],"cwes":["CWE-476"],"updated_at":"2026-11-09T23:35:22.059445Z"}],"euvd":[{"id":"EUVD-2026-120488","description":"usbh_device_init() in subsys/usb/host/usbh_device.c rejects a device whose device descriptor advertises bNumConfigurations == 0, but it only logs the error and jumps to the cleanup label without setting the return code. At that point the local err is still 0 from the preceding successful descriptor read, so the function returns success while having skipped usbh_device_set_configuration() — the only place udev-\u003ecfg_desc is allocated. The device structure is zero-initialised by usbh_device_alloc(), so udev-\u003ecfg_desc remains NULL.\n\nusbh_device_connect() treats the zero return as a successful enumeration and calls usbh_class_probe_device(), which starts its descriptor walk from udev-\u003ecfg_desc. usbh_desc_get_next_function() passes that NULL pointer to usbh_desc_is_valid(), whose only guard compares the caller-supplied size, so head-\u003ebLength is read through a NULL pointer.\n\nThe condition is triggered entirely by the attached peripheral: attaching a USB device (or any USB gadget emulating one) that reports bNumConfigurations = 0 reaches the defect directly from the UHC_EVT_DEV_CONNECTED_FS/_HS event handler in subsys/usb/host/usbh_core.c, with no authentication and no user interaction beyond the physical attachment.\n\nOn targets where page zero is unmapped or CONFIG_NULL_POINTER_EXCEPTION_DETECTION is enabled this raises a fatal exception in the USB host thread, denying service to the host. Where address zero is readable, the descriptor walker instead parses low memory as a descriptor chain and can dispatch a class probe() with attacker-influenced values, causing further out-of-bounds reads through the still-NULL udev-\u003ecfg_desc in usbh_desc_get_iface(). No attacker-controlled write was identified, so the impact is availability plus a bounded out-of-bounds read. Note that CONFIG_USB_HOST_STACK is marked experimental.","status":"published","published":"2026-11-09T22:03:59Z","modified":"2026-11-09T22:03:59Z","cvss":[{"version":"3.1","score":4.6,"vector":"CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"medium"}],"updated_at":"2026-11-09T23:18:32.235826Z"}],"nvd":[{"id":"CVE-2026-90587","description":"usbh_device_init() in subsys/usb/host/usbh_device.c rejects a device whose device descriptor advertises bNumConfigurations == 0, but it only logs the error and jumps to the cleanup label without setting the return code. At that point the local err is still 0 from the preceding successful descriptor read, so the function returns success while having skipped usbh_device_set_configuration() — the only place udev-\u003ecfg_desc is allocated. The device structure is zero-initialised by usbh_device_alloc(), so udev-\u003ecfg_desc remains NULL.\n\nusbh_device_connect() treats the zero return as a successful enumeration and calls usbh_class_probe_device(), which starts its descriptor walk from udev-\u003ecfg_desc. usbh_desc_get_next_function() passes that NULL pointer to usbh_desc_is_valid(), whose only guard compares the caller-supplied size, so head-\u003ebLength is read through a NULL pointer.\n\nThe condition is triggered entirely by the attached peripheral: attaching a USB device (or any USB gadget emulating one) that reports bNumConfigurations = 0 reaches the defect directly from the UHC_EVT_DEV_CONNECTED_FS/_HS event handler in subsys/usb/host/usbh_core.c, with no authentication and no user interaction beyond the physical attachment.\n\nOn targets where page zero is unmapped or CONFIG_NULL_POINTER_EXCEPTION_DETECTION is enabled this raises a fatal exception in the USB host thread, denying service to the host. Where address zero is readable, the descriptor walker instead parses low memory as a descriptor chain and can dispatch a class probe() with attacker-influenced values, causing further out-of-bounds reads through the still-NULL udev-\u003ecfg_desc in usbh_desc_get_iface(). No attacker-controlled write was identified, so the impact is availability plus a bounded out-of-bounds read. Note that CONFIG_USB_HOST_STACK is marked experimental.","status":"published","published":"2026-11-09T22:18:56.97Z","modified":"2026-11-09T22:18:57.087Z","cvss":[{"version":"3.1","score":4.6,"vector":"CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"medium","assessor":"secondary"}],"cwes":["CWE-476"],"updated_at":"2026-11-09T23:16:05.865626Z"}],"osv":[{"id":"CVE-2026-90587","title":"NULL pointer dereference in the Zephyr USB host stack when a device reports zero configurations","description":"usbh_device_init() in subsys/usb/host/usbh_device.c rejects a device whose device descriptor advertises bNumConfigurations == 0, but it only logs the error and jumps to the cleanup label without setting the return code. At that point the local err is still 0 from the preceding successful descriptor read, so the function returns success while having skipped usbh_device_set_configuration() — the only place udev-\u003ecfg_desc is allocated. The device structure is zero-initialised by usbh_device_alloc(), so udev-\u003ecfg_desc remains NULL.\n\nusbh_device_connect() treats the zero return as a successful enumeration and calls usbh_class_probe_device(), which starts its descriptor walk from udev-\u003ecfg_desc. usbh_desc_get_next_function() passes that NULL pointer to usbh_desc_is_valid(), whose only guard compares the caller-supplied size, so head-\u003ebLength is read through a NULL pointer.\n\nThe condition is triggered entirely by the attached peripheral: attaching a USB device (or any USB gadget emulating one) that reports bNumConfigurations = 0 reaches the defect directly from the UHC_EVT_DEV_CONNECTED_FS/_HS event handler in subsys/usb/host/usbh_core.c, with no authentication and no user interaction beyond the physical attachment.\n\nOn targets where page zero is unmapped or CONFIG_NULL_POINTER_EXCEPTION_DETECTION is enabled this raises a fatal exception in the USB host thread, denying service to the host. Where address zero is readable, the descriptor walker instead parses low memory as a descriptor chain and can dispatch a class probe() with attacker-influenced values, causing further out-of-bounds reads through the still-NULL udev-\u003ecfg_desc in usbh_desc_get_iface(). No attacker-controlled write was identified, so the impact is availability plus a bounded out-of-bounds read. Note that CONFIG_USB_HOST_STACK is marked experimental.","status":"published","published":"2026-11-09T22:03:59.315Z","modified":"2026-11-11T02:49:07.077547334Z","cvss":[{"version":"3.1","score":4.6,"vector":"CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"medium"}],"cwes":["CWE-476"],"updated_at":"2026-11-11T03:21:16.313764Z"}]}}
