Unauthenticated NaN Injection via MAVLink PARAM_SET in ArduPilot ArduPlane
| CVE | CVE-2026-36522 |
| CWE | CWE-1287 (Improper Validation of Specified Type of Input) |
| CVSS 3.1 | 9.1 Critical — AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H |
| Affected | ArduPilot ArduPlane 4.0.1 (confirmed) |
| Component | GCS_MAVLINK::handle_param_set() — libraries/GCS_MAVLink/GCS_Param.cpp |
| Vector | Remote, unauthenticated MAVLink |
| Impact | Denial of service (SITL) / silent flight-parameter corruption (hardware) |
| Reporter | Sebastien Arseneault, Deep Woods Security |
handle_param_set() accepts an IEEE 754 floating-point value from an
unauthenticated MAVLink PARAM_SET message without validating it for NaN or
infinity. The malformed value reaches a floating-point comparison
(is_equal<float,float>() in AP_Math.cpp) with no type or value check.
This is not a code-execution vulnerability. The impact is denial of service and integrity corruption.
- SITL / builds with FP exceptions enabled: the NaN triggers a floating-point exception (SIGFPE) and the autopilot process aborts — denial of service.
- Production hardware (STM32/Pixhawk), where FP exceptions are disabled: the malformed value is stored silently into a flight-critical parameter, with no crash and no operator-visible warning. This is the more dangerous case: corrupted flight parameters propagate into control math with no indication to the operator.
The validation gap is in the common parameter handler, so all float-typed parameters are affected.
A single unauthenticated PARAM_SET carrying a quiet NaN (0x7FC00000)
targeting ARSPD_FBW_MIN:
python3 poc/CVE-2026-36522.py [host:port] # default tcp:127.0.0.1:5760
Captured SITL stack trace (stacktrace.txt) showing the
external input reaching the unguarded comparison:
#6 is_equal<float, float> (v_1=nan(0x400000), v_2=0) at AP_Math.cpp:35
#7 GCS_MAVLINK::handle_param_set ... at GCS_Param.cpp:299
packet = {param_value = nan(0x400000), param_id = "ARSPD_FBW_MIN", param_type = 9}
The call chain (update_receive -> packetReceived -> handle_common_message
-> handle_param_set) confirms the path is reachable from unauthenticated
network input.
Validate the incoming value before use:
if (isnan(packet.param_value) || isinf(packet.param_value)) {
// reject: value out of range
return;
}| Date | Event |
|---|---|
| 2026-02-26 | CVE request submitted to MITRE |
| 2026-02-26 | Vendor notified (ArduPilot) |
| 2026-06-15 | CVE-2026-36522 assigned; PoC and stack trace published |
Sebastien Arseneault — Deep Woods Security