Back to Blog
high SEVERITY5 min read

js-yaml 5.2.1 DoS: Exponential Parsing in Flow Collections

A denial-of-service vulnerability in js-yaml 5.2.1 allows an attacker to crash the parser by supplying deeply nested flow collections that trigger exponential parsing behavior. The fix in version 5.2.2 improves the parser's handling of these structures, preventing the algorithmic complexity attack. This is critical for any service accepting user-controlled YAML input.

O
By Orbis AppSec
•Published October 1, 2026•Reviewed October 1, 2026

Answer Summary

js-yaml versions up to 5.2.1 are vulnerable to denial of service. An attacker can craft a malicious YAML document with deeply nested flow collections (arrays and objects) that causes the parser to enter exponential time complexity, consuming CPU and memory until the process hangs or crashes. The fix in js-yaml 5.2.2 optimizes the parsing algorithm to prevent this exponential behavior. The CWE is unknown.

Vulnerability at a Glance

cweN/A
fixUpgrade js-yaml to 5.2.2 for optimized parsing logic
riskAttackers can crash services by submitting specially crafted YAML, disrupting availability
languageJavaScript
root causeFlow collection parser enters exponential time complexity on nested input
vulnerabilityDenial of Service via Exponential Parsing

Understanding the Vulnerability

js-yaml is a widely used YAML parser for JavaScript and Node.js applications. It converts YAML documents—human-readable data serialization format—into JavaScript objects. Services that accept YAML input from users, configuration systems, or APIs rely on js-yaml to deserialize untrusted data safely.

A flaw in js-yaml 5.2.1's handling of flow collections (YAML's inline syntax for arrays and objects) allows an attacker to trigger exponential parsing behavior. Flow collections use brackets and braces: [item1, item2] for arrays and {key: value} for objects. When deeply nested, the parser must recursively evaluate each level, but in version 5.2.1, this recursion enters an exponential time loop—each nesting level multiplies the work required.

Affected Versions

Affected js-yaml >= 5.0.0, < 5.2.2
Fixed in 5.2.2
Ecosystem npm
CVE / GHSA CVE-2026-73643
CWE unknown

Attack Scenario

Consider a service that accepts YAML configuration from external sources:

const yaml = require('js-yaml');

app.post('/config', (req, res) => {
  const config = yaml.load(req.body);
  processConfig(config);
  res.send('Config updated');
});

An attacker sends a POST request with a deeply nested flow collection:

