CVE-2026-13213: Bluetooth HAS: NULL-pointer dereference DoS when a bonded peer reconnects before bt_has_register
The Hearing Access Service (HAS) GATT server in subsys/bluetooth/audio/has.c installs a connection-callback set unconditionally via BTCONNCBDEFINE, so securitychanged() runs for every connection that establishes security even before the application has called bthasregister(). The service attribute pointers hearingaidfeaturesattr, presetcontrolpointattr, and activepresetindexattr remain NULL until bthasregister() resolves them and sets has.registered.
With CONFIGBTSETTINGS, settingssetcb() restores each bonded client's persisted context at boot and unconditionally sets context->flags to BONDEDCLIENTINITFLAGS (non-zero). When a previously bonded peer reconnects and re-establishes security during the startup window before bthasregister() has been called, securitychanged() sees the non-zero flags and schedules notifyworkhandler, which calls btgattissubscribed() with a still-NULL attribute pointer. That triggers an assertion (ASSERT(attr, ...) in btgattissubscribed()), or a NULL dereference of attr->uuid when assertions are compiled out.
The result is a remotely triggerable (Bluetooth, adjacent) crash of the HAS peripheral. Exploitation requires the peer to have previously bonded with the device and to reconnect within the boot-time race window before the application registers the service; a peer that reconnects persistently can prolong the outage. Impact is denial of service only, with no memory corruption or information disclosure.
The fix adds an early if (!has.registered) { return; } guard in securitychanged(), so no notification work is scheduled until the GATT service is registered and its attribute pointers are valid.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Configuration
In has.c, update security_changed() to immediately return when the HAS service has not yet been registered (i.e., add an early guard: if (!has.registered) { return; }). This prevents notification scheduling (including bt_gatt_is_subscribed) until bt_has_register() has resolved attribute pointers.
Zephyr Bluetooth HAS GATT server (subsys/bluetooth/audio/has.c) guard in security_changed() = if (!has.registered) { return; }
Event History
Frequently Asked Questions
Which deployments are exposed to this crash condition?
HAS GATT server deployments using CONFIG_BT_SETTINGS are exposed when persisted context for a previously bonded peer is restored. The affected peripheral must receive a reconnection from that bonded peer during startup before the application calls bt_has_register().
What must an attacker be able to do?
The attacker must be a previously bonded Bluetooth peer and be within Bluetooth range of the peripheral. They must reconnect and re-establish security during the window before HAS registration completes.
What is the operational impact if exploitation succeeds?
The HAS peripheral crashes due to an assertion in bt_gatt_is_subscribed(), or a NULL-pointer dereference when assertions are compiled out. The reported impact is denial of service; no confidentiality or integrity impact is indicated.