Ly Gravity

The Bookmark Is the Attack Surface: Inside the FOMO Session-Hijack Phishing Chain

BitBoy โ€ข โ€ข DeFi

Your bookmarks bar is a trusted execution environment. Treat it accordingly.

On October 8, SlowMist's Cosine flagged a phishing campaign targeting the FOMO web client โ€” one that never asks for a seed phrase, never deploys a malicious contract, and never touches a private key. It asks the user to complete a fake human-verification check, then to drag a "verification token" into the browser's bookmarks bar. The dragged object is not a token. It is a javascript: URI. After two or three clicks, the victim's already-authenticated FOMO session is silently handed to the attacker, and the balances inside it are drained. No signature prompt. No hardware-wallet confirmation. No red banner.

Bookmarklets โ€” bookmarks whose URL uses the javascript: scheme โ€” predate the modern web. They were designed to let a user run a small script against the page they are viewing: a reader-mode toggle, a price extractor, a translation helper. The browser treats a bookmarklet click as a user-initiated action, and that designation carries enormous privilege.

FOMO's web client is a browser-based interface to a self-custodial account. Once a user authenticates, the application stores a session credential โ€” typically a bearer token in localStorage or a non-httpOnly cookie โ€” and reuses it to authorize subsequent API calls without re-prompting. This is a standard convenience pattern. It is also the exact assumption the campaign exploits.

The phishing kit's mechanics deserve to be stated plainly. The landing page mimics a Cloudflare-style interstitial โ€” the "Verify you are human" checkbox that a decade of bot-mitigation has trained every internet user to click without reading. The check "completes" only if the user drags a supplied element into their bookmarks bar. That element's payload executes in the origin of the page the user is currently on. If that page is fomo.com, the script runs with fomo.com's own privileges. There is no memory corruption, no unpatched CVE, no bypassed Content Security Policy. The attacker did not break into the application. They convinced the user to become the execution vector.

The two-to-three-click threshold is not arbitrary, and why it exists tells you more than any single indicator of compromise.

A bookmarklet fires on every click, so one execution is already enough to exfiltrate localStorage, enumerate document-readable cookies, and POST the session token to an attacker endpoint. Requiring two or three clicks implies a staged payload: first fingerprinting the environment, then confirming the token is still live, then committing the transfer. It also implies the attacker is optimizing for silence over speed.

I have audited this class of bug before. In late 2017, working as a senior developer at a major exchange, I traced the Ethereum congestion caused by CryptoKitties back to inefficient contract logic and published a post-mortem with fifteen specific optimization recommendations. The lesson was not that the network was fragile. It was that a system's failure mode is rarely where its designers were looking. In 2020 I mapped a governance flaw in Curve Finance that let whale wallets distort pool incentives, and published a risk assessment predicting a thirty-percent TVL drawdown if voting power stayed coupled to liquidity. Same lesson, different layer.

Here, the architecture in question is the boundary between a session and an action โ€” and in most browser wallets today, that boundary is effectively nonexistent.

Consider what actually protects a self-custodial account. A hardware wallet protects key material: the seed never leaves the secure element, and every transaction requires a physical confirmation. Excellent design. It is also entirely irrelevant to this attack, because no transaction is ever proposed to the signer. The malicious bookmarklet does not need to sign anything. It inherits an authenticated session and issues the withdrawal through the same API the legitimate client uses. From the backend's perspective, the request is indistinguishable from the user's own โ€” same origin, same token, same device fingerprint, often the same IP.

One detail matters for defenders: the drain is immediate and total, which means the attacker's infrastructure was pre-staged before the victim clicked. There is no negotiation window, no mempool delay long enough for a white-hat rescue, and no unfamiliar approval to notice in the wallet history. By the time anything appears on-chain, the funds are already moving.

Now stack the usual defenses against it and watch each one fail. Two-factor authentication? The session is post-2FA; the factor was satisfied at login, and the attacker is riding the credential that resulted. Content Security Policy? A javascript: bookmarklet is not an inline script, not an external script, and not an eval โ€” it is a user-initiated navigation, and CSP does not police the bookmarks bar. Anti-phishing lists? The bookmarklet has no URL reputation until it is clicked, and by then the payload is already in the page. Wallet-drainer detection? Drainers watch for malicious approve calls and permit signatures. This attack never touches either primitive.

