Poisoned Pipeline / Incidents / AS336
Firefox wallet impersonators shipped a review-time dead config and the live stealer behind it
Socket published this on 27 October 2026. It found three Firefox Add-ons
impersonating crypto wallets — Phantom, Jupiter and Bitget Wallet — all
live on addons.mozilla.org during the analysis and removed by publication.
Each was published from its own throwaway Mozilla developer account, which
spreads the takedown work: anonymous-30b17a249a34fdf5d2be64b3dfcc8494 for
Phantom, anonymous-3efb89873d4c425c012cd1cb1736629a for Jupiter and
anonymous-ca2bf8b1ba371a1426c1049d9dad8168 for Bitget.
The listings are brand copies rather than lookalikes. The Phantom listing's
display name is built from Unicode homoglyphs that render on the page as
"Phantom"; it reuses the real ghost icon and marketing copy, including the
heading "OFFICIAL PHANTOM WALLET (Firefox Update)". The Jupiter listing
renders as "Jupiter" and claims to be "Built by Jupiter Exchange". The
Bitget package is named TabFlow Pro in its manifest while the listing shows
Bitget Wallet branding. The Phantom listing's review count rose from 275 to
546 and its average rating from 2.9 to 3.9 in about two days, pushing the
one-star reviews in which users report losing funds further down the page.
All three declare that the developer does not collect data, and the Phantom
listing supplied no privacy policy, while requesting access to browser tabs
and to data for all websites.
Every one of the three packages carries a complete stealer inside the signed
code Mozilla reviewed; Socket's scanner rated all three 10 out of 10.
Phantom's is analytics.js, wired into its own popup and onboarding pages.
Jupiter ships a 621 kB trojanized background.js that posts the mnemonic and
private key on wallet import, plus a hook.js that reads seed phrases and
keys from page inputs and the clipboard. Bitget ships static/js/hook.js and
a background worker, bg-init.js, that hooks the wallet's own storage to lift
the seed as it is decrypted and overrides tab creation to funnel the victim
into the local import screen. All of them post to a brand-named subdomain of
a single apex, bonto.io: phantom.bonto.io, jupiter.bonto.io and
bitget.bonto.io.
Only Phantom adds a remote layer, a loader appended to
background/serviceWorker.js. It rebuilds its hostname from a character-code
array that decodes to phantom.bonto.io, fetches /config with cache
no-store, requires both an active flag and a base64 code field, and runs
the decoded payload with scripting.executeScript in the MAIN world — which
gives it the page's own injected wallet provider — falling back to the
isolated content-script world. It re-injects on every tab load, on install
and on browser startup, and caches the payload in storage.local under _px.
At publication the endpoint returned active: true with a 4,029-byte
payload.
The point of that layer is the review. The Phantom package also ships
server.js, a Node.js drainer backend that logs captured secrets to local
files, forwards them to a Telegram bot and sweeps funds to hardcoded
Ethereum, BSC, Polygon, Arbitrum, Optimism, Base, Avalanche, Solana and
Bitcoin addresses, and server-review.js, a stripped build of the same
server that returns an inactive config during Mozilla's review. A comment
in server.js says the payload reaches the extension only "after approval
flip". The endpoint can therefore be inert while the add-on is examined and
live afterwards, with no further submission to Mozilla.
The captured strings are classified rather than blindly forwarded: the
stealer recognises BIP-39 phrases of 12, 15, 18 or 24 words, EVM keys as an
optional 0x prefix plus 64 hex characters, and Solana keys as 87 to 88
base58 characters. It reads every input and textarea value, listens for
paste and focusout, and scans page text for a numbered recovery-phrase grid
of the kind a wallet shows on its reveal-secret-phrase screen. Running in
the main world it also wraps window.phantom.solana.connect to capture the
connected public key. Captures are de-duplicated and posted as JSON with
keepalive, with an XMLHttpRequest fallback.
Every exfiltration point is a subdomain of bonto.io behind Cloudflare.
Probing the apex for other brand names returned provisioned
coinbase.bonto.io and exodus.bonto.io hosts answering with the same
signature, so the same infrastructure also targets Coinbase Wallet and
Exodus, though no AMO listings for those brands were found. Socket does not
attribute the cluster. The Phantom and Jupiter packages also ship a
CLAUDE.md file that the extension never loads, containing an AI-assistant
jailbreak prompt. Daily user counts reported by AMO were between one and
three per listing at publication; the loss reports in the reviews are
self-reported and unverified.
Mapped techniques
- T0108 Accounts in public registry
- T0109 Publish malicious artifact
- T0110 Advertise malicious artifact
- T0136 Brandjacking
- T0141 Fake developer reputation (Starjacking)
- T0154 Malicious IDE extension
- T0220 Deliver the payload only after artifact review
- T0159 Malicious artifact execution
- T0184 Harvesting sensitive information from files
- T0156 Exfiltration over webhooks
- T0201 Customers compromised
supply-chain Firefox Add-ons listings impersonating Phantom, Jupiter and Bitget Wallet
Three throwaway Mozilla developer accounts, one per listing, each
publishing a single brand impersonation. Separate accounts mean a
takedown of one listing does not reach the others.
The signed add-ons were published to addons.mozilla.org and were
live there during Socket's analysis: add-on ids 3092199 (Phantom,
version 25.6.0), 3092666 (Jupiter, 1.19.2) and 3092059 (Bitget /
TabFlow Pro, 2.21.8).
Store search is the distribution channel: the listings are named,
described and rated to rank against the wallets they copy, and the
Phantom listing's rating was inflated to 3.9 across 546 reviews
before publication.
Homoglyph display names (the Phantom listing is built from
characters that render as "Phantom"), the genuine icons, the real
marketing copy and a claim of being "Built by Jupiter Exchange".
The Bitget package hides the brand behind a manifest name of
TabFlow Pro.
Review count doubled from 275 to 546 and the average rating rose
from 2.9 to 3.9 in about two days, which moves the one-star
reports of lost funds down the page. The technique is written
around star counts and unvalidated repo links; here the same
reputation signal is manipulated inside a store listing.
Browser-extension analogue, as on AS60: an add-on rather than an
IDE extension, with access to tabs, all-site page data and script
injection into the pages the victim visits.
The Phantom package ships server-review.js, a stripped server that
answers the loader's /config request with an inactive config while
Mozilla reviews the add-on, and server.js, the live drainer
backend, with a comment naming the "approval flip". The signed
code is what was reviewed; what it becomes is decided by a server
response the reviewer never sees.
post-supply-chain Wallet users who installed an impersonating add-on
The stealers run as part of the installed extension — Phantom's in
its popup and onboarding pages, Jupiter's in a background worker
and a content hook, Bitget's in its background worker — and the
Phantom loader re-injects on every tab load, install and startup.
Recovery phrases and private keys are lifted from the wallet UI:
every input and textarea, paste and focusout events, a numbered
recovery-phrase grid in page text, and Bitget hooking the wallet's
own storage to read the seed as it is decrypted.
Captures go out as JSON POSTs to brand subdomains of bonto.io, and
Phantom's bundled server.js forwards them to a Telegram bot
(chat -5433023573) alongside writing them to local files.
A recovery phrase or private key is a bearer secret: whoever holds
it controls the wallet and can move everything in it. Phantom's
backend sweeps to hardcoded addresses on Ethereum, BSC, Polygon,
Arbitrum, Optimism, Base, Avalanche, Solana and Bitcoin; loss
reports in the listings' own reviews are self-reported and
unverified.
Framework gaps noted
- The drainer backend is bundled inside a browser extension — a Node.js server that logs secrets, messages Telegram and sweeps nine chains to fixed addresses. No technique covers an operator backend shipped as a file in the artifact, so T0156 carries the Telegram path and T0201 the fund movement.
- Rating inflation on a store listing is mapped to T0141, whose text is about star counts and unvalidated repository links. Store review counts are the same reputation signal in a different surface, and the catalogue has no separate technique for review manipulation.
- Homoglyph names and a copied icon on a store listing are mapped to T0136, which is written around package and container naming. The mechanism is the same brand impersonation; only the surface differs.
- Socket does not attribute the cluster, and nothing links it to the earlier Firefox wallet campaign on AS60 — different infrastructure (brand subdomains of bonto.io against Cloudflare Workers hosts), different wallets copied (Phantom, Jupiter and Bitget against Rabby and OKX) and no shared indicator.
- Reach at publication was small — one to three daily users per listing according to AMO — and the loss reports are unverified user reviews, so the reported theft is not established by first-party data.
- The CLAUDE.md jailbreak prompt shipped in the Phantom and Jupiter packages is never loaded at runtime. It indicates AI-assisted authoring and an attempt to subvert AI-assisted review; it is not mapped as a stage.
- coinbase.bonto.io and exodus.bonto.io answer with the same signature as the confirmed exfiltration hosts, which suggests two more target brands, but no listings for them were found.