[[[[[[[[[[[[[[[[[[[[[
  [[[[[[[[[[[[[[[[[[[[[
    [true]
  ]]]]]]]]]]]]]]]]]]]
]]]]]]]]]]]]]]]]]]]

The parser begins evaluating the outermost bracket, then recursively enters each nested level. At each depth, the algorithm re-evaluates previous levels to resolve the structure. With 20 levels of nesting, the parser performs exponentially increasing amounts of work, consuming CPU until the request handler times out or the process crashes. The attacker achieves denial of service without submitting a gigabyte of data—just a few kilobytes of carefully nested YAML.

The Technical Details

The vulnerability stems from how the parser resolves flow collection delimiters. Each opening bracket or brace triggers a recursive descent. In 5.2.1, the parser lacked optimization to memoize or short-circuit redundant evaluations at each recursion level. This means a 30-level nested flow collection doesn't just cost 30× work—it costs 2³⁰ work, or roughly one billion operations, even though the structure itself is trivial.

Services that parse untrusted YAML are particularly at risk:
- Config management systems accepting user-supplied configuration
- API gateways that forward YAML payloads
- Log aggregators ingesting YAML-formatted events
- CI/CD pipelines processing YAML job definitions

Any of these could be stalled by a single malicious request.

The Fix

js-yaml 5.2.2 optimizes the flow collection parser to avoid redundant recursion. The fix modifies the internal parsing state machine to recognize and efficiently handle deeply nested structures without re-evaluating ancestor levels.

The dependency upgrade in agent-core/package.json enforces this fix:

-    "js-yaml": "^5.2.1",
+    "js-yaml": "^5.2.2",

The lockfile is updated to pull the patched version:

     "node_modules/js-yaml": {
-      "version": "5.2.1",
+      "version": "5.2.2",

This ensures that the next npm install in agent-core will fetch js-yaml 5.2.2, which contains the optimized parser. Existing deployments running 5.2.1 should update their dependencies immediately.

How the Optimization Works

The 5.2.2 release doesn't change the YAML specification or the public API—it changes only the internal algorithm. The parser now uses a single-pass state machine for flow collections instead of recursive re-evaluation. For a 20-level nested structure, parsing time drops from exponential to linear.

Legitimate YAML documents benefit from this too. Configuration files with moderate nesting (5–10 levels) parse faster. Deeply nested legitimate structures (rare in practice) now parse instead of timing out.

How Orbis AppSec Detected This

Source: YAML documents supplied via yaml.load() or yaml.parse() on untrusted input—HTTP request bodies, uploaded files, API payloads, or any external data source.

Sink: The flow collection parser's recursive descent function within js-yaml, invoked whenever the parser encounters [ or { characters.

Missing control: js-yaml 5.2.1 lacked algorithmic safeguards against nested flow collections. There was no recursion depth limit, no parser state memoization, and no early-exit heuristics for exponential patterns.

CWE: unknown; this is an algorithmic complexity issue (related to CWE-407 "Inefficient Algorithm") rather than a memory corruption or traditional injection vulnerability.

Fix: Upgrade js-yaml to 5.2.2, which implements an optimized single-pass parser for flow collections.

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Key Takeaways

  • Deeply nested flow collections in YAML can cause exponential parsing time: js-yaml 5.2.1 re-evaluates ancestor levels during recursion, making nesting depth a direct multiplier of computation. Always validate nesting depth or use version 5.2.2+.

  • Denial of service doesn't require large payloads: A few kilobytes of nested YAML crashed the parser—less data than a typical HTTP request. Monitor for slow or hanging requests even when input size is small.

  • Algorithmic vulnerabilities are as real as buffer overflows: This wasn't memory corruption or code injection; it was an algorithmic flaw that spent 2³⁰ cycles processing what should cost 30. Auditing algorithms is as important as auditing bounds checking.

  • Lock in dependency versions in production: agent-core's lockfile ensures reproducible builds. Updating the lockfile from 5.2.1 to 5.2.2 is a low-risk fix—same major.minor, same public API, just safer internals.

  • Untrusted YAML is particularly risky: If your service parses YAML from users or external systems, patch immediately. YAML parsing is a high-value attack surface because the format is expressive and the parser is complex.

Conclusion

CVE-2026-73643 demonstrates that not all denial-of-service vulnerabilities come from infinite loops or memory exhaustion—they can come from algorithmic complexity. js-yaml 5.2.1's exponential parsing behavior on nested flow collections allowed attackers to crash services with minimal input. The fix in 5.2.2 optimizes the parser to handle these structures efficiently, and upgrading is straightforward: a single version bump in your dependency manifest. If you use js-yaml in any capacity that touches untrusted YAML, update to 5.2.2 or later now.

Prevention and further reading

Frequently Asked Questions

How would an attacker exploit this in a real service that accepts YAML uploads?

An attacker would submit a YAML file containing deeply nested flow collections like `[[[[[...]]]]]` or `{{{{{...}}}}}`. The parser would enter exponential backtracking as it tries to resolve the structure, causing the service to freeze or crash before the document is fully parsed.

Does js-yaml 5.2.2 change the public API for parsing YAML?

No. The version upgrade only changes the internal parsing algorithm. All public methods like `parse()` and `load()` retain their signatures and behavior—only malformed deeply nested structures now parse efficiently instead of hanging.

Which agent-core versions are affected by this vulnerability?

Any version of agent-core that depends on js-yaml 5.2.1 is affected. The fix updates agent-core's dependency manifest to require js-yaml 5.2.2 or later, ensuring future builds pull the patched version automatically.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #12

Related Articles

high

Anthropic API Adapter Prototype Pollution in parseToolCallInput

The `parseToolCallInput` function in the Anthropic API adapter used `JSON.parse` without protecting against prototype pollution keys. An attacker who could manipulate API responses—through a man-in-the-middle attack, compromised Codex backend, or DNS spoofing—could inject `__proto__`, `constructor`, or `prototype` properties to pollute JavaScript's Object prototype and affect extension runtime behavior.

high

load_localStorage.js JSON Parse: Prototype Pollution via __proto__

The load_localStorage.js utility parsed JSON configuration without validating keys, permitting prototype pollution through malicious `__proto__`, `constructor`, or `prototype` properties. An attacker with filesystem access could poison downstream JavaScript execution by injecting these special keys into the loaded data structure.

critical

How Arbitrary Code Execution Happens in protobufjs and How to Fix It

CVE-2026-41242 is a critical vulnerability in protobufjs versions 8.0.0 and earlier that allows attackers to execute arbitrary code by injecting malicious type fields into protobuf definitions. The fix upgrades the dependency from `^8.0.0` to `^8.6.6` in `core/package.json`, eliminating the unsafe code path that processed attacker-controlled type metadata without validation.

high

How Quadratic CPU Consumption Happens in JS-YAML and How to Fix It

A critical vulnerability in JS-YAML versions 3.x and 4.x allowed attackers to trigger quadratic CPU consumption through maliciously crafted YAML input using the `!!omap` tag resolver. The vulnerability stems from inefficient array operations in the ordered map resolution logic, which could be exploited for denial-of-service attacks. Upgrading to JS-YAML 4.3.1 or 3.15.1 patches this attack surface by optimizing the computational complexity of ordered map processing.

critical

How Type Confusion Vulnerabilities Happen in JavaScript Dependencies and How to Fix Them

A critical type confusion vulnerability (CVE-2021-23436) was discovered in immer 9.0.7, a popular immutable state management library used in the client application. By upgrading to immer 9.0.6, the vulnerability was patched, eliminating a flaw that could have allowed attackers to bypass previous security fixes (CVE-2020-28477). This fix demonstrates why keeping dependencies current is essential for maintaining application security.

high

CVE-2026-54673: builder-util-runtime Leaks Auth Headers on Redirect

electron-updater and electron-builder rely on builder-util-runtime to fetch update manifests and artifacts over HTTP. A flaw in that shared HTTP executor allowed credential headers attached to the original update-feed request to be re-sent after a redirect, exposing them to any host the redirect pointed to. The project fixes this by upgrading builder-util-runtime to 9.7.0 and collapsing a duplicate, older copy of the package that electron-updater had pinned on its own.