Safeguard
DevSecOps

SnakeYAML in Maven: How to Use It Safely and Avoid CVE-2022-1471

Adding SnakeYAML as a Maven dependency is fine, but parsing untrusted YAML with the default constructor is not. Here is how to pin a safe version and lock down deserialization.

Marcus Chen
DevSecOps Engineer
5 min read

Pulling SnakeYAML into a Maven build is safe as long as you stay on version 2.0 or later and never parse untrusted YAML with the bare Constructor class. The snakeyaml maven coordinate most teams reference is org.yaml:snakeyaml, and the version you pin there is the single most important security decision you will make with this library.

SnakeYAML is the de-facto YAML parser for the JVM. It ships transitively inside Spring Boot, Jackson's YAML data format, testing tools, and dozens of other libraries, so you often have it on the classpath without ever declaring it yourself. That is exactly why it is worth understanding before an auditor or a scanner flags it.

Adding the maven snakeyaml dependency

The direct declaration looks like this:

<dependency>
  <groupId>org.yaml</groupId>
  <artifactId>snakeyaml</artifactId>
  <version>2.3</version>
</dependency>

Most of the time you will not write that block at all. Spring Boot's dependency management BOM already selects a SnakeYAML version for you. If you run mvn dependency:tree you will usually find it arriving through spring-boot-starter or jackson-dataformat-yaml. When you want to force a specific version regardless of what a transitive dependency asks for, add it to <dependencyManagement> in your parent POM rather than as a plain dependency, so the override applies everywhere.

CVE-2022-1471: the reason version matters

The headline risk with the maven snakeyaml artifact is CVE-2022-1471, a critical insecure-deserialization flaw. In affected releases (1.33 and every earlier 1.x version), SnakeYAML's Constructor class did not restrict which Java types a YAML document could instantiate. An attacker who controls the YAML input can craft a payload that constructs arbitrary objects and, in the worst case, reaches remote code execution.

The fix landed in SnakeYAML 2.0, released in February 2023. From 2.0 onward the Constructor inherits from SafeConstructor, so instantiating arbitrary classpath types is off by default. If your dependency:tree still shows a 1.x version, that is your remediation target.

Pin a fixed version, then verify the tree

Upgrading is usually a one-line change, but a transitive dependency can silently drag an old version back in. After you bump the version, confirm what actually resolves:

mvn dependency:tree -Dincludes=org.yaml:snakeyaml

If two dependencies request different versions, Maven's nearest-wins resolution can surprise you. Force the outcome with dependency management:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.yaml</groupId>
      <artifactId>snakeyaml</artifactId>
      <version>2.3</version>
    </dependency>
  </dependencies>
</dependencyManagement>

A transitive dependency like this is easy to miss by eye. An SCA tool such as Safeguard can flag a vulnerable SnakeYAML version even when it is three levels deep in the graph and you never declared it.

Parse untrusted YAML with SafeConstructor

Version pinning removes the known CVE, but secure coding still matters. If you are on 1.x and genuinely cannot upgrade yet, wire the parser explicitly to SafeConstructor:

Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
Map<String, Object> data = yaml.load(untrustedInput);

SafeConstructor refuses to build arbitrary types and returns only maps, lists, strings, and primitives. On 2.0+ this is closer to the default behavior, but being explicit documents intent and survives future refactors. As a rule, treat any YAML that crosses a trust boundary (uploaded config, webhook body, multi-tenant input) as hostile.

Guard against resource-exhaustion payloads

Deserialization RCE is not the only failure mode. YAML supports anchors and aliases, which a malicious document can nest to produce a "billion laughs" style expansion that exhausts memory. SnakeYAML's LoaderOptions lets you cap the blast radius:

LoaderOptions options = new LoaderOptions();
options.setMaxAliasesForCollections(50);
options.setCodePointLimit(5 * 1024 * 1024); // 5 MB
Yaml yaml = new Yaml(new SafeConstructor(options));

Setting a code-point limit and an alias cap turns an unbounded parse into a bounded, predictable one. These options exist precisely because YAML's expressiveness cuts both ways.

Keep the dependency honest over time

A version you pinned in March is not necessarily safe in December. New advisories get published, and transitive graphs shift every time you upgrade a framework. Two habits keep the risk low:

  1. Run a dependency scan in CI so a regression in the SnakeYAML version fails the build instead of shipping.
  2. Re-run mvn dependency:tree after any major framework upgrade, since Spring Boot and Jackson both manage SnakeYAML's version for you and may move it.

If you want the broader pattern behind this kind of issue, our Jackson databind security guide walks through the same trust-boundary thinking for JSON deserialization.

FAQ

What is the safe version of snakeyaml for Maven?

Use SnakeYAML 2.0 or later. Version 2.0 fixed CVE-2022-1471 by making the Constructor inherit from SafeConstructor, so arbitrary type instantiation is disabled by default. The 2.x line (2.3 at time of writing) is the current recommendation.

Do I need to declare snakeyaml if Spring Boot already includes it?

No. Spring Boot's dependency management selects a version for you. Declare it only when you need to override that version. Put the override in <dependencyManagement> so it applies to transitive uses too.

Is CVE-2022-1471 exploitable if I only parse my own config files?

The practical risk comes from parsing attacker-controlled YAML. If every YAML input is trusted and never crosses a trust boundary, exploitation is unlikely, but upgrading is still the right call because you rarely control every future call site.

How do I find which dependency pulls in an old SnakeYAML?

Run mvn dependency:tree -Dincludes=org.yaml:snakeyaml. It prints the exact path from your project through each intermediate artifact to the SnakeYAML version that resolved.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.