{"id":"CVE-2026-10685","summary":"Use-after-free of GATT subscribe params in Bluetooth host CCC-write response handler","details":"The Zephyr Bluetooth GATT client CCC-write response handler gatt_write_ccc_rsp() in subsys/bluetooth/host/gatt.c invoked the application's params-\u003esubscribe() callback after it had already called params-\u003enotify(conn, params, NULL, 0).\n\nPer the public GATT API, a notify callback with NULL data is the documented signal that the subscription has terminated and the bt_gatt_subscribe_params struct may be freed or reused by the application; calling subscribe() on the struct afterwards is a use-after-free, including an indirect call through the freed params-\u003esubscribe function pointer.\n\nThe error branch is remotely (adjacent) reachable: a Zephyr device acting as a GATT client that calls bt_gatt_subscribe() can be driven into this ordering when a connected GATT server peer answers the CCC write with an ATT Error Response (the peer-supplied error code flows through att_error_rsp -\u003e att_handle_rsp into gatt_write_ccc_rsp).\n\nFor applications that free or recycle subscription parameters in their notification-termination handler, this results in memory corruption, a crash (denial of service), or potentially attacker-influenced control flow. The fix reorders the handler so the subscribe() callback runs before the terminating notify(NULL) in both the error and unsubscribe paths.","aliases":["GHSA-29xh-jm2m-4qvx"],"modified":"2026-09-02T03:31:00.322011847Z","published":"2026-07-31T14:41:47.259Z","database_specific":{"cna_assigner":"zephyr","cwe_ids":["CWE-416"],"osv_generated_from":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/10xxx/CVE-2026-10685.json"},"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/10xxx/CVE-2026-10685.json"},{"type":"ADVISORY","url":"https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-29xh-jm2m-4qvx"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-10685"},{"type":"FIX","url":"https://github.com/zephyrproject-rtos/zephyr/commit/c7292f20223637232b6f962141725611a38f6a52"},{"type":"PACKAGE","url":"https://github.com/zephyrproject-rtos/zephyr"}],"affected":[{"ranges":[{"type":"GIT","repo":"https://github.com/zephyrproject-rtos/zephyr","events":[{"introduced":"7a3b253ced7333f5c0269387a7f3ed1dee69739d"},{"fixed":"dccb09599635bdff17633fa7e9dab014b91dce90"}],"database_specific":{"extracted_events":[{"introduced":"2.4.0"},{"fixed":"4.4.2"}],"source":"AFFECTED_FIELD"}}],"versions":["v4.4.2-rc1","v4.4.1","v4.4.1-rc1","v4.4.0","v4.4.0-rc3","v4.4.0-rc2","v4.4.0-rc1","v4.3.0","v4.3.0-rc3","v4.3.0-rc2","v4.3.0-rc1","v4.2.0","v4.2.0-rc3","v4.2.0-rc2","v4.2.0-rc1","v4.1.0","v4.1.0-rc3","v4.1.0-rc2","v4.1.0-rc1","v4.0.0","v4.0.0-rc3","v4.0.0-rc2","v4.0.0-rc1","v3.7.0","v3.7.0-rc3","v3.7.0-rc2","v3.7.0-rc1","v3.6.0","v3.6.0-rc3","v3.6.0-rc2","v3.6.0-rc1","zephyr-v3.5.0","v3.5.0","v3.5.0-rc3","v3.5.0-rc2","v3.5.0-rc1","zephyr-v3.4.0","v3.4.0","v3.4.0-rc3","v3.4.0-rc2","v3.4.0-rc1","zephyr-v3.3.0","v3.3.0","v3.3.0-rc3","v3.3.0-rc2","v3.3.0-rc1","zephyr-v3.2.0","v3.2.0","v3.2.0-rc3","v3.2.0-rc2","v3.2.0-rc1","zephyr-v3.1.0","v3.1.0","v3.1.0-rc3","v3.1.0-rc2","v3.1.0-rc1","zephyr-v3.0.0","v3.0.0","v3.0.0-rc3","v3.0.0-rc2","v3.0.0-rc1","v2.7.99","v2.7.0-rc3","v2.7.0-rc2","v2.7.0-rc1","zephyr-v2.6.0","v2.6.0","v2.6.0-rc3","v2.6.0-rc2","v2.6.0-rc1","zephyr-v2.5.0","v2.5.0","v2.5.0-rc4","v2.5.0-rc3","v2.5.0-rc2","v2.5.0-rc1","zephyr-v2.4.0","v2.4.0"],"database_specific":{"source":"https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-10685.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:H"}]}