How we made our blog an exploit database
CVE-2024-38063 was the unauthenticated remote code execution bug in the Windows network stack that cost a lot of people a week last August. Here is its official description, in full:
Windows TCP/IP Remote Code Execution Vulnerability.
Six words and a link to the vendor.
I read all 350,192 published vulnerability records to find out how common that is. The typical one runs 38 words. The severe ones come in shorter than the mild ones. Fewer than one in a hundred says enough to test a machine against, and one in six of the links they point at have been dead for years.
That is our problem specifically. Our product checks whether a vulnerability is actually exploitable on your machines, and to do that it has to know what to send, when to skip a machine it cannot apply to, and what a patched machine sends back instead. The record almost never says.
Somebody always knows how it works
The patch could not have been written otherwise. The explanation comes out when a maintainer commits the fix and says what was wrong, when researchers argue about root cause on a mailing list, when somebody publishes a walkthrough. It exists. It is written by people, in prose, spread across the internet in places no database indexes.
Reading all of that is a full time job, and it has been ours for a while. Most of the posts on this site are what came out of it. Somebody works out how a bug functions and writes it down in plain language: what the code assumed, why the assumption was wrong, what an attacker does with it, and what you would see if they did.
So we pointed the app at our own posts
It works because of how we write them. A post saying a product has a server-side request forgery bug gives software nothing to do, and every feed on earth already says that much. A post saying the code checks the address and then throws it away before it makes the connection tells you the test is two different answers for one hostname, which is a sentence a machine can turn into a plan. The first time I ran it for real, it read our own post about an MLflow bug and came back describing the cause in almost the same terms the maintainer used in the patch. It had never seen the patch.
What comes out the other side is small: the false assumption, the steps in the order they have to happen, and what a defender would see at each one. The first two feed the exploit test. The third feeds something a defender can use directly: the process, the connection, the line in a log that means this actually happened to you, where the CVE description never said what to look for in the first place.
For the MLflow bug, that breakdown looked like this. The false assumption: validation runs against a URL, delivery runs against a fresh connection, and nothing carries the validated address forward, so a redirect or a second DNS lookup can send the real request somewhere the validator never checked. The steps, in order: register a webhook at an address that passes validation, fire the test call, let the redirect or the DNS rebind do the rest. What a defender would see: the tracking server's own outbound request landing on a cloud metadata address milliseconds after a validation call that resolved somewhere else entirely, the same pattern we already told readers to grep their access logs for in the post about that CVE.
A test that fails still leaves your security team something to go watch for. When a post does not actually explain the bug, the software returns nothing and a person picks it up. An empty answer costs somebody twenty minutes of reading. A confident wrong answer goes into a plan and tells a customer their machine is fine.
We almost graded our own homework
I found out the hard way that two sources counted as independent just because they had different names on them. Our own weekly threat digest and our own blog are one voice under two mastheads, and for a stretch the software let a post we had already written confirm a finding we had also already written, then treated the agreement as new evidence. Dozens of writeups got promoted on the strength of us agreeing with ourselves. It is fixed now: a source has to declare who actually stands behind it, separate from whatever byline sits on top, and two posts from the same voice cannot corroborate each other anymore. We are telling on ourselves here on purpose. If you are building anything that scores confidence by counting sources, ask how it validates the quality of those sources, and how it stops one source from getting counted twice, or from counting itself.
This is already a step behind
All of it came out of building what I still think of as the 2.5 engine, the version that proved a blog post could become a test, warts included. What replaced it does more, but the shape underneath has not moved: when a claim does not hold up, when a citation turns out to be us, when a post is too thin to test, it says nothing rather than guess. When it works, the page shows evidence.
The lessons seemed worth writing down anyway. It is also one of the reasons the product feels the way it does. When CVEasy tells you a vulnerability matters on one of your machines, the reasoning underneath it came from somebody sitting down and explaining how the bug actually works.