The SnakeYAML vulnerability tracked as CVE-2022-1471 comes down to a default that trusted YAML input too much: SnakeYAML's Constructor class, used whenever an application calls Yaml.load() on a YAML document, didn't restrict which Java classes could be instantiated during parsing. A YAML file is supposed to describe data — strings, numbers, lists, maps — but SnakeYAML's default constructor let a document also describe which Java class to instantiate and how to construct it, and that capability is exactly what turns a config-file parser into a remote code execution path when the YAML source isn't trusted.
What is a Java deserialization vulnerability, and why does SnakeYAML have one?
A java deserialization vulnerability happens when a program reconstructs objects from serialized data without verifying that the resulting object types are safe to instantiate — if an attacker can specify the class, and that class has a constructor or setter with a side effect (writing a file, opening a connection, invoking a shell), the act of parsing the data becomes the act of running attacker-chosen code. SnakeYAML's YAML 1.1 spec support includes a feature for tagging values with explicit Java types (!! type tags), and the library's default Constructor honored those tags by instantiating essentially any class on the classpath that matched a recognizable constructor pattern. Combined with "gadget chain" classes already present in most Java applications' dependencies — classes whose otherwise-ordinary methods can be chained together to execute a command — this gave attackers a path from "I can supply YAML this app parses" to full code execution.
What did CVE-2022-1471 change?
The fix moved SnakeYAML toward a safe-by-default posture: newer versions require applications to explicitly opt into unrestricted type instantiation, and the recommended path for any application parsing untrusted YAML is to use SafeConstructor (or the newer Constructor with an explicit allow-list of permitted types) rather than the old unrestricted default. Applications that only ever parse their own trusted configuration files were never at meaningful risk from this specific issue, since the attacker model requires the YAML content itself to be attacker-controlled — but any service that accepts YAML as user input (import features, CI configuration uploads, webhook payloads) was exposed if it called the library's defaults directly.
How do you tell if your application is actually exposed?
Check two things: which SnakeYAML version is resolved in your dependency tree, and how your code calls it. A project on a patched SnakeYAML version that still calls the unsafe constructor pattern explicitly can reintroduce the same risk the patch was meant to close, because the fix is about defaults and available APIs, not a blanket ban on the unsafe behavior. This is the kind of finding where a version-only scanner produces a false positive in one direction (flagging a patched-but-unused dependency) and a false negative in the other (missing an app that still explicitly opts into unsafe deserialization). Reachability-aware scanning — tracing whether the vulnerable constructor path is actually invoked with attacker-reachable input — is what separates a real finding here from noise, which matters given how often SnakeYAML shows up as a transitive dependency of Spring Boot, Jenkins plugins, and other Java frameworks that use YAML for configuration.
Why does this keep showing up in scans years after the fix?
Because SnakeYAML sits so deep in the Java ecosystem's dependency graph — pulled in by Spring, by countless CI/CD tools, by YAML-based configuration libraries — that a huge number of projects carry an old, unpinned transitive copy without anyone on the team having chosen it directly. Safeguard's SCA engine resolves the full transitive graph for Java projects (Maven and Gradle alike) and flags outdated SnakeYAML versions along with whether the vulnerable constructor path is reachable from code the application actually runs, rather than just reporting "SnakeYAML found, CVE present" and leaving triage to the team.
How does this compare to other deserialization vulnerabilities in the Java ecosystem?
SnakeYAML's issue sits alongside a broader family of Java deserialization vulnerabilities that made headlines around the same general period, including well-known issues in Apache Commons Collections and various application server frameworks that relied on native Java object serialization rather than YAML. The common thread across all of them is the same underlying design mistake: trusting that data received from an external source only describes values, when the deserialization mechanism actually allows it to describe code paths. Any time a library adds a convenience feature that lets serialized input specify a type to instantiate — whether that's a YAML type tag, a native Java ObjectInputStream, or a JSON library's polymorphic type handling — it reopens the same category of risk unless type instantiation is explicitly restricted. Teams auditing for this class of bug should look across all of these mechanisms together rather than treating SnakeYAML as an isolated case, since the same reasoning applies to XML deserialization, PHP's unserialize(), and any other format with a similar "type hint" feature.
FAQ
Is every YAML parser vulnerable to this kind of issue?
No — the risk is specific to parsers that support instantiating arbitrary types from tagged data and default to trusting that capability. Parsers that only ever produce plain data structures (strings, maps, lists) without a type-instantiation feature don't share this exact vulnerability class, though they can have other parsing bugs.
Does this affect YAML files my own team writes and controls?
Generally no — the attacker model requires the YAML content to come from an untrusted source. Internal configuration files your team authors and controls aren't the risk; user-uploaded YAML, YAML pulled from external webhooks, or YAML embedded in API requests is.
What's the safe way to parse untrusted YAML in Java today?
Use SafeConstructor or a Constructor instance configured with an explicit allow-list of permitted types, and keep SnakeYAML on a current, patched version — the combination of a safe API and a current library version is what actually closes the gap, not either one alone.