Is Plug safe?

Medium risk

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.

Plug Developersv2.18.1Chrome Web Store
45Risk
Who publishes it

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.

Publisher
Plug Developers

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
What actually happens
You did this

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 did this

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.

Captured request
POSThttps://www.google-analytics.com/mp/collect?measurement_id=G-6RZR3MVKZS&api_secret=<redacted>

HTTP 204 No Content, GA Measurement Protocol accepted the event.

Headers
Content-Type
application/json
Body
{  "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"      }    }  ]}
GA event parameters sent per transaction type (from code analysis)
  • Persistent wallet UUID
    f8245113-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 UUID
    8f601a61-a8f6-4aaa-8d68-fab9dcfea241

    A fresh UUID per browser session, used by GA to group events within a visit.

  • Timezone region
    America/New_York

    Your browser timezone, used by Google to infer geographic region.

  • Locale identifier
    USA

    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 amount
    0.025

    The quantity of tokens involved, converted to decimal form. Sent for swaps, token sends, stakes, mints and borrow/lend events.

  • Swap provider
    ICPSwap

    Which DEX or bridge service was used (e.g. ICPSwap, OneSec, Odin). Sent for every swap event.

The code that does this

GoogleAnalytics class and swap event call site, main-ed614665.js

Readable version

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)});
Destination
    • 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.

Updated 30 September 2026cfbfdhimifdmdehjmkdobpcjfefblkjm