The most underappreciated dimension is distribution. Bookmarks synchronize. Chrome, Edge, and Firefox replicate the bookmarks bar through a signed-in account, so a payload installed on one desktop can surface on a laptop, a phone, or a work machine โ€” automatically, silently, with no further user action. The attack has a propagation channel closer to a supply-chain compromise than a phishing page. And because it generates no on-chain transaction until the final drain, no block explorer, threat-intel feed, or on-chain analytics platform can see it coming. The entire pre-drain phase is invisible to the tools the industry built to detect theft.

There is a governance failure underneath the technical one. Browser wallets have spent a decade hardening the key layer โ€” secure enclaves, MPC threshold signing, passkeys, social recovery โ€” and comparatively little time hardening the authorization layer. Code is law until the economy breaks it; here, the code never breaks at all, it simply executes for the wrong operator. The session token remains a bearer instrument: whoever holds it acts as the user, with the user's full authority and none of the user's intent. The industry solved "who holds the key" and quietly deferred "what is this session permitted to do."

The reflexive response will be to blame the user. That is wrong, and it is also strategically useless. "Don't drag things into your bookmarks bar" is not a security control; it is a hope. The phishing page borrowed the visual grammar of a bot-check every user has been conditioned to complete, and framed the drag as verification rather than installation. That is not a lapse in user judgment. It is a designed ambiguity, and design beats education at scale every time.

The real blind spot is that the industry has been optimizing the wrong half of the threat model. We celebrate self-custody as a civil liberty โ€” and it is โ€” but self-custody only protects you if the signing surface is trustworthy. When the interface can be hijacked without a signature, the guarantee evaporates. A bearer session token is a private key with a friendlier name and no backup phrase. We hardened one and forgot the other.

The next generation of wallets will not be judged on key management. It will be judged on whether a session can be scoped, time-boxed, and bound to explicit intent โ€” so that a stolen token buys an attacker a read-only view instead of a withdrawal. Until then, assume your bookmarks bar is a threat vector and clear it the way you clear a suspicious contract approval. The question is no longer whether your keys are safe. It is whether the thing clicking "confirm" on your behalf is actually you.

Market Prices

BTC Bitcoin
$81,727.2 +0.04%
ETH Ethereum
$2,411.44 -0.93%
SOL Solana
$103.1 -1.71%
BNB BNB Chain
$720.2 -0.32%
XRP XRP Ledger
$1.29 -1.39%
DOGE Dogecoin
$0.0788 -2.16%
ADA Cardano
$0.2188 -2.23%
AVAX Avalanche
$9.78 -2.64%
DOT Polkadot
$1.1 -4.62%
LINK Chainlink
$11.94 -2.60%

Fear & Greed

53

Neutral

Market Sentiment

Event Calendar

{{ๅนดไปฝ}}
08
04
upgrade Solana Firedancer

Independent validator client goes live on mainnet

15
04
halving Bitcoin Halving

Block reward reduced to 3.125 BTC

28
03
unlock Arbitrum Token Unlock

92 million ARB released

18
03
unlock Sui Token Unlock

Team and early investor shares released

12
05
halving BCH Halving

Block reward halving event

22
03
unlock Optimism Unlock

Circulating supply increases by about 2%

10
05
upgrade Ethereum Pectra Upgrade

Raises validator limit and account abstraction

30
04
upgrade Celestia Mainnet Upgrade

Improves data availability sampling efficiency

Altseason Index

40

Bitcoin Season

BTC Dominance Altseason

Gas Tracker

Ethereum 28 Gwei
BNB Chain 3 Gwei
Polygon 42 Gwei
Arbitrum 0.5 Gwei
Optimism 0.3 Gwei

Market Cap

All โ†’
# Coin Price
1
Bitcoin BTC
$81,727.2
1
Ethereum ETH
$2,411.44
1
Solana SOL
$103.1
1
BNB Chain BNB
$720.2
1
XRP Ledger XRP
$1.29
1
Dogecoin DOGE
$0.0788
1
Cardano ADA
$0.2188
1
Avalanche AVAX
$9.78
1
Polkadot DOT
$1.1
1
Chainlink LINK
$11.94

๐Ÿ‹ Whale Tracker

๐Ÿ”ต
0x3d16...b291
12h ago
Stake
25,942 SOL
๐ŸŸข
0x5e8a...443c
5m ago
In
6,380,859 DOGE
๐Ÿ”ด
0x2792...b742
2m ago
Out
13,627 SOL

๐Ÿ’ก Smart Money

0x8963...7506
Institutional Custody
-$4.3M
76%
0x673f...60e9
Experienced On-chain Trader
+$4.6M
78%
0x250d...0e90
Market Maker
+$3.6M
75%

Tools

All โ†’