The Bug That Won't Die:

10 Years of the Same Mistake

A decade of deserialization vulnerabilities (and why we keep making them)

CVE-2025-55182 Intelligence Card c/o Recorded Future

There are now multiple publicly available exploit scripts (I forked one on GitHub here) for the React and Next.js vulnerabilities (CVE-2025-55182 and CVE-2025-66478).

The underlying issue is data serialization/deserialization, which evoked thoughts about a blog I wrote in 2016, addressing the same issue (at the time, the topic was CVE-2015-4852, a serialization flaw in Java objects that affected Oracle and Apache products).

Timeline illustrating the deserialization vulnerability impacts of 40+ critical CVEs across 6 ecosystems, over the course of 10 years.

2 Risk Takeaways

Technical Causation

The Threat

The attack surface has expanded once again. In 2015, we were tracking exploit chatter on Chinese forums appearing weeks before CVEs. Now, there are double-digit public GitHub repositories with weaponized exploit code within days of disclosure. Agentic workflows will soon compress that window down to minutes. The time-to-exploitation will amount to the time defenders spend reading about any new high-severity vulnerability.

PoC exploit testing, c/o Recorded Future

Defender Considerations for CVE-2025-55182 / CVE-2025-66478

AI-generated serialization vulnerability audit

For “Vibe Coders”: A Conversation with Claude Opus 4.5

Q: What’s a proper input validation methodology for deserializing data to avoid security failures?

A: Native serialization formats (Java ObjectInputStream, PHP unserialize, Python pickle, .NET BinaryFormatter) reconstruct objects with behavior, which means arbitrary code can execute during deserialization. The fix is using formats that only transfer data, not executable structures.

Safe alternatives:

1. Data-only interchange formats

These parse into primitive types and structures—no object instantiation, no code execution.

2. Schema validation on top

Define exactly what shape the data must have. Reject anything that doesn’t match before your application logic ever sees it.

3. When you need objects, build them explicitly

Instead of:

obj = pickle.load(untrusted_data) # dangerous

Do:

data = json.loads(untrusted_data) # safe parse
obj = MyClass(**validated_schema(data)) # explicit construction

4. For config/markup

The one-liner: If your serialization format can reconstruct arbitrary types, it’s a vulnerability. Stick to dumb data formats + explicit object construction.

Q: Do modern LLMs know how to securely validate data by default?
A: Technically, yes, practically, it’s complicated.

What’s in the training data:

So if you ask directly—”Is pickle safe for untrusted data?”—any decent LLM will say no.

The problem:

LLMs are also trained on millions of Stack Overflow answers, tutorials, and GitHub repos that use pickle.load(), unserialize(), and yaml.load() because they’re convenient. When someone asks, “How do I save this object to a file and load it later?” the pattern-match often lands on the dangerous-but-common approach.

What I’ve observed:

The real gap:

LLMs don’t reason about security—they predict likely tokens based on training. They won’t spontaneously say “wait, where is this data coming from?” the way an experienced developer might. The threat model isn’t automatic.

Practical advice for developers using LLM assistants:

So yes, the knowledge is in there. But so is a decade of insecure examples, and the LLM doesn’t inherently prioritize one over the other unless prompted.

Stay Ahead with Recorded Future

Learn how Recorded Future's Vulnerability Intelligence tracks CVE disclosures, monitors exploit availability across GitHub and underground forums, and prioritizes vulnerabilities based on active threats to your environment. The platform compresses your response window from days to hours.