Lintify Logo
Lintify
Security & Reliability 13 min read 2026-05-04

Hardening Production JSON APIs: Prototype Pollution, Denial of Service (JSON Bomb), and Parser Exploits

A practical guide to securing JSON parsers and web APIs against prototype pollution, quadratic JSON bomb memory exhaustion, unicode homoglyph attacks, and parser differential vulnerabilities.

Lintify Engineering Team
Application Security & Cryptography

1. The JSON Attack Surface

Because JSON is syntactically simple, software engineers often mistakenly assume it is inherently secure. However, serialization is the bridge between untrusted network bytes and your application's internal memory state.

Common attack vectors targeting JSON parsers include: 1. Object Prototype Hijacking: Overriding global JavaScript object properties. 2. Algorithmic Complexity Attacks (JSON Bombs): Creating deeply nested structures that trigger stack overflows. 3. Parser Differentials: Exploiting mismatches between API Gateway parsers and downstream backend parsers (e.g. duplicate key precedence). 4. Number Precision Manipulation: Overflowing 64-bit IEEE 754 floats to alter financial balances.


2. Deep Dive: Prototype Pollution via JSON

In JavaScript and Node.js environments, merging recursive JSON payloads into existing objects without sanitizing special keys allows attackers to pollute Object.prototype:

jsonCode Example
{
  "__proto__": {
    "isAdmin": true,
    "role": "superadmin"
  }
}

If your server performs a recursive merge (e.g. lodash.merge({}, userInput)), every single object created in the entire Node.js runtime inherits isAdmin = true.

Production Defense: ```javascript // Safe JSON Parsing & Cloning function safeJsonParse(jsonString) { return JSON.parse(jsonString, (key, value) => { if (key === "__proto__" || key === "constructor" || key === "prototype") { return undefined; // Strip dangerous prototype keys } return value; }); }

// Or create dictionary objects with null prototypes: const safeLookup = Object.create(null);


3. JSON Bomb & Resource Exhaustion (DoS)

A "JSON Bomb" is a tiny payload that consumes exponential computational resources or triggers a stack overflow:

jsonCode Example
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[...10,000 brackets...]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
  • A recursive descent parser attempting to validate 15,000 nested brackets will exceed the maximum call stack size, crashing the worker process instantly.
  • Similarly, a 50 MB payload containing a single string of repeated spaces can exhaust regex tokenizers.

Defense Mechanisms: 1. **Enforce Maximum Request Body Lengths at the Gateway:** Reject any request exceeding your strict threshold (e.g. 1 MB for user endpoints, 10 MB for file uploads). 2. **Limit Nesting Depth:** Reject documents exceeding 30 levels of recursion.


4. Parser Differential Attacks

What happens when an API Gateway checks permissions using one parser, but the downstream microservice parses the payload with another?

jsonCode Example
{
  "account_id": "victim_123",
  "account_id": "attacker_456"
}
  • RFC 8259 states: *"The names within an object SHOULD be unique"*, but does not enforce a hard error.
  • Go `encoding/json`: Overwrites with the last key (attacker_456).
  • Python `json`: Overwrites with the last key.
  • Some C/C++ parsers: Preserve the first key (victim_123).
  • Security Result: The gateway authorizes the request based on the first key, but the database updates the record based on the second key.

Mitigation: Configure your JSON Schema validators to reject duplicate keys strictly.


5. Unicode Normalization & Homoglyph Spoofing

JSON supports full Unicode escaping (\uXXXX). Attackers exploit visual homoglyphs or non-normalized characters to bypass string filter blocklists:

  • "adm\u0069n" vs "admin"
  • Cyrillic а (U+0430) vs Latin a (U+0061)

Always run string.normalize('NFKC') before validating against allowlists or checking sensitive authorization strings.


6. Production Defense Checklist

  • ✓Reject keys named __proto__, constructor, and prototype.
  • ✓Configure Gateway payload size limits (e.g. client_max_body_size 2M in Nginx/Cloudflare).
  • ✓Reject JSON structures with depth > 32 layers.
  • ✓Strictly forbid duplicate object keys via JSON Schema or linter assertions.
  • ✓Use integer string representations for 64-bit IDs (Snowflake IDs) to prevent float truncation.
  • ✓Sanitize Unicode input using NFKC normalization.
LT

Lintify Engineering Team

Application Security & Cryptography

Lintify publishes in-depth engineering references for data format interoperability, stream processing, parser security, and API infrastructure. All tools on Lintify run purely browser-side with zero data collection.