A single malformed WAP Push text message can crash com.android.phone, the process that runs calls and mobile service on Android, and drop whatever call is in progress — including an emergency call. The researcher who found it, Mark Blaszczyk, published the details as SMS of Death on 29 October 2026, after Google's vulnerability programme classified it as a non-security issue and closed it as "Won't Fix".
The twist is that the code has already been fixed. An AOSP commit titled "Fix remote DoS in decodeWapPdu" was written in June, and GrapheneOS says the fix is in the November security bulletin. This article explains how the bug works, why one message can keep a phone offline for days, what the patch changes, how to check whether your devices have it, and the Java lesson every parser author should take from it.
| Component | WapPushOverSms.decodeWapPdu() in AOSP frameworks/opt/telephony |
| Effect | Uncaught NegativeArraySizeException crashes com.android.phone |
| User interaction | None; no notification, no inbox entry |
| Tested on | Pixel 9 (April 2026 firmware), several Samsung Galaxy and A-series phones |
| CVE | None assigned |
| Google's VRP verdict | Non-security issue, "does not meet the severity threshold" |
| Upstream fix | AOSP commit 735d967, authored 15 June 2026 |
What is the SMS of Death bug?
It is a remote denial of service in Android's telephony framework: a crafted WAP Push message, sent as a binary data SMS, makes the WAP Push parser throw an exception nobody catches, and the phone process dies. All an attacker needs is the victim's number (researcher's write-up).
WAP Push is a mechanism from the WAP era for carriers to push configuration and service messages to handsets. Android still parses it in the telephony framework, outside any messaging app, which is why the crash happens before anything reaches an inbox and why changing your SMS app does nothing.
According to the write-up, the parser reads a WSP header length as a Java long, casts it to int without a range check and uses the result as an array size. A value just above Integer.MAX_VALUE turns negative, new byte[negative] throws, and because the exception is not one the surrounding code catches, it escapes on the telephony main thread.
Why one text message can keep a phone offline for days
Because the crash happens before the phone acknowledges the message, the network keeps redelivering it, and the phone keeps crashing on it. The damage is the retry loop, not the single crash.
The researcher reports one to two seconds without service per crash, carrier redelivery that repeated the crash for up to a week, about 20 messages leaving a test phone unusable for an extended period, and about 30 rapid messages corrupting the SMS database so the phone crashed on every boot (write-up, CyberInsider). A factory reset only helped until the carrier redelivered the queued messages; recovery meant moving the SIM to a non-Android phone so the messages were acknowledged, then cleaning the SMS store over ADB. He notes that eSIM devices would be harder to recover.
- Sender → Carrier SMSC: data SMS
- Carrier SMSC → Modem / RIL
- Modem / RIL → InboundSmsHandler
- InboundSmsHandler → WapPushOverSms
- WapPushOverSms → com.android.phone dies: uncaught exception
- com.android.phone dies → Carrier SMSC: no ack → redeliver
Did Google fix it? The AOSP commit says yes
Yes, in code: Google's VRP called it a non-security issue, but its telephony team committed a fix titled "Fix remote DoS in decodeWapPdu" on 15 June 2026, tracked as b/517376969 (AOSP commit).
The change is defensive rather than surgical. It widens the catch in decodeWapPdu() from ArrayIndexOutOfBoundsException to RuntimeException, so any malformed PDU becomes a generic SMS error instead of a crash:
- } catch (ArrayIndexOutOfBoundsException aie) {+ } catch (RuntimeException e) { // 0-byte WAP PDU or other unexpected WAP PDU contents can easily throw this; // log exception string without stack trace and return false.- Rlog.e(TAG, "ignoring dispatchWapPdu() array index exception: " + aie);+ Rlog.e(TAG, "ignoring decodeWapPdu() runtime exception: " + e); result.statusCode = Intents.RESULT_SMS_GENERIC_ERROR;The second half is the more interesting one. InboundSmsHandler now wraps message processing in a try/catch and, on failure, deletes the "poison" message from the raw table where pending SMS parts wait. That is what breaks the redelivery and boot-crash loop described above. The commit adds tests for malformed header lengths, header lengths longer than the PDU and decoder exceptions.
On the GrapheneOS tracker, GrapheneOS member thestinger wrote that the fix shipped in Android's security preview patches in mid-July, that GrapheneOS shipped it in its July preview releases, and that it is in the upcoming November bulletin. The October 2026 bulletin contains no entry for it.
| Date (2026) | Event | Source |
|---|---|---|
| 5 May | Reported to Google's Android & Google Devices VRP | write-up |
| 15 June | Fix authored in AOSP telephony (b/517376969) | commit |
| 20 June | VRP closes report as "Won't Fix (Infeasible)" | write-up |
| Mid-July | Fix in security preview patches; GrapheneOS ships it | GrapheneOS #9024 |
| 5 August | Cherry-picked fix committed by Android's build infrastructure | commit |
| 5 October | October bulletin, no entry for this bug | bulletin |
| 29 October | VRP final verdict: non-security; public disclosure | write-up |
| 2 November | November bulletin due (first Monday) | bulletin schedule |
Which Android phones are affected?
Assume any Android phone with a SIM is affected until it has the fix. The researcher confirmed a Pixel 9 on April 2026 firmware and several Samsung Galaxy and A-series phones, and Cyber Kendra reports his proof of concept targets Android 11 and later; nobody has published a full list of versions or OEM builds.
The fix lives in the telephony framework, so it reaches you through your phone maker's monthly update, not through Google Play. Pixels and GrapheneOS get it first; other vendors ship it on their own schedules, and devices that no longer receive security updates will not get it at all.
How to check a device's security patch level
Read ro.build.version.security_patch over ADB, or in Settings under Security, and compare it with the bulletin that lists the fix. For a fleet, your MDM reports the same field.
adb shell getprop ro.build.version.security_patch# e.g. 2026-10-05 -> October patch level adb shell getprop ro.build.version.release# Android version, for your inventoryDo not treat a November patch level as proof until the November bulletin is published and lists the issue. Bulletins come out on the first Monday of the month (schedule), which makes the next one Monday 2 November 2026. Each bulletin has two patch levels (-01 and -05); check which one carries the telephony fix once it is out.
The Java bug behind it: narrowing a long to an int
A cast from long to int in Java keeps only the low 32 bits (JLS §5.1.3), so a large length silently becomes a negative or small number. In a parser, that number then becomes an array size or a copy length, and the parser either throws or reads the wrong bytes.
This program shows the class of bug and its fix with a made-up 16-byte buffer. It contains nothing specific to SMS:
public class NarrowingDemo { // The bug class: a length decoded as a long, narrowed to int, used as an array size. static byte[] unsafeCopy(byte[] pdu, int offset, long declaredLength) { int len = (int) declaredLength; // silently wraps above Integer.MAX_VALUE byte[] header = new byte[len]; // negative len -> NegativeArraySizeException System.arraycopy(pdu, offset, header, 0, len); return header; } // The fix: check the range against what is actually left in the buffer, then narrow. static byte[] safeCopy(byte[] pdu, int offset, long declaredLength) { if (declaredLength < 0 || declaredLength > pdu.length - offset) { throw new IllegalArgumentException("header length " + declaredLength + " outside 0.." + (pdu.length - offset)); } int len = Math.toIntExact(declaredLength); byte[] header = new byte[len]; System.arraycopy(pdu, offset, header, 0, len); return header; } public static void main(String[] args) { byte[] pdu = new byte[16]; long hostile = 0xFFFF_FFF0L; // 4294967280, fits a long, not an int System.out.println("(int) " + hostile + " = " + (int) hostile); try { unsafeCopy(pdu, 2, hostile); } catch (RuntimeException e) { System.out.println("unsafe: " + e); } try { safeCopy(pdu, 2, hostile); } catch (IllegalArgumentException e) { System.out.println("safe: " + e.getMessage()); } }}$ java NarrowingDemo.java(int) 4294967280 = -16unsafe: java.lang.NegativeArraySizeException: -16safe: header length 4294967280 outside 0..14Two rules fall out of it. Validate a decoded length against the bytes actually left in the buffer before you allocate or copy, and narrow with Math.toIntExact), which throws ArithmeticException instead of wrapping. Then decide what happens to input you reject: Google's patch shows the second line of defence, catching broadly at the boundary of untrusted input and dropping the message so it cannot be retried forever.
The crash takes a second; the retry loop is what takes the phone offline for days.
Is SMS of Death a security vulnerability?
Google's programme says no: the VRP's final answer was that it "does not meet the severity threshold" (write-up). The researcher, and much of the coverage, disagree because the bug is remote, needs no interaction and can drop emergency calls.
Both things can be true. Bug bounty severity ratings are about payouts and bulletin entries, and a denial of service with no data exposure often scores low. But the engineers who own the code called their own commit a "remote DoS" fix and shipped it through the security preview channel. Cyber Kendra also notes that a similar WAP Push bug was handled as a security flaw in 2009 (CVE-2009-2999). For anyone who runs a fleet of phones that must make calls — field staff, on-call engineers, lone workers — treat it as a security update and schedule it like one.
What to do now
- To do: Inventory Android devices by
ro.build.version.security_patchand flag anything that no longer receives monthly updates. - To do: Watch the November 2026 Android Security Bulletin on 2 November and confirm which patch level lists the WAP Push fix.
- To do: Push the update to on-call, field and lone-worker phones first; they depend on calls working.
- To do: If a phone starts dropping service in a loop, use the researcher's recovery path: move a physical SIM to a non-Android phone so queued messages are acknowledged, then clean up over ADB.
- To do: In your own parsers, check decoded lengths against the remaining buffer and narrow with
Math.toIntExact.
Questions people ask about SMS of Death
What is the Android SMS of Death?
A zero-click bug in Android's WAP Push parser where one malformed data SMS crashes com.android.phone, the process that runs calls and mobile service. Active calls, including emergency calls, drop while it restarts.
Does SMS of Death need me to open a message?
No. WAP Push is parsed by the telephony framework before any messaging app sees it, so there is no notification, no inbox entry and nothing to tap.
Is there a patch for SMS of Death?
Yes. Google committed a fix to AOSP telephony on 15 June 2026, and GrapheneOS says it is in the November 2026 security bulletin. Phones get it through their maker's monthly security update.
Why did Google mark SMS of Death as won't fix?
Google's vulnerability reward programme classified it as a non-security issue that does not meet its severity threshold. That decision is about the bounty and bulletin process; the code fix exists separately.
Does it have a CVE?
No CVE had been assigned as of 30 October 2026, and the October bulletin has no entry for it.
Can I disable WAP Push on Android?
Not through any user setting. Until a device is patched, filtering malformed WAP Push messages has to happen in the carrier's network.
Are iPhones affected?
No. The bug is in Android's AOSP telephony code, and the researcher's recovery method relies on a non-Android phone acknowledging the queued messages.
Sources and further reading
- SMS of Death: zero-click Android telephony DoS — Mark Blaszczyk's write-up
- AOSP commit 735d967: Fix remote DoS in decodeWapPdu
- GrapheneOS os-issue-tracker #9024
- Google Issue Tracker 509520497 (may require sign-in)
- Android Security Bulletins overview and schedule
- Android Security Bulletin, October 2026
- CyberInsider coverage and Cyber Kendra coverage
- Java Language Specification §5.1.3, narrowing primitive conversion
- Hacker News discussion
Discussion
Join the discussion
Sign in with Google, Apple or an email code to comment and reply.