blobforge

Adversarial fixtures

break your json parser

12 JSON documents engineered to fail. Duplicate keys, __proto__ as a key, integers past MAX_SAFE_INTEGER, lone surrogates, a thousand levels of nesting — each isolating one failure, with the correct behaviour documented next to it.

Built in your browser. Nothing is uploaded, and no signup is required.

0Passed
0Failed
12Untested

UTF-8 byte order mark before the document

encoding-bom-utf8.json

What this tests

A UTF-8 BOM precedes the opening brace.

What a correct parser should do

Strip the BOM, or reject with an encoding error. RFC 8259 says implementations MUST NOT add a BOM and MAY ignore one — so this file is legal to reject. What it must not do is produce the confusing `Unexpected token  in JSON at position 0`, which is what JSON.parse gives you when the bytes are decoded without stripping it.

Bytes · 25 B
00000000EFBBBF7B226964223A312C226E616D65...{"id":1,"name
00000010223A22416461227D0A":"Ada"}.
Hover a byte to see why it matters.
  • Byte order mark
  • Line feed
  • Double quote
  • Delimiter

How to use these fixtures

  1. Download a single file, or take all 12 as a ZIP — the archive includes a README explaining every file.
  2. Run each one through your own JSON import path.
  3. Come back and record whether your parser handled it. Results are kept in your browser, so leaving the page is expected.
  4. Copy the damage report as Markdown and paste it into a pull request or an issue.

Why JSON parsers fail

JSON looks far better specified than CSV, and mostly is. But the spec deliberately leaves gaps, and JavaScript fills them quietly rather than loudly. JSON.parse accepts a duplicate key and keeps the last one. It accepts 9007199254740993 and returns a different number. It accepts an unpaired surrogate and hands back a string that is not well-formed Unicode.

None of those raise an error, which is what makes them dangerous. The failure appears later — at the database write, at the API boundary, or in a service that made a different choice about the same gap. Twitter and Discord both ship string ids specifically because of the integer case.

Questions

JSON is well specified — what is there to get wrong?
RFC 8259 explicitly leaves several behaviours to the implementation: what to do with duplicate keys, how much nesting to accept, and how to represent numbers that do not fit a double. None of those produce a parse error in JavaScript, so the bug surfaces later as wrong data rather than as a failure.
Does JSON.parse protect me from prototype pollution?
JSON.parse itself is safe — it creates plain objects and does not invoke setters. The danger is what your code does afterwards: a recursive merge, deep clone or Object.assign loop that walks the parsed object can write to Object.prototype and change behaviour for every object in the process.
Are these files dangerous?
No. They are inert test files for checking your own import pipeline. Nothing here executes on its own — the fixtures that model injection or traversal exist so you can verify your own code rejects them, and the resource-exhaustion ones are deliberately scaled down so they demonstrate the behaviour without taking down the machine you are testing from.
Why does the page show raw bytes?
Because most of these cases are invisible in a text preview. A byte order mark renders as nothing, a bare carriage return looks identical to a CRLF, and a NUL looks like the end of the string. The hex view highlights exactly which bytes matter and explains each one when you hover it.
Does my pass/fail progress get saved?
Yes, in your own browser only, and separately for each format. The workflow expects you to leave the page, run a fixture through your parser, and come back — so results persist locally. Nothing is uploaded, and clearing site data clears them.
Is this free?
Yes. Every fixture is generated in your browser, with no signup and no upload.