The JSON Formatter Adware Incident Is the Browser Extension Trust Model Working As Designed
Source: hackernews
If you have the JSON Formatter extension installed in Chrome, remove it now. The popular developer utility created by Callum Locke has been taken over and is injecting adware. The HN thread hit 262 points and 126 comments within hours, and the response was the usual mix of technical postmortems and resigned frustration from developers who had trusted the extension for years.
This story is worth examining carefully, because the incident is not a surprise or an anomaly. It is what the browser extension model produces, reliably, when an extension gains enough users.
Why Developer Tools Are the Best Target
From an attacker’s perspective, a JSON formatter extension is a near-perfect acquisition. The user base skews heavily toward software engineers, who tend to have access to internal APIs, staging environments, production credentials stored in browser cookies, and authentication tokens that appear in JSON response bodies. When a developer hits an API endpoint in the browser, the extension sees the full response, including any tokens, user IDs, or sensitive data the API returns.
Beyond the user profile, a JSON formatter needs <all_urls> permissions to function. The extension must intercept responses from any domain to detect and reformat JSON, so there is no way to scope it down. You grant it access to every page you visit, and that permission persists silently across every update the extension receives.
An extension like this with two million developer users is worth real money. Adware networks pay by the user for access to browsing behavior, affiliate link injection, and session data. At even conservative per-user revenue estimates, a takeover pays back an acquisition price within months.
The Mechanics of a Takeover
The sequence is consistent across every documented case. The original developer stops actively maintaining the extension. The Chrome Web Store version sits dormant, accumulating installs, while the GitHub repo collects dust. Then someone approaches the developer with a purchase offer.
Google’s Chrome Web Store allows extension ownership to transfer between developer accounts with no public disclosure, no notification to existing users, and no review of the new owner’s stated intentions. Once the transfer completes, the new owner pushes an update. Chrome auto-updates extensions silently. Within 24 to 48 hours, the malicious version is running on every existing install.
The malicious update typically does not break the core functionality. JSON formatting still works. The adware behavior is designed to be subtle: affiliate link hijacking on e-commerce sites, browsing data transmitted to a collection endpoint, or a small injected script loaded from an external CDN. The external script approach was particularly common in Manifest V2 extensions because it allowed behavior changes without shipping new code to the Chrome Web Store, avoiding repeated review.
This Has Happened Before, Many Times
The Add to Feedly extension was sold in 2014 for $100,000 and immediately began injecting affiliate links. That case prompted the first wave of serious discussion about the problem. The discussion concluded, nothing structural changed, and the pattern continued.
The Great Suspender, a tab management extension with over two million users, was sold and infected with obfuscated malicious code. Google eventually took the unusual step of remotely disabling it in browsers, but not before the malicious version had run for months.
Nano Adblocker and Nano Defender, forks of uBlock Origin with hundreds of thousands of users, were sold in 2020. The new owners pushed an update that collected session data from social media accounts. The original uBlock Origin author discovered and publicized it.
The Cyberhaven breach in late 2024 compromised a data loss prevention extension used by major financial institutions, specifically targeting Facebook advertising accounts and AI platform credentials. That incident was a phishing attack on the developer’s account rather than a sale, but the delivery mechanism was identical: a silent auto-update to an established, trusted extension.
Every few months, a new version of this story surfaces. The details change; the structure does not.
The Fundamental Problem
A browser extension is not a website you choose to visit. It is a privileged software agent that runs persistently in your browser, executes on every page you load, and updates itself without asking. The mental model most users have, treating an extension as a one-time install decision, does not match what extensions actually are: a long-lived, auto-updating, highly-privileged process that you extend trust to indefinitely.
Google introduced Manifest V3 partly to address this attack surface. MV3 blocks remotely-hosted code, which prevents one class of injection attack. It also limits the webRequest blocking API, which reduces the ability to intercept and modify responses. But MV3 does not address ownership transfers, does not require user notification on ownership changes, and does not prevent malicious code from being shipped directly in the extension package. The Cyberhaven attack used MV3-compatible techniques without issue.
Firefox has had a native JSON viewer built into the browser since Firefox 44. No extension required. When you navigate to a URL that returns JSON, Firefox parses and renders it with syntax highlighting and a collapsible tree. This is the correct architectural answer for a feature like JSON formatting: build it into the browser, where it cannot be hijacked, rather than delegating it to a third-party process running with <all_urls> permissions.
Chrome’s DevTools Network tab also renders JSON responses in the Response panel for any intercepted request. For API development work, this is often sufficient and requires no extensions at all.
Practical Steps
For individual developers, the immediate action is uninstalling the json-formatter extension. Beyond that, the useful habits are:
Audit your installed extensions. Remove anything you do not actively use. Extensions you installed two years ago and forgot about are a liability.
Pay attention to permissions. An extension that requests <all_urls> has access to every authenticated session in your browser. That is a high bar that few utilities actually need.
Use browser-native or dedicated alternatives where they exist. Firefox’s built-in JSON viewer is the obvious replacement here. For API development, tools like Bruno or HTTPie keep HTTP work outside the browser entirely. For terminal use, curl https://api.example.com/endpoint | jq . formats and highlights JSON without touching your browser at all.
For teams and organizations, the risk is more serious. Developers with this extension installed may have exposed internal API responses, authentication tokens, and session data. Enterprise Chrome policy allows whitelisting specific extension IDs and blocking all others, which is the only reliable mitigation in a managed environment.
What Google Could Actually Do
Notifying users when extension ownership transfers would help. A simple in-browser prompt saying “The developer of this extension has changed. Review the extension before continuing” would catch most opportunistic acquisition attacks.
Versioned extension publishing with visible diffs would help more. The npm registry at least shows package owners; it does not show you diffs of what changed between versions, but some third-party tools do. Chrome provides nothing comparable.
Neither of these requires abandoning the extension model or breaking developer workflows. They require Google to treat ownership transfer as an event worth surfacing to users, rather than a silent administrative action.
Until then, every dormant extension with a large install base is a potential supply chain attack waiting for a buyer. The json-formatter incident will not be the last one.