The SnakeYAML vulnerability fix for CVE-2022-1471 is to upgrade org.yaml:snakeyaml to a 2.x release, or, if you are stuck on 1.x, to load YAML through SafeConstructor instead of the default Constructor. Everything else in this guide is about how the flaw works, why it kept showing up in dependency scans through 2023, and how to confirm you have actually removed it rather than just silenced the alert.
CVE-2022-1471 is a deserialization flaw. SnakeYAML's default Constructor did not restrict which Java classes a YAML document could instantiate. If your application parsed YAML from an untrusted source, an attacker could craft a document that used a global tag such as !!javax.script.ScriptEngineManager to reach a gadget chain and, in the worst case, achieve remote code execution. The NVD entry assigns it a critical rating, and it applies to all SnakeYAML 1.x versions.
Why this one traveled so far
Almost nobody adds SnakeYAML to their pom.xml on purpose. It arrives transitively. Spring Boot pulled it in for YAML configuration parsing, Jackson's YAML dataformat module depends on it, and dozens of other libraries do too. So the version in your build is usually decided by whatever your framework happens to pin, not by you.
That is why the fix felt slow. SnakeYAML 2.0 shipped in February 2023, but it was a breaking major release, and downstream projects had to adopt it deliberately. Spring Boot did not move to SnakeYAML 2.x until the 3.1 line, which meant teams on older Spring Boot kept seeing the CVE flagged even after they had upgraded their direct dependencies.
The core fix: move to 2.x
If you control the version, the cleanest fix is to force SnakeYAML forward. In Maven, pin it explicitly so the transitive version loses:
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>2.3</version>
</dependency>
In Gradle, a resolution strategy or a plain constraint does the same thing:
dependencies {
constraints {
implementation('org.yaml:snakeyaml:2.3') {
because 'CVE-2022-1471'
}
}
}
Since 2.0, SnakeYAML's Constructor inherits from SafeConstructor. Global tags are blocked by default, and only primitive types and basic collections deserialize without extra opt-in. That change is what closes the vulnerability, and it is also what breaks code that relied on YAML instantiating arbitrary beans.
Before you ship the bump, check whether anything in your codebase constructs custom types straight from YAML. If you were depending on that behavior, you will need to register the allowed types explicitly on a LoaderOptions / tag inspector after the upgrade. Most applications parse config maps and never notice.
If you cannot upgrade yet
Sometimes a framework hard-pins an old SnakeYAML and forcing it forward breaks the framework. In that case, stay on 1.x but never hand untrusted YAML to the bare Constructor. Use SafeConstructor:
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
Map<String, Object> data = yaml.load(untrustedInput);
SafeConstructor refuses to instantiate arbitrary classes, which removes the RCE path even on a vulnerable release. This is a real mitigation, not a workaround that only quiets the scanner — the exploit needs the permissive constructor to reach a gadget.
The one thing that does not work is treating the input as trusted "because it comes from our own config server." Any YAML that crosses a trust boundary — an uploaded file, an API body, a webhook payload — is untrusted for this purpose.
Confirming the fix actually landed
Because the vulnerable copy is transitive, patching your direct dependency is not the same as removing it. Print the resolved tree and look for stragglers:
# Maven
mvn dependency:tree -Dincludes=org.yaml:snakeyaml
# Gradle
./gradlew dependencyInsight --dependency snakeyaml
If you see two versions, a shaded fat JAR or a plugin classpath is probably carrying an old one. Rebuild your artifact and inspect what actually ships, not just what the reactor resolves. A software composition analysis tool such as Safeguard can flag the transitive snakeyaml pull across every module so you are not grepping trees by hand, and it will tell you which upstream dependency is pinning the old version.
For a broader look at how deserialization gadgets get into Java builds through JSON as well as YAML, the Jackson databind security guide covers the sibling problem in the JSON world.
Don't just suppress it
The tempting shortcut is a scanner suppression: mark CVE-2022-1471 as a false positive and move on. That is only honest if you have proven the vulnerable code path is unreachable — for example, you never parse YAML at all, or every parse already uses SafeConstructor. Write that reasoning into the suppression comment so the next person who reads the audit understands why it is safe. A bare suppression with no justification is how a critical deserialization flaw survives three release cycles.
FAQ
Which SnakeYAML versions are affected by CVE-2022-1471?
All 1.x releases are affected because the default Constructor allowed arbitrary type instantiation. The fix landed in SnakeYAML 2.0 (February 2023), and any 2.x release carries it. Later 2.x versions add further hardening and bug fixes, so pin to a current 2.x rather than exactly 2.0.
Does upgrading Spring Boot fix it automatically?
Only if you move to a Spring Boot line that already ships SnakeYAML 2.x, which started with Spring Boot 3.1. On older Spring Boot you can override the managed version by setting the snakeyaml.version property, but test your YAML config loading afterward.
Is SafeConstructor enough on SnakeYAML 1.x?
Yes for this CVE. SafeConstructor blocks the arbitrary-class instantiation that the exploit relies on, so untrusted YAML can no longer reach a gadget chain. It is the recommended mitigation when a version upgrade is not immediately possible.
How do I know if the old version is still in my build?
Run mvn dependency:tree -Dincludes=org.yaml:snakeyaml or the Gradle dependencyInsight equivalent, then inspect the final packaged artifact for a stray shaded copy. Two versions on the classpath usually means a fat JAR or a build plugin is dragging in the old one.