Safeguard
Vulnerability Analysis

Unsafe deserialization in SnakeYAML CVE-2022-1471

CVE-2022-1471 lets attackers achieve RCE via SnakeYAML's unsafe Constructor. Learn affected versions, CVSS/EPSS context, and remediation steps.

Yukti Singhal
Security Analyst
7 min read

A widely used Java library for parsing YAML, SnakeYAML, shipped a default configuration that let attacker-controlled YAML documents instantiate arbitrary Java types during deserialization — and under the right conditions, that translates directly into remote code execution. This is the core of CVE-2022-1471, a critical unsafe deserialization flaw in SnakeYAML's Constructor class that affects every application calling Yaml.load() on untrusted input without explicitly restricting which classes can be built. Because SnakeYAML sits as a transitive dependency inside Spring Framework, dozens of Jenkins plugins, Apache projects, and countless internal Java services, the practical blast radius of this CVE is far larger than the library's own download count would suggest. If you're triaging snakeyaml cve-2022-1471 in a vulnerability report right now, the short version is: treat it as critical, confirm whether the vulnerable code path is actually reachable, and upgrade rather than patch around it.

What the Vulnerability Actually Does

SnakeYAML's Constructor class (as opposed to the safer SafeConstructor) is designed to deserialize YAML into arbitrary Java objects, including custom types referenced by YAML tags like !!org.example.SomeClass. That flexibility is the entire problem. When an application calls new Yaml().load(untrustedInput) using the default, unconfigured Constructor, an attacker who controls the YAML payload can specify tags that instantiate Java classes already present on the classpath — including classes with constructors or setters that trigger side effects.

The most commonly cited proof-of-concept abuses javax.script.ScriptEngineManager, which SnakeYAML will happily instantiate and populate with a URL pointing to a remote classloader. When invoked, the ScriptEngineManager fetches and executes attacker-supplied Java code, giving full remote code execution without needing a separate deserialization gadget-chain library like ysoserial. That's what makes this bug distinct from many "just another deserialization CVE" writeups: the exploitation primitive is native to the JRE itself, so the attack surface exists almost everywhere SnakeYAML's default Constructor touches untrusted YAML, regardless of what else is on the classpath.

Affected Versions and Components

  • SnakeYAML versions up to and including 1.30 are affected by the core issue as originally reported.
  • SnakeYAML 1.31 was released as an initial remediation attempt, but subsequent analysis showed the fix was incomplete — the underlying design (allowing arbitrary type instantiation by default) remained largely intact for applications that didn't change how they called the library.
  • SnakeYAML 2.0, released in January 2023, is the version that delivers the real architectural fix: it changes the API so that Constructor requires an explicit LoaderOptions and, more importantly, introduces a TagInspector mechanism that forces callers to explicitly allow the classes they intend to deserialize, rather than trusting everything on the classpath by default.

Because SnakeYAML is rarely a direct dependency for most teams, the exposure usually comes in transitively. Common carriers include Spring Framework and Spring Boot (via spring-core's YAML property source support), a large number of Jenkins plugins that parse YAML configuration, Apache NiFi, Alfresco, Elasticsearch/Logstash tooling, Liquibase, Backstage plugins, and any internal service that accepts YAML — configuration files, CI pipeline definitions, Kubernetes manifests, IaC templates — from a source that isn't fully trusted. The key triage question isn't "do we have snakeyaml on the classpath," it's "does any code path pass externally influenced YAML into Yaml.load() using the default Constructor."

CVSS, EPSS, and KEV Context

NVD scores CVE-2022-1471 at 9.8 (Critical) under CVSS v3.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) — network-exploitable, no privileges or user interaction required, and full compromise of confidentiality, integrity, and availability if the deserialization path is reachable and a suitable gadget class is present.

EPSS scoring for this CVE has trended higher than the median for library-level deserialization bugs, reflecting both the ease of exploitation once a reachable sink is found and the sheer number of downstream projects that reference SnakeYAML. As of this writing, CVE-2022-1471 is not listed in CISA's Known Exploited Vulnerabilities (KEV) catalog, but that shouldn't be read as low risk — KEV listing tracks confirmed in-the-wild exploitation, and the exploitation prerequisites here (an application must actually parse attacker-influenced YAML with the vulnerable constructor) are common enough in Java ecosystems that security teams should not wait for a KEV entry to prioritize remediation. EPSS and KEV status can change; always check current values against NVD and CISA's feeds before finalizing a risk rating for your environment.

Timeline

  • Early April 2022 — Security researchers report the unsafe-deserialization behavior in SnakeYAML's default Constructor to the project maintainers, describing the ScriptEngineManager exploitation path.
  • May 16, 2022 — CVE-2022-1471 is published in NVD, along with the corresponding GitHub Security Advisory for the snakeyaml package.
  • May 2022 — SnakeYAML 1.31 ships as an initial response, but the fix is later assessed as incomplete for applications relying on default behavior.
  • Mid-to-late 2022 — Downstream projects (Spring, Jenkins plugins, various Apache and vendor products) begin publishing their own advisories and dependency bumps as the ecosystem-wide exposure becomes clearer.
  • January 17, 2023 — SnakeYAML 2.0 is released, introducing the TagInspector/allowlist model that removes the unsafe default and forces explicit opt-in for custom type construction — the version most organizations should treat as the actual remediation target.
  • Ongoing — New advisories continue to surface periodically as previously unaudited internal tools and older transitive dependency chains are discovered still pinning pre-2.0 SnakeYAML.

Remediation Steps

  1. Inventory every instance of SnakeYAML in your dependency tree, direct and transitive. Run mvn dependency:tree -Dincludes=org.yaml:snakeyaml or gradle dependencies --configuration runtimeClasspath and cross-reference against an SBOM if you generate one during builds — transitive pulls via Spring, Jackson's YAML data-format module, or CI tooling are the most commonly missed cases.
  2. Upgrade to SnakeYAML 2.0 or later, not just 1.31. The 1.31 release does not close the underlying design gap for teams that haven't changed their calling code; only 2.0's opt-in allowlist model provides durable protection.
  3. Audit calling code for direct use of new Constructor() or new Yaml() with default settings. Anywhere YAML from an external, user-supplied, or otherwise untrusted source is parsed, replace the default Constructor with SafeConstructor, or configure LoaderOptions/TagInspector (on 2.0+) to explicitly allow only the classes you actually need deserialized.
  4. Bump framework versions that bundle SnakeYAML transitively. Confirm your Spring Boot / Spring Framework version pulls a patched SnakeYAML release, and do the same for any Jenkins plugins, Apache components, or third-party libraries in your stack that parse YAML.
  5. Re-run SCA scans after upgrading to confirm the vulnerable version is fully removed from the resolved dependency graph — partial upgrades that leave an older transitive copy shadowed elsewhere in the tree are a common false sense of security.
  6. Where upgrading isn't immediately possible, restrict which sources of YAML your application accepts, and treat any YAML ingestion endpoint (config upload, webhook payload, CI job definition) as a high-priority input validation boundary until the dependency is patched.

How Safeguard Helps

Finding "snakeyaml is in my SBOM" is the easy part — the harder question is whether your specific application actually calls the vulnerable Constructor path on attacker-influenceable input, and that's where generic CVE severity scores mislead teams into either panic or complacency. Safeguard's reachability analysis traces the actual call graph from your application's untrusted input sources down to SnakeYAML's Constructor/Yaml.load() sinks, so you can immediately tell whether CVE-2022-1471 is exploitable in your codebase or sitting dormant in a code path that never touches external YAML. Griffin AI correlates that reachability signal with your build context to prioritize this finding against the rest of your backlog instead of treating every CVSS 9.8 the same. Our continuous SBOM generation and ingest keeps your dependency inventory current across every service pulling SnakeYAML transitively, closing the visibility gap that lets pre-2.0 versions linger unnoticed in nested dependency chains. And when remediation is confirmed necessary, Safeguard can open an auto-fix pull request that bumps the affected dependency to a patched SnakeYAML release, so your team moves from detection to a mergeable fix without manually chasing version pins across dozens of repositories.

Never miss an update

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