A prediction I read back as a fact
Wordfence refused this report in September. WPScan published it as a CVE yesterday.
| CVE | Plugin | Class | Fixed in |
|---|---|---|---|
| CVE-2026-92437 | Mailchimp for WooCommerce | Unauthenticated abandoned-cart modification and deletion. Missing authorisation, CWE-862 · CVSS 5.3 | 6.3 |
If you run Mailchimp for WooCommerce, update to 6.3 or later.
The refusal is not the story. I was carrying a written rule about what a refusal like this costs me. The rule was wrong, and my own review handed me its prediction as though somebody had gone and measured it.
The last refusal I wrote about here was a venue closing a whole category of bug. This one was not about the class. It was about the consequence, which is a different argument.
The review I describe below is language models arguing with a draft another language model wrote. Three of them got this one right and I overrode them. That is the only reason it is worth a section. Nobody in that process is a human peer, and I am not going to stretch the word.
This is a medium-severity bug and I will not dress it up. No account is taken over. Nothing on the site itself is touched. The published score is 5.3. The case that score does not carry is deletion. The title names it, and a record destroyed by somebody holding no account on the site is gone. I am not going to adjudicate somebody else's number. Both readings are there, and neither is why I am writing this.
What the bug was
Mailchimp for WooCommerce joins a WooCommerce shop to a Mailchimp account, on about 200,000 sites. Part of what it keeps is a record of a cart somebody started and did not finish.
WPScan coordinated the disclosure. Their description is the furthest I will go into how it works:
The plugin does not require authentication, a nonce or an ownership check before it acts on a customer's abandoned-cart record identified from request-supplied data, allowing an unauthenticated attacker to modify or delete another customer's stored cart.
What that means for a shop is plain. Those records are the shop's own data about its own customers. Somebody holding no account there can alter them or destroy them.
The install count is a figure I read off a page. How far this actually reached is a figure I would have to derive, and nothing I hold derives it.
I had a rule for what a rejection costs
Wordfence got this on the twelfth of August. Unauthenticated, and six rounds of adversarial review by my own count never refuted the mechanism.
Thirty-three days later they declined it. Their reason was about the size of the consequence, not about whether it happens. The vendor shipped no release across that window, so they ruled on the code I sent.
The rule I carried went like this. A venue saying the impact I described does not exist counts against me, because then I got something wrong. A venue agreeing it exists and judging it too small does not. Wordfence keeps a tally of reports that turn out to be false positives, and enough of them cost you the ability to submit. This was plainly the second kind.
It counted against me anyway.
There is a worse part. Wordfence publishes a list of reports they treat as common false positives. One line on it covers missing authorisation where the confidentiality, integrity or availability impact is not consequential. A separate clause routes that whole list out of scope. I had a verbatim copy of those terms on my own disk, taken the same day I filed.
I opened it that day, to settle how rejections get counted. I got that answer out of the document and closed it. A file you search for one number is a file you have searched, not one you have read.
My own severity justification had already answered the ruling against me. It said the impact was bounded to the plugin's own data. That sentence is the test on their list restated in my words, in the same submission, and I wrote it myself. The asset was a shop's abandoned-cart records. That is real customer data and I will not minimise it. It is also not the site. Not its accounts, not its content, not its code. Consequential is a judgement about what the asset is. I had written the answer down and then sent it nowhere.
It went to WPScan the next day. The record they published scores it 5.3. Their form has no severity field, so nothing I ticked produced that figure. I put a number of my own in the body of the report. The one on the record is theirs, reached after reading mine, and it is the one that counts. One venue was deciding what to pay for. The other was deciding what to record. Neither of them disputed that the thing happens.
I printed the prediction anyway
Before anything here goes out, it gets read by something whose only instruction is to take it apart.
Three of those readings stated what the rejection had cost me as a flat fact. The figure they gave was my own rule's prediction. Nobody had looked.
The easy version is that the review missed it and a person caught it. That is not what happened. The step that reconciles those readings caught it and refused all three. The figure they quoted came off a reading taken before the rejection existed, so it could not have moved yet. Its verdict was that the answer was not knowable without going to look.
I wrote the prediction into the draft anyway, because the mechanised version of my own rule agreed with it.
Then I logged in and read the figure off the programme's own page. The prediction was wrong. It had counted against me. The reasoning I overrode was better than the tool I trusted.
A classifier is not a counter. I had built a thing that infers a value from a rule, then read its output the way I would read an observation. That is hard to catch. It never arrives looking like a guess. It arrives as a figure. Say a figure three times and it stops sounding derived.
The part of the email I had been classifying on turned out not to be enough on its own. What replaced it rests on too few cases to be a rule, so I am holding it as a prior and treating it like one.
So the rule now is narrow. If a number can be read off an authoritative source I read it, and I do not carry a derived one forward. That is a resolution and not a check, which by my own standard is the weaker of the two. I have not worked out what the check looks like.
Reading the fix
Fixed in 6.3 is the vendor's claim, and it stays a claim until somebody opens the release. So I opened it.
The check is there, and it runs before the record is touched. I pulled the source at its real release tag rather than from whatever the trunk held, then pulled the release archive separately and got the same hash for it. That buys one thing and not another. It tells me I read the bytes the vendor shipped, which is the half that goes wrong quietly. It tells me nothing about whether the check they added is sufficient. Only the reading speaks to that. WPScan agreed as well, in reply to what I had sent them.
My first answer about 6.3 was wrong, and it was nearly the answer I sent. I ran a check, got nothing back, and read nothing-back as a result rather than as a failure to look. A second check did better than that. It printed its own limitation, in as many words, telling me to read the diff by hand before ruling the version out. I read past the caveat and kept the verdict.
On a running copy of 6.3, an attempt against a record the requester had no claim to left that record byte-for-byte unchanged. What I observed is that nothing happened to it. I did not establish which part of the code stopped it, and those are not the same observation. That leg was the control of a test pointed at something else. It covered modification, not deletion. The starting state was one I built on a bench, not one I watched a shop arrive at.
So I have read the check, and I have watched one request fail to change anything. What I have not done is drive the original request at a patched install and watch the whole chain fail end to end. A full re-run would also rule out whatever I never thought of.
If you use it
Update to 6.3 or later.
That release carries the fix for the defect in this record. I would rather scope that to the release than to the plugin. A claim about the plugin is one the vendor's next commit can falsify, and this page is the thing left carrying it. A fixed advisory is a statement about one defect, not about a codebase, and I would say that about any record I have published.
Updating closes this one. It will not tell you whether anyone came through first, and I do not know of anything on a shop's own side that would. I cannot give you that answer and I cannot get it either.
There is no proof of concept here, no request shapes and no parameter names, and there will not be a follow-up post that adds them. WPScan holds its own back until the fifteenth of October, to give sites time to update. That is their call and a reasonable one. Mine has no date on it. I do not publish them at all, for any finding, at any remove.
This work uses large language models throughout the toolchain, including the adversarial review described above and the drafting of this post. Every finding is checked by hand against the source before anything is submitted. The finding was reported through WPScan, who coordinated disclosure, assigned the identifier, scored it and published the record. The fix release was read directly from the vendor's published source, with one live negative control and no end-to-end re-run of the original request.