The Word 'Toad' Gave Any Website Full Control of Chrome's Most Popular VPN - Am I Being Pwned?
← Back to blogUrban VPN is the most popular VPN extension on the Chrome Web Store, with approximately 9 million active users across Chrome and Edge1. Until last week, any website could control it.
Any site could disconnect the VPN, reroute traffic through Russia, disable every "security" feature, kill your other proxy/VPN extensions and force you into data collection you'd opted out of.
TL;DR. Any website could silently send commands to Urban VPN's Chrome extension without origin verification. The only "authentication" was two publicly known strings: the extension ID and the word Toad, hardcoded in the source. We also found the "Opt out of data collection" toggle is inverted in code - when it shows ON, you're opted in. Fixed in 5.12.5 (21 May 2026). CVSS 8.32 | CVE pending.
The Exploit
A web page includes this JavaScript. The user's VPN silently disconnects:
window.postMessage(<br>extensionId: "eppiocemhmnlbhjplcgkofciiegomcon", // public Chrome Web Store ID<br>sender: "Toad", // hardcoded "password"?<br>message: {<br>type: "Toad.FromToad",<br>toadName: "Exploit",<br>payload: {<br>to: "Mario",<br>message: { type: "LocationProcessor.Disconnect" }, // the command<br>},<br>},<br>},<br>"*",<br>);
The user sees nothing, their VPN disconnects and their real IP is exposed.
The boilerplate never changes. Swap LocationProcessor.Disconnect for any of the 20+ exposed commands, and that command runs instead.
How It Works
Urban VPN's extension deliberately sets up a postMessage listener - a channel that lets any script on any page you visit send it messages.
Extensions that do this are supposed to verify who's sending, checking that messages come from a trusted origin. They're not the only ones to make this mistake, Multipassword has a similar problem, although they were leaking full account credentials.
Urban VPN performs no origin verification. Instead, it checks two static values:
Is extensionId set to eppiocemhmnlbhjplcgkofciiegomcon? (The extension's public Chrome Web Store ID. Visible to anyone.)
Is sender set to Toad? (A string hardcoded in the source code.)
Pass both and the command executes. Here's the actual handler from the extension's content script (deobfuscated from the bundle):
onFromToadMessageHandler = ({ data }) => {<br>const wrongExtension = data?.extensionId !== chrome.runtime.id;<br>const wrongSender = data.sender !== "Toad";<br>if (wrongExtension || wrongSender) return;
const handlers = {<br>"Toad.FromToad": handleSync,<br>"Toad.FromToadAsync": handleAsync,<br>};<br>handlers[data?.message?.type]?.(data);<br>};
There's no event.origin check, so if any page passes those two if statements and the message is forwarded directly to the service worker.
POV: Nintendo's lawyers once they see Toad and Mario
What an Attacker Could Do
Your VPN connection:
Disconnect, exposing your real IP (LocationProcessor.Disconnect)
Reroute traffic through an attacker-chosen country, e.g. { code: "RU" } (LocationProcessor.Connect)
Add specific domains to the bypass list, selectively routing traffic outside the tunnel (BypassMessages.AddItem)
Your privacy settings:
Force opt-in to data collection, overriding your preference (DataCollectionStateMessage.Set)
Disable WebRTC leak protection, leaking your real IP while the VPN appears connected (WebRTCLeakPrevention.Toggle)
Your browser:
Disable other extensions - such as other VPNs or anything with the proxy permission (InterruptExtensions.DisableInterruptedExtensions)
Open arbitrary URLs in new tabs (Tab.OpenTab)
Reading your state (bidirectional):
Query VPN connection status (LocationProcessor.GetState)
List which extensions can be disabled (InterruptExtensions.GetInterruptedExtensionsList)
Read bypass list and data collection state (BypassMessages.GetList)
The async variants (Toad.FromToadAsync) make this a two-way control channel. An attacker can query your VPN status, confirm you're connected, disconnect you, then verify the disconnection succeeded. The extension responds via postMessage with no origin restriction on the response, so the attacking page reads it directly.
The Data Collection Angle
The commands above are concerning on their own. But one of them - DataCollectionStateMessage.Set - becomes significantly worse in context.
In December 2025, Koi Security reported that Urban VPN appeared to be capturing user conversations with AI chatbots - ChatGPT, Gemini, and Claude - in ways Koi Security assessed were not clearly disclosed to users. In our own analysis, we observed the extension POSTing visited URLs to servers operated by BIScience, including full OAuth callback URLs and search queries. Persistent tracking identifiers survived clearing cookies. The "sensitive data filter" referenced in Urban VPN's public response failed to redact any of seven sensitive parameters in our testing.
Now look at the data collection toggle in Urban VPN's settings:
The "Privacy Preferences" toggle in Urban VPN's...