Security firm Calif disclosed research on 8 September 2026 into a memory corruption flaw in WeChat's VoIP stack, affecting the app on both iOS and Android. The write-up is published at calif.io/research/weworm.
The bug itself takes one line to describe: memory corruption in the code that handles voice and video calls. What makes it worth a longer look is when it fires, and what the researchers built on top of it.
It runs while the phone is still ringing
This is zero-click in the strictest sense of the phrase. The victim does not answer.
The exploit fires during the ringing phase — in the window between the notification appearing and the user reaching for accept or decline. The call-handling code has already parsed attacker-controlled data by the time a person has registered that the phone is buzzing.
Declining does not help. Declining is a decision taken after the code has already run.
That detail deserves a moment, because almost every piece of practical phone-security advice ordinary people have been given ends at "do not answer calls from people you do not know". Here that instruction is not merely insufficient. It is aimed at a moment that arrives after the compromise is finished.
The Pegasus cases had the same property: by the time there was anything for the target to react to, there was nothing left to react to.
The precondition is not a limitation. It is the routing table.
There is one requirement. The attacker must be in the victim's friend list.
Read cold, that is a constraint, and it is exactly how a precondition like this normally gets reported: serious flaw, but you have to already be a contact, so the blast radius is bounded.
Calif's description of how it propagates is the reason it is not bounded:
"Attacker calls victim, victim becomes attacker, victim calls the next victim."
Every account that falls hands over something the original attacker never had — a fresh list of people who have already authorised it. The precondition is satisfied for free at every hop, by the definition of the hop. What looks like a fence around the first victim is the routing table to the second.
That is what makes this a worm rather than an exploit. The requirement that appears to limit spread is the thing that produces spread.
It also inverts the usual mitigation. Normally a contact-list precondition means the sensible advice is do not accept requests from strangers. Here the danger arrives from people you deliberately added years ago, whose accounts are behaving exactly as the app intends.
Two days for the exploit, one more week for the worm
Calif's own account of how it was built, verbatim:
"Working with AI, our team found the bug and wrote the first remote code execution (RCE) exploit in about two days. Building the worm took one more week."
Nine days end to end, from nothing to a self-propagating remote code execution chain against an application with more than a billion users.
Apply whatever discount you think appropriate — this is a research firm describing its own work, with the technical detail withheld. But the direction the figure points is the same one that keeps turning up in every measurement anyone publishes: the cost of turning a memory corruption bug into a working chain is falling, and it is falling fastest for people who already knew how to do it slowly. Forescout's number for porting a PLC exploit was eight hours and 536 dollars. Same curve, larger target.
Three handsets
The demonstration used three test devices. That is the entire observed spread.
No real-world attack has been reported. No victims. The technical details are withheld pending a conference talk.
So the honest framing is narrow: a worm that works, proven at a scale of three, against a platform of a billion. Nobody outside Calif can independently verify the chain, and nobody should be describing this as an incident.
Reported in July, mitigated in August, no CVE ever
| Date | Event |
|---|---|
| 24 July 2026 | Reported to Tencent |
| 21 August 2026 | Mitigation ships — Android 8.0.77, iOS 8.0.76 |
| 28 August 2026 | Full mitigation confirmed |
Four weeks from report to shipped fix on both platforms is a good response by any standard, and it should be said plainly.
And there is no CVE. There will not be one.
That is not an oversight. CVE identifiers exist so independent parties downstream — distributors, integrators, scanner vendors, asset owners — can refer to the same defect without ambiguity. Tencent runs the client and the server. There is no downstream. Nobody needs a shared name for a defect that exactly one organisation can patch.
The consequence is worth stating flatly: this vulnerability will never appear in a vulnerability database. If the way your organisation learns what is wrong with the software its staff carry is a feed of CVEs, this one was invisible to you from the day it was reported to the day it was fixed, and it is invisible now.
That is a structural gap rather than a WeChat one. Every application where a single company owns both ends has the same property, and the list of those applications is most of what is on a modern phone.
What to do
- Confirm WeChat is on Android 8.0.77 or iOS 8.0.76 or later. That is the whole fix, and it has been out since late August.
- Stop treating messaging-app updates as cosmetic. The most valuable surface on a phone is the code that runs before the user makes any decision at all.
- Prune contact lists on any app where a contact is a permission. Here, being in the list is the entire precondition, and old entries carry the same weight as new ones.
- Retire the advice about not answering unknown calls as a control for this class. It is aimed at the wrong moment.
- Add a non-CVE source to your vulnerability intake. Vendor release notes for the apps your people actually use will catch things the databases structurally cannot.
What is not established
- The technical detail. Withheld until the conference talk.
- Whether it was ever used against anyone. No real attack reported.
- How reliable the chain is outside three controlled handsets.
- What the mitigation actually changed. Tencent has published nothing.
- Whether the same code path holds other reachable bugs — the usual question once a VoIP stack is shown to be reachable before the call is answered.

