← Back to CVE Explorer

CVE-2026-10685

Full vulnerability record from the local CVENow database.

Description

The Zephyr Bluetooth GATT client CCC-write response handler gatt_write_ccc_rsp() in subsys/bluetooth/host/gatt.c invoked the application's params->subscribe() callback after it had already called params->notify(conn, params, NULL, 0). Per 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->subscribe function pointer. The 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 -> att_handle_rsp into gatt_write_ccc_rsp). For 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.

Severity
HIGH
CVSS score
7.6 (v3.1)
Vulnerability status
Analyzed
Source identifier
Published
2026-07-31 15:16:27.433000
Last modified
2026-10-23 23:10:00.157000
View original CVE JSON
{
  "id": "CVE-2026-10685",
  "sourceIdentifier": "[email protected]",
  "published": "2026-07-31T15:16:27.433",
  "lastModified": "2026-10-23T23:10:00.157",
  "vulnStatus": "Analyzed",
  "cveTags": [],
  "descriptions": [
    {
      "lang": "en",
      "value": "The Zephyr Bluetooth GATT client CCC-write response handler gatt_write_ccc_rsp() in subsys/bluetooth/host/gatt.c invoked the application's params->subscribe() callback after it had already called params->notify(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->subscribe 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 -> 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."
    },
    {
      "lang": "es",
      "value": "El gestor de respuesta de escritura CCC del cliente Zephyr Bluetooth GATT gatt_write_ccc_rsp() en subsys/bluetooth/host/gatt.c invocó la devolución de llamada params  ->  subscribe() de la aplicación después de haber llamado ya a params  ->  notify(conn, params, NULL, 0).\n\nSegún la API pública de GATT, una devolución de llamada de notificación con datos NULL es la señal documentada de que la suscripción ha terminado y la estructura bt_gatt_subscribe_params puede ser liberada o reutilizada por la aplicación; llamar a subscribe() en la estructura después es un uso después de liberación, incluyendo una llamada indirecta a través del puntero de función params  ->  subscribe liberado.\n\nLa rama de error es alcanzable remotamente (adyacente): un dispositivo Zephyr que actúa como un cliente GATT que llama a bt_gatt_subscribe() puede ser llevado a este ordenamiento cuando un par de servidor GATT conectado responde a la escritura CCC con una Respuesta de Error ATT (el código de error proporcionado por el par fluye a través de att_error_rsp   ->   att_handle_rsp hacia gatt_write_ccc_rsp).\n\nPara aplicaciones que liberan o reciclan parámetros de suscripción en su gestor de terminación de notificación, esto resulta en corrupción de memoria, un fallo (denegación de servicio), o un flujo de control potencialmente influenciado por el atacante. La solución reordena el gestor para que la devolución de llamada subscribe() se ejecute antes de la notificación de terminación notify(NULL) tanto en las rutas de error como de anulación de suscripción."
    }
  ],
  "affected": [
    {
      "source": "[email protected]",
      "affectedData": [
        {
          "vendor": "zephyrproject",
          "product": "zephyr",
          "defaultStatus": "unaffected",
          "collectionURL": "https://github.com/zephyrproject-rtos/zephyr",
          "packageName": "zephyr",
          "programFiles": [
            "subsys/bluetooth/host/gatt.c"
          ],
          "versions": [
            {
              "version": "2.4.0",
              "lessThan": "4.4.2",
              "versionType": "semver",
              "status": "affected"
            }
          ]
        }
      ]
    }
  ],
  "metrics": {
    "cvssMetricV31": [
      {
        "source": "[email protected]",
        "type": "Secondary",
        "cvssData": {
          "version": "3.1",
          "vectorString": "CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:H",
          "baseScore": 7.6,
          "baseSeverity": "HIGH",
          "attackVector": "ADJACENT_NETWORK",
          "attackComplexity": "LOW",
          "privilegesRequired": "NONE",
          "userInteraction": "NONE",
          "scope": "UNCHANGED",
          "confidentialityImpact": "LOW",
          "integrityImpact": "LOW",
          "availabilityImpact": "HIGH"
        },
        "exploitabilityScore": 2.8,
        "impactScore": 4.7
      }
    ],
    "ssvcV203": [
      {
        "source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
        "ssvcData": {
          "timestamp": "2026-07-31T17:46:39.697257Z",
          "id": "CVE-2026-10685",
          "options": [
            {
              "exploitation": "none"
            },
            {
              "automatable": "no"
            },
            {
              "technicalImpact": "partial"
            }
          ],
          "role": "CISA Coordinator",
          "version": "2.0.3"
        }
      }
    ]
  },
  "weaknesses": [
    {
      "source": "[email protected]",
      "type": "Secondary",
      "description": [
        {
          "lang": "en",
          "value": "CWE-416"
        }
      ]
    }
  ],
  "configurations": [
    {
      "nodes": [
        {
          "operator": "OR",
          "negate": false,
          "cpeMatch": [
            {
              "vulnerable": true,
              "criteria": "cpe:2.3:o:zephyrproject:zephyr:*:*:*:*:*:*:*:*",
              "versionStartIncluding": "2.4.0",
              "versionEndExcluding": "4.5.0",
              "matchCriteriaId": "00A2B469-12D7-40D8-BF4A-CEFDEB9DC72A"
            }
          ]
        }
      ]
    }
  ],
  "references": [
    {
      "url": "https://github.com/zephyrproject-rtos/zephyr/commit/c7292f20223637232b6f962141725611a38f6a52",
      "source": "[email protected]",
      "tags": [
        "Patch"
      ]
    },
    {
      "url": "https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-29xh-jm2m-4qvx",
      "source": "[email protected]",
      "tags": [
        "Exploit",
        "Patch",
        "Vendor Advisory"
      ]
    }
  ]
}