What happened in November 2025
JSONFormatter and CodeBeautify let you press “save” and get a link to your pasted text. Both also listed saved pastes on public “Recent Links” pages, and the links were easy to enumerate. Researchers at watchTowr Labs collected more than 80,000 of them (five years of JSONFormatter and one year of CodeBeautify) and found Active Directory and database credentials, cloud and CI/CD keys, private keys, personal data and more, from government, banks, healthcare and telecoms. Canary tokens they planted were used within days: people were already scraping the sites for secrets. Read the reports by BleepingComputer and Help Net Security.
Nobody hacked anything. The sites worked as designed: the text left the browser, was stored on a server and was reachable by address. Pasting a production config “just to make it readable” is a data transfer to a third party, and a “save” button turns it into publication.
How DevBench keeps your input in the tab
- The work is done by scripts on the page. The JSON parser, the hash functions (MD5, SHA-1, SHA-256, SHA-384, SHA-512, CRC32, HMAC), Base64, URL and JWT code are part of DevBench itself, written for it and checked against the official test vectors. Only two libraries come from elsewhere: js-yaml and PapaParse, loaded from cdnjs and verified by their hashes (Subresource Integrity), and only on the YAML & CSV tab.
- The page may not send anything. It declares its own security policy: connections only to fof.lol itself (for the offline cache) and to the analytics beacon, and forms cannot be submitted. Even a bug could not post your text to another server. The analytics beacon sees the address of the page without anything after the # sign, and nothing you type is ever in the address.
- No saved links, no history, no storage. Input and results exist only in the page’s memory and vanish when you close or reload the tab. What is remembered in this browser are settings: indent width, the algorithms you ticked, switches. Never text, keys, files or results.
- Files stay put. A file is read in pieces by a background worker and never uploaded; big files do not freeze the page.
- You can check. Open the Network tab of your browser’s developer tools and paste something: nothing is sent. The page also works with the network off, once opened. A hidden self-test at
#/selftestruns the test vectors in your browser.
JSON: format, validate, tree
Format indents with 2 spaces, 4 spaces or a tab; Minify removes all spaces; Sort keys orders keys A→Z at every level. The text is checked as you type. DevBench reads strict JSON (RFC 8259) and reports the first mistake with its line and column, the offending character marked in the input and a plain-words hint for the common slips: a trailing comma, single quotes, comments, unquoted keys, NaN and undefined.
It does not parse into JavaScript values and print them back, so nothing is changed on the way: 12345678901234567890 stays that (JavaScript would turn it into 12345678901234567000), 1.0 stays 1.0, string escapes stay as written, and repeated keys are kept and flagged. Escape string and Unescape string convert text to and from the inside of a JSON string literal.
The Tree view opens branches as you click (large arrays 300 items at a time). Click a key to copy its path such as $.items[2].name; the path and value buttons copy the path or the formatted value. Files of 10 MB and more are processed in a Web Worker, so the page stays responsive; the tree works up to 3 MB. Drop a file on the input or use Open file; a file that is not UTF-8 is read as Windows-1251.
YAML and CSV converters
JSON ⇄ YAML uses js-yaml with the YAML 1.2 rules: no and yes stay text instead of becoming booleans (the “Norway problem”), dates stay text, anchors and merge keys (<<) are resolved, a duplicate key is an error with its position, and several documents separated by --- become an array.
JSON ⇄ CSV uses PapaParse. Nested objects are flattened into columns a.b.c; arrays become a.0, a.1 or stay JSON in one cell; the columns are the union of all keys. Choose the delimiter (comma, semicolon for Excel in many European locales, tab, pipe) and whether every cell is quoted. UTF-8 with BOM makes the downloaded file open in Excel with Cyrillic and other letters intact. Defuse formulas prefixes cells that start with =, +, - or @, so a spreadsheet cannot run them. Back to JSON, a.b.c columns are rebuilt into objects, numbers and true/false are recognised only where they read back the same (007 stays text), and the delimiter is detected.
Base64 and data: URLs
Text is encoded as UTF-8, so Cyrillic and emoji come out right (the plain browser function btoa fails on them). Choose the standard alphabet or URL-safe (- and _, as used in JWT), padding with = or without, and lines of 76 characters (MIME). Decoding accepts both alphabets, line breaks and missing padding, and points to the first bad character.
With File or picture any file becomes Base64 and a Base64 text decodes back into a file; the result is shown as text if it is valid UTF-8 and as a hex dump with a Download button if not. Tick Add data: URL prefix to get data:image/png;base64,… ready for CSS or HTML; a pasted data: URL is parsed and, if it is a picture, previewed. Pictures are recognised by their first bytes, not by what a name claims. Base64 is about a third larger than the original.
URL encoding and parsing
Component encodes everything except letters, digits and - _ . ~ (right for one query value); Full URL keeps : / ? # & =; Form writes spaces as +. Decoding names the position of a broken %.
The parser splits an address into scheme, user, password, host, port, path and fragment and lists the query parameters in a table, in their order and with repeats. Edit any cell or add, delete and sort parameters; the address is rebuilt live with values encoded again.
Hashes and checking a download
Choose any of MD5, SHA-1, SHA-256, SHA-384, SHA-512 and CRC32, for text or a file, shown as hex or Base64. Tick HMAC and enter a key (text or hex) to get a keyed hash. Files are read in pieces with a progress bar, speed and a Cancel button, so a multi-gigabyte image is fine.
To check a download, paste the checksum from the publisher into Compare with the expected sum: a plain hash, a line from sha256sum, Base64 or an integrity value like sha384-…. DevBench picks the algorithm from the length, says Match or No match and highlights the row. A match means the file is the one the sum was made for; the sum itself must come from a place you trust, ideally another one than the download. MD5 and SHA-1 can be forged on purpose, so they only catch accidents; CRC32 is an error check, not security.
Reading a JWT
A JSON Web Token is three Base64URL parts: header, payload and signature. DevBench shows the header and payload as formatted JSON, colours the three parts, and turns the dates exp, nbf and iat into readable time in your zone and UTC with “in 2 hours” or “expired 3 days ago”, flagging an expired token, one that is not valid yet and one issued in the future. A date in milliseconds is pointed out.
Decoding is not verifying. Anyone can read a token and anyone can forge one, so the page always warns that the signature is not checked. For HS256, HS384 and HS512 you may enter the shared secret (as text, Base64 or hex) and DevBench checks the signature locally with the browser’s crypto. Tokens signed with a key pair (RS256, ES256, …) need the public key and a trusted library on your server. A token with alg: none is flagged: it has no signature at all. Five-part tokens are encrypted (JWE) and cannot be read without the key.
UUID, time, bases, entities, regex
- UUID v4 (random) and v7 (Unix time in the first 48 bits, so ids sort by creation time; ids made in the same millisecond keep rising), up to 1000 at once, in upper case, without hyphens or in braces. Paste a UUID to see its version, variant and, for v7, when it was made.
- Unix time: seconds, milliseconds, microseconds or nanoseconds are told apart by size; the date is shown in UTC, in any time zone of your browser’s database and in words. The other way, a date in a chosen zone becomes a timestamp, with summer time handled by the zone rules.
- Number bases 2, 8, 10, 16, 36 and your own, with numbers of any size (no 253 limit), prefixes
0x,0b,0oand separators. - HTML entities: encode only the dangerous characters, add common names such as
©, or write every non-ASCII character as a number; decode understands all named entities, and nothing in the text is executed. - Regular expressions (JavaScript): matches are highlighted, with numbered and named groups listed and an optional replacement. The test runs in its own worker and is stopped after two seconds, so a pattern with catastrophic backtracking cannot freeze the page.
Handy: Ctrl+Enter (⌘+Enter on a Mac) runs the current tool, files can be dropped into the input fields, and every tab has its own address (#/json, #/base64, #/hash…).
Limitations
- Your browser is still in the chain. Extensions can read what is on a page; keep secrets away from a browser you do not trust. DevBench cannot protect a compromised device.
- The YAML and CSV libraries are fetched from cdnjs the first time you use those tabs (and cached for offline use afterwards). Everything else needs no network at all.
- The JSON tree works up to 3 MB; larger files can be formatted, not browsed.
- JSON must be strict: JSON5, comments and trailing commas are reported, not guessed.
- Hashing in the browser is slower than a native tool (hundreds of megabytes per second for SHA-256 at best, tens for SHA-512); for a 50 GB image use
sha256sum. - CSV to JSON cannot tell an empty cell from a missing value, and JSON
nullbecomes an empty cell.
Frequently asked questions
Is DevBench really offline?
After the first visit the pages and scripts are cached by the browser, and everything except the YAML and CSV conversion works without a network. Those two libraries are cached the first time they are used.
Can the site owner see what I paste?
No: the text never leaves the page, and the page’s security policy forbids sending it anywhere else. You can confirm in your browser’s Network tab.
Why not just use my editor’s formatter?
You should, when you have one. DevBench is for a phone, a borrowed computer, a quick look at a token or checksum, or when you have nothing installed.
Why is my JSON “invalid” when my program accepts it?
Many parsers are lenient (comments, single quotes, trailing commas, NaN). DevBench follows the standard so that what it accepts, every parser accepts.
Is it safe to decode a production JWT here?
Decoding happens locally, so nothing is sent. Still, treat a live token like a password: it may grant access until it expires.
Which hash should I use?
SHA-256 for checking downloads and general use. MD5 and SHA-1 only when a site offers nothing else, and never for security.