Skip to content

Build1 publisher2 min readPublished

A Firefox extension arms itself five seconds after install from a lookalike Google domain

The add-on shipped to Mozilla's store as a dispatcher and took its instructions afterwards from a page it opened itself, on a domain built to resemble googleusercontent.com.

The Engineer · Build desk

What happened

  • Socket's Threat Research team found a Firefox extension, [email protected], sold as a utility for identity verification before opening protected PDF documents.
  • The add-on reached the Firefox Add-ons store on September 3, 2026, and the malicious functionality first appeared in version 1.4 on September 11, aimed at Portuguese- and Spanish-speaking users.
  • Mozilla's store carried three files: manifest.json, content.js and background.js. None of them held a target URL, an exfiltration endpoint or credential-stealing logic.
  • The malicious behaviour arrives after install as data written into browser.storage.local: which network requests to watch, which headers to read, which function to call, which code to inject.
  • Once armed, the extension injects an account-takeover script into real accounts.google.com pages and captures the session cookie plus, when Google prompts for one, a password reset value the attacker controls.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint Deciding this case takes installing the add-on and watching what it fetches. A review queue is doing a different job.
  • decision Allowlisting add-ons by extension ID hands the decision to whoever publishes the next version under that ID. An entry has to pin a version to mean anything.
  • capability The arming step is a DNS lookup and an HTTPS fetch to a lookalike domain. Egress filtering and DNS logging get a chance at this extension that the store review did not.
  • exposure The same content script that bridges page messages into the privileged worker runs on every google.com page the victim opens, so the worker is reachable from more than the attacker's own landing page.

The design rests on one expression in background.js. Socket quotes it as `const _call = (path, ...args) => path.split('.').reduce(...)(...args)`, a helper that resolves any global by a dotted string and invokes it [7]. The name of the global arrives later, as text.

It arrives over a bridge the extension opens itself. The landing page loads a module from attacker infrastructure, `/loginSdk/assets/index-BhOgWOaO.js` [17]. That module calls `window.postMessage` with `["ext", [1, "browser.storage.local.set", "browser.runtime.reload", <config>]]` [18]. content.js is injected into that page too, because the manifest matches `*.gusercontent.com`, and it forwards any message whose first element is `"ext"` to the privileged background worker [16]. The worker's handler for `m[0] === 1` runs `_call(m[1], m[3])`, which is `browser.storage.local.set` with the attacker's config [19]. The storage read at the top of background.js, empty at install time, now returns something [6]. Socket's Karlo Zanki wrote that "A store reviewer or static scanner sees only a content-free dispatcher; there is nothing to flag until the extension is armed at runtime" [9].

Two statements in the post sit awkwardly beside each other. Socket says the shipped files contain no hardcoded malicious code and no target URLs [5]. The other is that `browser.runtime.onInstalled` opens an active tab to pdf.gusercontent.com/oninstalled after a five-second delay [14]. That URL is in the shipped code, and Socket says the domain was chosen to resemble Google's googleusercontent.com [15].

Static review reached the loader but never the config. To stop this in the review queue, a reviewer would have had to treat a lookalike domain in an install handler, plus a dotted-string invoker, as disqualifying on their own. Socket's list stops short of that: the content script matches on `*.google.com/*` at `document_start`, the `webRequest` and `storage` permissions, and a content.js patch that makes `PublicKeyCredential` always report a platform authenticator as available are each called unusual and individually inconclusive [10][11][12][13].

Version pinning is where the allowlist argument lands. [email protected] was in the store for eight days before 1.4 [22]. An allowlist entry keyed to that ID and written the week the add-on appeared would have admitted the armed version. Socket says the extension does not have a significant user base and expects impact to be fairly low, and did not disclose an install count [21][23].

What to watch

  • Whether Mozilla pulls the listing, and whether the same ID ships a 1.5 with the install-time loader intact.
  • Whether pdf.gusercontent.com keeps serving /loginSdk/assets/index-BhOgWOaO.js, since the chain stops when that fetch fails.
  • Whether the same content-free dispatcher and install-time loader turn up under other add-on IDs.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories