```html ```
top of page

Six Times in Five Years, CISA Has Listed a Bug Whose Only Job Was Defeating the Fix for the Last One. Two of Them Landed in the Same Week.

  • Writer: Patrick Duggan
    Patrick Duggan
  • 1 day ago
  • 6 min read

Updated: 5 hours ago

I went looking for something small this morning and found a number worth publishing.


Of the 1,671 entries in CISA's Known Exploited Vulnerabilities catalogue, exactly six describe a vulnerability whose existence is the failure of a previous patch. Not a new bug in the same product. Not a variant. A bug that exists specifically because somebody's fix did not hold.


Six. Out of 1,671. 0.36 percent.


Here is the entire list, and it is a hall of fame:


KEV listed

CVE

Product

What it was

2021-11-03

vBulletin

incomplete patch for CVE-2019-16759

2021-11-03

Apache HTTP Server

incomplete patch for CVE-2021-41773

2021-11-03

DotNetNuke

incomplete patch for CVE-2018-15811

2023-05-01

Apache Log4j2

incomplete fix for CVE-2021-44228

2026-07-27

Fortinet FortiOS

bypasses the patch for symlink persistence

2026-08-03

N-able N-central

result of an incomplete patch for CVE-2026-18556



Look at the dates in the bottom two rows. Seven days apart.


Against a base rate of roughly one every ten months, we just got two in a week. And that undercounts it, because there is a third one running right now that cannot appear on this list — I will come back to that.




Why the second bug is worse than the first



This is the part that matters and almost nobody says it plainly.


When a vulnerability is disclosed, defenders are afraid. They read the advisory, they check whether they are exposed, they schedule the patch, they watch the logs. Fear is a defensive asset and disclosure generates it for free.


When the patch ships, the fear is spent. The ticket closes. The asset moves from "vulnerable, tracked" to "patched, done." The scanner stops flagging it. Nobody is watching that box any more, because watching it was the cost of not having patched it, and you patched it.


Then the bypass drops.


Now every organisation that did the right thing is exposed, and every one of them believes it is not. The defensive posture after a failed patch is strictly worse than the posture before the original disclosure, because the first time around you at least knew you were in trouble. The second time you have a green tick.


Log4j is the canonical proof. Everyone remembers CVE-2021-44228 — Log4Shell, the worst weekend of that December. Far fewer remember CVE-2021-45046, the one that landed days later because the first fix was incomplete: the Thread Context Lookup path was still reachable. Teams that had sprinted through a weekend to patch 44228 and gone home had to be dragged back in. Some were not dragged back in, which is why that second CVE is on the KEV list at all — it was exploited in the wild against people who genuinely believed they had already handled it.


Apache HTTP the same. CVE-2021-41773 was path traversal. The fix was insufficient. CVE-2021-42013 was the same hole, reopened, and it got its own KEV entry because attackers went straight back through a door everybody had just watched being nailed shut.


The third one, which does not appear on the list



On 12 August 2026, a researcher publishing as Nightmare Eclipse released a working proof of concept called ShieldBreak: a local privilege escalation to SYSTEM through Microsoft Defender, and a functional bypass of the RoguePlanet patch (CVE-2026-50656) that Microsoft shipped in July.


Same shape as every row in that table. A fix that closed one path into a class rather than the class.


It is not in the KEV catalogue. It cannot be, and the reason is instructive: there is still no patch. Microsoft acknowledged it, said it is investigating, shipped nothing in the August Patch Tuesday cycle, and has committed to no timeline. Meanwhile Defender's own scan engine started failing — quick and full scans stopping, offline scans hanging at 90 to 93 percent — in a window that lines up with the mitigation attempt, though Microsoft has not stated a cause and I am not going to assert one.


So the honest count for the last four weeks is three patch bypasses on actively exploited software, against a five-year base rate of six.


What I am not claiming



I am not claiming vendors are getting worse at patching. Six data points across five years cannot support that, and I would be embarrassed to publish it. n=6 is an anecdote with a spreadsheet.


I am also not claiming this is a trend. Two in a week could be exactly what randomness looks like at this base rate — clustering is what random events do, and the human eye is famously terrible at accepting that.


What I will claim, because it follows from the definition rather than the sample size:


A patch bypass is the single highest-leverage bug class that exists, because it arrives precisely when the target population has stopped looking. The attacker gets a pre-built list of exposed hosts — everyone who applied the patch is, by definition, someone who was running the vulnerable product — combined with a defender who has already filed the incident as closed.


That is true whether it happens six times or six hundred.


Why patching an auth bypass is genuinely hard



It is worth being fair to the vendors here, because "they shipped a bad patch" is a lazy read and mostly wrong.


Look at what the two 2026 entries actually are. N-able N-central: authentication bypass using an alternate path or channel. Fortinet: a bypass of the mitigation for a symlink persistence mechanism. ShieldBreak: privilege escalation through a security agent that must run with enormous privilege in order to function at all.


Each of those is a bug where the vulnerable behaviour is a legitimate capability being reached the wrong way. You cannot delete the capability — N-central needs alternate authentication paths, FortiOS needs symlinks, Defender needs to touch every file on the system. The fix has to distinguish authorised use from unauthorised use of a mechanism the product requires. That is a policy problem wearing a memory-safety costume, and policy problems have edges that a patch author has to enumerate by hand.


Enumerating them by hand is how you miss one.


We nearly shipped one ourselves today



I would not publish the above without this part, because we spent this morning inside exactly the same failure mode.


Yesterday we published a finding about our own free-tier registration gate: it had four abuse controls, and every one of them silently skipped IPv6, because a prefix function returned null on any address containing a colon. Twenty-two percent of our signups walked past a gate that was not looking.


Today we fixed it. And the fix had a trap in it that would have made it an incomplete patch of the exact kind this post is about.


IPv6 text is not canonical. These three strings are one address and share no common prefix:


2600:381:c648:93c0::1 — 2600:0381:c648:93c0:0:0:0:1 — 2600:381:C648:93C0::1


Our velocity and burn checks compare with a string prefix match. A naive IPv6 port — the obvious one, the one that looks right in review — would have compiled, deployed, reported success, and matched nothing, forever. A gate that evaluates zero addresses while logging that it ran. We would have closed the ticket, published that we closed it, and been in a worse position than before, because now we would believe it was handled.


The fix normalises both the query prefix and every stored record to full 32-nibble form before comparing, and we tested it against the real cluster in our own table before it shipped: four keys from one residential /64 that previously counted as zero now correctly trip the velocity threshold.


That is not a humblebrag. It is the same bug as the table above, caught by luck and a habit of testing the thing rather than the intention, and it is why I think the vendors in that list deserve less contempt than they usually get.


What to actually do



Do not close the ticket when the patch lands. Close it when you have verified the specific behaviour is gone. Those are different events and the gap between them is where this entire bug class lives.


Keep the asset on the watch list through one full cycle after remediation. The bypass, when it comes, comes within days to weeks of the original fix — Log4j was days, ShieldBreak was about four weeks. That window is when you have stopped looking and the attacker knows it.


Treat "incomplete patch for CVE-X" in an advisory as a severity multiplier, not a footnote. It means the exposed population is precisely the set of organisations diligent enough to have patched, which is a better target list than any scanner produces.


And when you fix something, test the fix against real data, not against your intent. Every entry in that table was written by someone who was sure they had fixed it.


Sources



CISA Known Exploited Vulnerabilities catalogue, 1,671 entries as of 2026-08-20. The six figure is our own count over the full catalogue text, reproducible by anyone: pull the catalogue and match descriptions for incomplete-patch and patch-bypass language.


The Hacker News, BleepingComputer, Arctic Wolf and Malwarebytes on ShieldBreak and CVE-2026-50656 (RoguePlanet), August 2026.


Our own IPv6 gate finding and fix are documented in the preceding post and in commit history.




If you have a patch bypass in your own history — one where the fix did not hold and you found out the hard way — I would genuinely like to hear it. That is a story people do not tell and it is the one that would help most. Rate this post below.





Her name was Renee Nicole Good.


His name was Alex Jeffery Pretti.

 
 
 

Comments

Rated 0 out of 5 stars.
No ratings yet

Add a rating
bottom of page