In February 2018, Google Project Zero's Tavis Ormandy disclosed CVE-2018-6654 against Grammarly's browser extension: a hidden iframe named gr_-ifr accepted an action:"user" message from any origin at all, handing over an authentication token that let any website read a user's private documents. Grammarly patched it within a day, but the bug had shipped to an install base numbering in the tens of millions. That pattern of extension security vulnerabilities hasn't gone away. In January 2026, Anthropic patched its own Claude Chrome extension (v1.0.41) after a vulnerability disclosed in late December 2025 combined a wildcard *.claude.ai origin allowlist with a DOM XSS bug on one subdomain, enabling silent cross-site prompt injection. In May 2026, the Urban VPN extension shipped a fix (v5.12.5, CVSS 8.32) for a flaw where any website could issue privileged commands using nothing more than the extension's public ID and a hardcoded string, "Toad." These are not obscure toy extensions — they are mainstream products from well-resourced teams, and they all fell into one of three recurring vulnerability classes: permission over-scoping, insecure cross-context messaging, and devtools-style bridges that leak internal state. This piece walks through each class with the disclosed CVEs behind it.
Why does permission over-scoping keep happening?
Permission over-scoping happens because Manifest V2 and V3 both let developers request host_permissions far broader than any single feature needs, and the browser's install prompt does not push back. OWASP's Browser Extension Vulnerabilities Cheat Sheet lists broad grants like <all_urls> as one of the most common root causes it sees in extension security reviews, because a single overreaching permission line turns a minor logic bug elsewhere in the extension into a full cross-site data-exfiltration or clickjacking-adjacent primitive. The failure mode is almost always the same: a developer requests <all_urls> "to be safe" or because one edge-case feature touches an arbitrary page, and that grant then applies to every other script and message listener the extension ships, including ones written months later by someone who never revisited the original threat model. Chrome's Manifest V3 narrowed some background-script capabilities, but it did not change how host_permissions are declared or reviewed, so the underlying incentive to over-request remains. The fix isn't exotic — it's requesting the narrowest permission a feature needs and using activeTab instead of persistent host access wherever possible — but it requires deliberately auditing a manifest file that most teams write once and never revisit.
What makes extension messaging so easy to get wrong?
Extension messaging is easy to get wrong because postMessage and chrome.runtime.onMessageExternal are both origin-agnostic by default — the browser delivers the message regardless of who sent it, and it's entirely the developer's job to check event.origin before trusting the payload. The Grammarly case (CVE-2018-6654) is the canonical example: Ormandy's writeup, rated high severity, noted the listener performed no origin check at all, so a malicious page could just forge the same message format Grammarly's own scripts sent. Vue.js Devtools had a related bug in 2023, where an unauthenticated postMessage listener leaked base64-encoded screenshot data to any page that asked. The Urban VPN case shows the same root cause wearing a different disguise: the "authentication" was a fixed string embedded in the extension's own code, readable by anyone who unpacked the CRX — not a per-session secret. Microsoft's MSRC research team documented this exact anti-pattern more broadly in its August 2025 "postMessaged and Compromised" writeup, which found overly permissive postMessage trust models — including overly broad domain allowlists — behind multiple cross-tenant and token-forwarding flaws across Microsoft's own web services. In every one of these, the fix is the same one line: verify event.origin against an explicit allowlist before acting on message content.
Can a narrow origin allowlist still fail?
Yes — an allowlist narrows the attack surface but doesn't eliminate it if any single origin on that list has its own vulnerability. That's exactly what happened to Anthropic's Claude Chrome extension: disclosed on December 26, 2025 and patched at v1.0.41 the following month, the extension trusted messages from any *.claude.ai subdomain, which is a far smaller surface than "any origin" but still large enough that a DOM XSS bug on one subdomain gave an attacker a foothold inside the trusted zone. From there, the attacker could pass messages the extension treated as legitimate, enabling prompt injection without ever touching the extension's own code. This is a compound failure — over-broad trust boundary plus a bug in one trusted party — and it's a useful reminder that wildcard subdomain trust (*.example.com) inherits the security posture of every subdomain you don't control as tightly as the root domain. Scoping trust to the exact origin that needs it, rather than a wildcard pattern, removes an entire class of this risk.
Do extension-specific bugs beyond messaging matter too?
Yes — reflected XSS and other classic web bugs still show up inside extension surfaces, and they're often more damaging there because of the elevated privileges extensions run with. CVE-2024-0981, disclosed by Okta on July 22, 2024, was a reflected cross-site scripting flaw in the Okta Browser Plugin — a piece of software millions of enterprise users have installed specifically because it holds credential-adjacent trust. A reflected XSS bug that would be a moderate finding on a public marketing site becomes far more serious inside an extension that can read and fill login forms across a company's entire SaaS footprint. The lesson from Okta's case, and from the broader set of extension security vulnerabilities disclosed across 2024–2025, is that extensions need the same input-sanitization discipline as any web application — templating output correctly, avoiding innerHTML with untrusted strings — layered on top of the extension-specific concerns around permissions and messaging.
How does devtools-style tooling widen the attack surface?
Devtools and debugging bridges widen attack surface because they intentionally expose internal application state to page-level scripts, which is useful for developers and useful for attackers in equal measure. Snyk's research into React Developer Tools and Vue.js Devtools found both extensions exposed internal component state and messaging channels to the page itself, meaning a malicious page could potentially read data the extension's own bridge was never meant to hand to arbitrary websites. This class differs from the Grammarly-style bug in that the extension isn't necessarily missing an origin check on a privileged action — it's exposing a legitimate feature (inspecting component state) through a channel that any page on the internet can also reach, not just the developer's own devtools panel. The practical guidance is the same OWASP gives for permissions generally: any bridge that connects page content to extension-privileged code needs to assume the page is hostile, because on the open web, eventually one is.
How does Safeguard's own extension avoid these classes?
Safeguard's Chrome, Edge, and Firefox extension is built to sidestep all three classes by having almost nothing to exploit in the first place. Its Chrome and Edge manifest declares exactly one permission — sidePanel — and no host_permissions array at all, so there's no broad grant for a future bug to abuse. It has no background API calls, no local credential storage, and no custom message-passing logic between the extension and the page it embeds; the panel simply loads app.safeguard.sh/portal/search and the user authenticates inside that page using their normal web session, the same way they would in an ordinary browser tab. Because the extension doesn't implement a postMessage listener, an onMessageExternal handler, or any devtools-style bridge, entire categories of the vulnerabilities above — origin-validation bugs, wildcard trust boundaries, leaked internal state — simply have no code path to occur in. It's a useful illustration of the OWASP guidance in practice: the smallest permission footprint and the fewest custom messaging surfaces is still the most reliable way to keep an extension off a CVE list.