Is Plug safe?
Plug transmits financial transaction details and a persistent user ID to Google Analytics, and exposes multiple third-party API keys in a web-accessible script any page can read.
On every swap, token send, stake, mint, or borrow action, Plug sends the transaction type, token names, amounts, and a persistent UUID stored in chrome.storage.local to Google Analytics via the Measurement Protocol. Separately, a web-accessible JavaScript file bundled with the extension contains plaintext API keys for Infura, QuikNode, Tatum, Etherscan, LI.FI, WalletConnect, and SoChain — any website can fetch this file and extract the keys.
Who publishes itPlug Developers - no other listings under this identity
Plug Developers - no other listings under this identity
What this publisher told the store about itself, and the other listings that told it the same thing.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Plug Wallet reports financial transaction details to Google Analytics
Every time you swap, send, stake, mint, borrow or lend through Plug wallet, it sends transaction details (token, amount, provider) to Google Analytics, tied to a persistent identifier that lets on-chain activity accumulate there.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Dynamic sandbox
You complete a token swap, send, stake, mint, or borrow inside Plug Wallet.
The action fires the relevant handler inside main-ed614665.js.
The extension POSTs a telemetry event to Google Analytics including the token type, amount, swap provider and your persistent wallet-session identifier.
The POST goes to www.google-analytics.com/mp/collect without notifying the user.
HTTP 204 No Content, GA Measurement Protocol accepted the event.
- Content-Type
- application/json
{ "client_id": "f8245113-09a5-45ef-ae8a-92bfe07fef17", "user_properties": { "registered": { "value": false }, "region": { "value": "UTC" }, "locale": { "value": "USA" }, "language": { "value": "en-GB" }, "platform": { "value": "extension" }, "version": { "value": "2.16.3" } }, "events": [ { "name": "page_view", "params": { "session_id": "8f601a61-a8f6-4aaa-8d68-fab9dcfea241", "engagement_time_msec": 100, "page_title": "backup_seed", "page_location": "/wallet/setup/backup-seed" } } ]}- Persistent wallet UUIDf8245113-09a5-45ef-ae8a-92bfe07fef17
A random UUID generated once and stored permanently, linking every transaction across sessions to one identifier in Google's systems.
- Session UUID8f601a61-a8f6-4aaa-8d68-fab9dcfea241
A fresh UUID per browser session, used by GA to group events within a visit.
- Timezone regionAmerica/New_York
Your browser timezone, used by Google to infer geographic region.
- Locale identifierUSA
The locale ID stored in the wallet (e.g. country or language code).
- Token symbol (swap: from/to)ICP → ckBTC
The tokens involved in a swap, both the token you spent and the token you received.
- Transaction amount0.025
The quantity of tokens involved, converted to decimal form. Sent for swaps, token sends, stakes, mints and borrow/lend events.
- Swap providerICPSwap
Which DEX or bridge service was used (e.g. ICPSwap, OneSec, Odin). Sent for every swap event.
GoogleAnalytics class and swap event call site, main-ed614665.js
GoogleAnalytics class — readable form
class GoogleAnalytics { debug; clientId; // persistent UUID from chrome.storage.local sessionId; // per-session UUID constructor(clientId, sessionId, debug = false) { this.debug = debug; this.clientId = clientId; this.sessionId = sessionId; } async fireEvent(eventName, eventParams, userProperties) { // Wrap each user_property value in {value: ...} as GA4 MP expects const wrappedProps = userProperties && Object.fromEntries( Object.entries(userProperties).map(([k, v]) => [k, { value: v }]) ); const endpoint = (this.debug ? GA_DEBUG_ENDPOINT : GA_ENDPOINT) + `?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`; await fetch(endpoint, { method: 'POST', body: JSON.stringify({ client_id: this.clientId, user_properties: wrappedProps, events: [{ name: eventName, params: { session_id: this.sessionId, engagement_time_msec: 100, ...eventParams } }] }) }); }}Swap event call site — readable form
fireEvent(GAEventName.SWAP, { type: 'swap', provider: selectedProvider.provider, // e.g. 'ICPSwap' from_token: fromToken.symbol, // e.g. 'ICP' to_token: toToken.symbol, // e.g. 'ckBTC' amount: Number(swapAmount), amount_received: receivedAmount / (10 ** toToken.decimals)});- www.google-analytics.com
Google Analytics 4 Measurement Protocol, receives transaction telemetry events linked to a persistent per-user UUID. Data is retained and processed by Google LLC.
Where it sends data
Destinations our analysis observed Plug Wallet contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.
- www.google-analytics.comwidely used
Plug Wallet sends data to www.google-analytics.com. A widely used service: 346 other extensions we have analysed send data here.
- sentry.io
Plug Wallet sends data to sentry.io. No other extension we have analysed sends data here.