Application Security

JSON Parsing Library Vulnerabilities You Should Know About

JSON is the lingua franca of APIs, but the libraries that parse it have had serious security issues. Here is what to watch for in your stack.

James
Senior Security Analyst
5 min read

JSON is simple. The specification fits on a business card. Parse strings, numbers, booleans, nulls, arrays, and objects. What could go wrong?

Quite a lot, as it turns out. JSON parsing libraries across every major programming language have had vulnerabilities ranging from denial of service to remote code execution. The simplicity of the format is deceptive -- the edge cases in parsing, number handling, and nesting are where the bugs hide.

Denial of Service Through Deep Nesting

The most common JSON parsing vulnerability is stack overflow through deeply nested structures. A JSON object containing 100,000 nested arrays will crash most recursive-descent parsers by exhausting the call stack.

This is trivially exploitable against any API that accepts JSON input without size or depth limits. An attacker sends a small (kilobytes) but deeply nested JSON document, and the server process crashes.

Most modern JSON libraries have added nesting depth limits, but the defaults vary. Python json.loads() has a default recursion limit of 1000. Some libraries still have no default limit.

Mitigation: Configure a maximum nesting depth that matches your application requirements. For most APIs, 20-50 levels is more than sufficient.

Hash Collision Attacks

JSON objects are typically implemented as hash tables. When an attacker can predict the hash function used by the parser, they can craft keys that all hash to the same bucket, converting O(1) lookups into O(n) lookups. Parsing a document with thousands of colliding keys takes seconds or minutes instead of milliseconds.

This attack was demonstrated against Python, Java, PHP, and Ruby JSON parsers in 2011-2012. The response varied by language:

  • Python switched to a randomized hash function (SipHash) in version 3.3
  • Java added a collision threshold that converts hash buckets to balanced trees
  • PHP added a max_input_vars configuration option
  • Ruby switched to a randomized hash function

Mitigation: Use a modern language runtime with randomized hash functions. If you are on an older runtime, set limits on the number of keys in parsed JSON objects.

Number Handling Issues

JSON numbers have no explicit size limit. The specification says a number is a sequence of digits with optional decimal point and exponent. This means 1e999999999 is a valid JSON number, but parsing it into a floating-point variable produces infinity, and parsing it into an integer produces overflow.

Libraries handle this differently. Some silently convert to infinity or zero. Some throw an exception. Some attempt arbitrary-precision arithmetic consuming unbounded memory. Some use the exponent value directly in memory allocation, leading to enormous allocations.

Mitigation: Validate numeric ranges after parsing. If your application expects a price field, verify it is within reasonable bounds before processing.

Prototype Pollution in JavaScript

JavaScript JSON parsing has a unique vulnerability class: prototype pollution. When JSON.parse() produces an object, that object inherits from Object.prototype. If the JSON contains keys like __proto__, constructor, or prototype, naive object merging operations can modify the prototype chain, affecting all objects in the application.

This is not a vulnerability in JSON.parse() itself but in the libraries that process the parsed output. Lodash _.merge(), jQuery $.extend(), and many other utilities have been vulnerable to prototype pollution when processing parsed JSON.

Mitigation: Use Object.create(null) for objects that will hold parsed data. Validate that incoming JSON keys do not include prototype-related property names.

Deserialization Attacks

Some JSON libraries go beyond simple parsing to support full object deserialization with type information. Java Jackson library supports polymorphic type handling where a JSON field specifies which Java class to instantiate.

CVE-2017-7525 and numerous subsequent CVEs in Jackson demonstrated that this feature could be exploited for remote code execution. An attacker sends JSON containing a type reference to a dangerous class, and Jackson instantiates it, triggering JNDI injection or other code execution.

Mitigation: Disable polymorphic type handling unless you specifically need it. If you must use it, maintain a strict allowlist of permitted types.

Billion Laughs Equivalent

The classic Billion Laughs attack (originally an XML bomb) has JSON equivalents. A small JSON document can define deeply nested or highly repetitive structures that expand to enormous size when processed.

JSON Schema validators are particularly susceptible. A schema with recursive references can cause the validator to enter an infinite loop or consume unbounded memory when validating a document.

Practical Recommendations

Set parsing limits. Maximum document size, maximum nesting depth, maximum string length, maximum number of keys. Most JSON libraries support these configuration options.

Validate after parsing. Never trust the structure of parsed JSON. Validate types, ranges, and required fields before processing.

Use streaming parsers for large documents. Streaming JSON parsers process documents incrementally without loading the entire document into memory.

Keep parsers updated. JSON library maintainers regularly fix security issues. Use the latest stable version.

How Safeguard.sh Helps

Safeguard.sh monitors JSON parsing libraries across your dependency tree and alerts you to known vulnerabilities. Whether you use Jackson, Gson, JSON.NET, or language-standard parsers, our platform tracks CVEs and provides remediation guidance. Our comprehensive SBOM generation ensures you know exactly which JSON processing components are in play across your application portfolio.

Never miss an update

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