An AI-generated CVE is a vulnerability record whose technical content was written by a language model and published without anyone reproducing it. It looks exactly like a real advisory: an affected version range, a named function, specific line numbers, a CVSS score. Every field is well formed. None of it is true.
On July 27, 2026, six CVEs were published against SQLite 3.41. Two carried a CVSS score of 9.8. They described use-after-free bugs in expression evaluation, in the parser, and in the JSON module, which is the class of memory-safety failure that, in a library embedded in nearly every phone, browser, and operating system in use, would make for a very bad week across a very large number of organizations.
On July 30, the security research team at JFrog published an analysis showing that the bugs did not exist. On July 31, all six records were rejected.
Four days from publication to withdrawal is a fast correction by the standards of vulnerability management, and everyone involved in making it happen deserves the credit. The interesting part is not that the system recovered. It is what the recovery cost, and what the whole episode says about the difference between a claim and a finding.
Key takeaways
- Six SQLite CVEs published on July 27, 2026, two of them rated 9.8 critical, were fabricated. All six were rejected on July 31.
- The tells were structural, not subtle: a function that did not exist in the named version, line numbers past the end of the file, and proof-of-concept payloads that crashed nothing.
- Every one of those checks required a human being to open the source and read it. Producing the advisories cost close to nothing. Refuting them cost expert hours.
- Corrections propagate more slowly than claims. As of August 3, 2026, the six records are marked Rejected at NVD while GitHub's Advisory Database still serves them, unwithdrawn, at their original severities.
- A CVSS score is an assertion about a bug. It is not the bug. Anything downstream that acts on the label rather than the behavior inherits whatever the label got wrong.
- The defense is not distrust of automation. It is insisting that a finding come with something you can run again.
What gave them away
The forensics are worth walking through, because the failure signature is specific and it will recur.
CVE-2026-51302, one of the two rated 9.8, described a use-after-free in SQLite's expression evaluation logic and located it in a function called exprComputeOperands(). As JFrog put it: "The primary issue here is that exprComputeOperands() didn't exist in SQLite 3.41." The function was not renamed or refactored. It was never there.
CVE-2026-51296 placed its bug in src/json.c at lines 3555 through 3575. "In version 3.41.0, src/json.c is only 2706 lines long," the analysis notes. "The cited line numbers don't exist." The advisory pointed past the end of the file.
Where proof-of-concept payloads were supplied, running them produced no crash. And the advisories cited no commit, no pull request, and no maintainer acknowledgement, because there was nothing to cite.
SQLite's maintainers have since added all six to the project's own vulnerability page under a heading that does not mince words: "Not a bug in SQLite. These are unreproducible. They appear to be AI hallucinations."
This was also not a one-off. JFrog went back through the rest of the submissions from the same account: "A broader audit of 55 advisories published by the same GitHub account revealed that 54 were completely fabricated, while one contained a real bug wrapped in unverified CVE metadata." One in fifty-five had a real bug inside it, and even that one arrived dressed in details nobody had checked.
The process did its job. Look at what the job cost.
It is tempting to read this as an indictment of the CVE system, and that reading is too easy. The system was never a verification service. It is a naming and coordination scheme, and it assumes good-faith submissions because for most of its history producing a plausible-looking advisory required someone who understood the code well enough to lie convincingly about it. That was the natural rate limiter, and it was never written down anywhere, because nobody needed to write it down.
That rate limiter is gone. Generating a well-formed advisory with a named function, a version range, a line number, a severity vector, and a confident technical narrative now costs a few seconds of inference. Refuting one still costs what it always cost: somebody who knows the codebase opening the file, checking whether the function exists, counting the lines, and running the payload.
The asymmetry is the whole story. The claim got cheaper by orders of magnitude. The verification did not get cheaper at all.
So the four-day turnaround is genuinely good news and also not a repeatable defense. It happened because SQLite is one of the most scrutinized pieces of software ever written, because a well-resourced research team decided to spend time on it, and because the fabrications were sloppy enough to disprove quickly. Change any of those three and the timeline stretches. Most projects have none of them.
The retraction has not travelled as far as the claim
There is a second-order effect here that is easy to miss, and it is the reason a withdrawn CVE is not the same thing as a resolved one.
As of August 3, 2026, all six records are marked Rejected at MITRE and in the National Vulnerability Database, carrying the standard notice: "DO NOT USE THIS CVE RECORD." The metadata has been stripped. That is the system working exactly as designed.
In GitHub's Advisory Database, on the same date, the same six records are still published. None is marked withdrawn. They still carry their original severities, including two at 9.8 critical and one at 9.1. Their last-modified timestamps read July 27 and July 28, which is to say they have not been touched since before the analysis that debunked them.
Two things are worth saying plainly about that. The first is that this is propagation lag, not negligence, and it will very likely be resolved shortly after this is published. The second is that the blast radius is narrower than it sounds: these are unreviewed advisories, imported automatically from the national database rather than curated by GitHub's security team. They carry no affected-package ranges, and Dependabot does not raise alerts from them. Nobody is being handed a pull request to patch a bug that was never there.
But they are still served, by the web interface and by the API, to anything that looks up those CVE identifiers. And looking up a CVE identifier is precisely what an automated triage step does. The correction reached the authoritative record in four days and had not reached one widely-read mirror in seven. Claims move at machine speed. Corrections move at human speed, and then wait in a queue.
What this does to an automated fix loop
Now put an agent in the middle of it.
The current enthusiasm in application security is for closing the loop: a tool reports a finding, a coding agent reads it, writes a patch, and opens a pull request. It is a genuinely good pattern and it is where a lot of the industry is heading, this company included. It also has a specific and underexamined dependency, which is that the finding going in has to be about something real.
JFrog spelled out the consequence: "An AI agent that encounters a fabricated CVE may attempt to locate the vulnerable function, generate a patch, or recommend changes based on code that does not even exist."
Consider what that actually looks like. An agent is handed CVE-2026-51302 and told to remediate a critical use-after-free in expression evaluation. It goes looking for exprComputeOperands(). It does not find it. A well-built agent reports that it cannot locate the function and stops, which costs you a triage cycle and some goodwill. A less careful one does what language models do when reality does not match the prompt: it finds the nearest plausible thing, decides that must be what was meant, and edits it. Now there is a pull request against working code, justified by a critical CVE, sitting in front of a reviewer who has forty other things to do and a severity score that says this one is urgent.
The failure mode is not that the agent is bad at its job. It is that the agent was given an assertion where it needed an observation, and an assertion is not something you can check by looking harder at the code.
A claim and a reproduction are different objects
It is worth being precise about what separates the two, because the distinction is usually collapsed into a vague preference for "high quality data."
| A severity label | A reproduced finding | |
|---|---|---|
| What it asserts | That a flaw exists somewhere, described in prose | That this specific request produced this specific response, on this target |
| How you check it | Read it and judge whether it sounds right | Run it again |
| Cost of a convincing fake | Seconds of inference | You would have to actually make the system behave that way |
| What a consumer receives | A score and a narrative | The exchange itself, replayable |
| When it is wrong | Wrong quietly, and stays wrong until a human intervenes | Fails to reproduce on the next run |
| What an agent can do with it | Trust it, or refuse to act | Verify it, fix it, then confirm the fix by rerunning |
The row that matters is the last one. An agent handed a label has exactly two options, both bad: take it on faith, or escalate everything to a human and give up the leverage that made the loop worth building. An agent handed a reproducible exchange has a third option, which is to check.
Where this leaves us
NightVision is a dynamic scanner, which means we do not get to stand outside this problem and comment on it. We consume CVE feeds like everyone else. We ship detection templates keyed to specific CVEs, including a template for the Next.js middleware bypass. A poisoned advisory feed is our supply chain too.
What keeps that from becoming our customers' problem is a rule that predates all of this: a check earns its place by firing against a running target. A template that cannot demonstrate the behavior on a live application does not become a finding, because there is nothing to demonstrate. That is not a clever defense against AI-generated advisories. It is just what dynamic testing is, and this episode happens to be a very clear illustration of why the discipline is worth keeping.
The same principle governs what comes out the other side. A NightVision finding carries the HTTP exchange that produced it, retained and replayable, with a curl reproduction the reviewer can paste into a terminal. On API findings discovered from source, it also carries the file and line the vulnerable route came from, which is a fact about your repository rather than a guess about it. When an agent fixes something over our MCP server, the closing move is a rescan: the same request, run again, against the patched application. Not a claim that the issue is resolved. A demonstration that the behavior is gone. The merge is still a human decision, and it should be.
None of that makes a finding true by decree. It makes it checkable, which is the only property that survives contact with an adversary who can generate infinite plausible text.
Related readingPart of our series on modern application security testing. Start with What You Should Know About Application Security Testing, then read From Runtime Finding Back to the Line That Caused It on why reproducibility is the property that makes a finding actionable, and Autonomous Penetration Testing: A CISO Reality Check on evaluating security claims that arrive with AI attached.
Frequently asked questions
What is an AI-generated CVE?
An AI-generated CVE is a vulnerability record whose technical content was produced by a language model and published without anyone reproducing the issue. It typically contains a plausible affected version range, a named function, specific line numbers, and a CVSS severity vector, all correctly formatted. The giveaway is usually that the cited code does not exist in the named version, that line numbers fall outside the file, or that the supplied proof of concept does not reproduce.
Which SQLite CVEs were fabricated?
Six records published on July 27, 2026 were fabricated: CVE-2026-51296, CVE-2026-51297, CVE-2026-51300, CVE-2026-51302, CVE-2026-51303, and CVE-2026-51304. Severities ranged from 7.5 to 9.8. JFrog's security research team published an analysis on July 30, 2026 showing the bugs did not exist, and all six records were rejected on July 31, 2026. SQLite's own vulnerability page lists them as unreproducible and describes them as AI hallucinations.
Does a rejected CVE disappear from vulnerability databases?
Not immediately, and not everywhere at once. A rejection is recorded at MITRE and reflected in the National Vulnerability Database, but downstream mirrors, vendor feeds, and internal scanner databases update on their own schedules. During that window the same identifier can be marked rejected in one authoritative source and still served at its original critical severity by another, which is why any pipeline that resolves CVE identifiers should record where it got an advisory and when.
How can you tell whether a CVE is real?
Check whether the cited code exists in the named version, since a function that was never in the release or a line number past the end of the file is conclusive. Look for a linked commit, pull request, or maintainer acknowledgement, because real fixes leave artifacts. Check the project's own security page rather than relying on the advisory. Then reproduce the proof of concept in a safe environment. JFrog's guidance is direct: do not blindly trust newly published CVEs from unvalidated sources, and reproduce the reported issue whenever possible.
Why are fabricated CVEs a bigger problem for AI remediation workflows?
Because an automated fix loop consumes advisories as instructions rather than as claims to be assessed. An agent handed a fabricated CVE will search for a function that does not exist, and may either stall or patch the nearest plausible code and report success, producing a pull request against working code that carries a critical severity label into review. A finding that arrives with a reproducible request and response gives the agent a third option: verify it before acting, and confirm the fix by running it again afterward.
Ask what the finding is made of
The lesson here is not that AI has no place in vulnerability research. It obviously does, and the same techniques that generated fifty-four fabrications are generating real findings elsewhere. The lesson is narrower and more durable: a severity score is a claim about the world, claims are now free to produce, and free things get produced in volume.
So the question to ask of any finding, from any tool, from any researcher, from any model, is not how confident it is. Confidence is the cheapest thing on the page. The question is what it is made of, and whether you can run it again.
A finding nobody can reproduce is not a finding. It is a rumor with a CVSS score.