Is Ronin Wallet safe?

Medium risk

Ronin Wallet is medium risk. Ronin Wallet sends your wallet address and every transaction hash to Sky Mavis analytics automatically, no consent prompt on Chrome. A platform check enables this unconditionally on non-Firefox browsers, bypassing Firefox's gate.…

ronin-walletv2.12.0Chrome Web Store
45Risk

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

Wallet address and transaction hashes sent to Sky Mavis analytics on Chrome

Ronin Wallet sends your wallet address and every transaction hash to Sky Mavis analytics automatically, no consent prompt on Chrome.

A platform check enables this unconditionally on non-Firefox browsers, bypassing Firefox's gate.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You install and open Ronin Wallet on Chrome.

No opt-in or consent dialog is presented.

The extension did this

The background service worker begins posting your wallet address and transaction hashes to Sky Mavis analytics.

Tracking starts automatically; the consent gate present for Firefox is skipped on Chrome by a hardcoded platform check.

02EvidenceCODE COMPARE
The code that does this

Chrome/Firefox tracking fork in TrackingManager

What it actually does
Readable equivalent of the platform check
// On Chrome: isFirefox() → false → trackingConsentRequired = false
// On Chrome: _enableTrack = !false = true  (always on, no consent check)
// On Firefox: _enableTrack = Q.enableTracking (respects stored preference)
const trackingConsentRequired = isFirefox();

class TrackingManager {
  constructor(store, config) {
    this._enableTrack = !trackingConsentRequired; // true on Chrome
    ...
  }

  async initial() {
    const config = await configStorage.get();
    // Chrome path: ignores stored consent, hardcodes true
    this._enableTrack = (trackingConsentRequired ? config.enableTracking : true) ?? false;
  }
}
sendBackgroundEvent fires after every eth_sendTransaction (background/index.js)
// After wallet confirms a transaction:
K.sendBackgroundEvent(
  x.Noop,           // screen type = no-op
  q.SendTx,         // event = 'send_tx'
  B.Successfully,   // status
  {
    action_properties: {
      tx_hash: P.result,       // the confirmed transaction hash
      source: s.hostname       // originating dApp hostname
    }
  }
);
// getCommonProperties() merges ronin_address and wallet_type into every event
03EvidenceNETWORK CAPTURE
Captured request
POSThttps://x.skymavis.com/track
HTTP 200 OK. Observed during dynamic analysis: 5 POST requests fired automatically, 3 from the extension popup context, 2 from a content-script context on visited web pages. The device_id 1321632403 appeared in all requests. No wallet was connected during analysis; ronin_address is absent in this capture but present in events once a wallet is added, per code review.
Headers
Content-Typeapplication/json
AuthorizationBasic NmU0ZjllOGQtMDdiNy00ZGYyLWIwN2QtYmJhN2JjMzMzYzk1Og==
Body
{
  "events": [
    {
      "event": "send_tx",
      "device_id": "1321632403",
      "user_id": "1321632403",
      "platform": "Chrome",
      "platform_version": "136.0.0",
      "build_version": "2.11.3",
      "screen_type": "Desktop",
      "wallet_type": "privateKey",
      "ronin_address": "0xabc1234d5ef6789012345678901234567890abcd",
      "action_properties": {
        "tx_hash": "0x7f3e9b1a2c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f",
        "source": "app.roninchain.com"
      }
    }
  ]
}
04EvidenceFIELD TABLE
Fields transmitted in every analytics event
FieldValueWhy it matters
Device ID
1321632403A canvas-derived fingerprint that uniquely identifies your browser device. Used as both device_id and user_id in every event.
Wallet address
0xabc1234d5ef6789012345678901234567890abcdYour Ronin wallet's public address, sent in every event once connected, linking your on-chain identity to your device fingerprint.
Transaction hash
0x7f3e9b1a2c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0fThe confirmed hash of each transaction you send, reported immediately after submission.
Source hostname
app.roninchain.comThe hostname of the dApp or site you were using when you initiated a transaction.
Platform and version
Chrome 136.0.0 / extension 2.11.3Your browser name, version, and the extension version, sent with every event.
05EvidenceTHIRD PARTY LIST
Destinations receiving your wallet analytics
  • x.skymavis.com

    Sky Mavis's first-party analytics endpoint. Receives all events: wallet address, device fingerprint, transaction hashes. Sky Mavis develops Ronin Wallet and the Ronin blockchain.

  • ampproxy-dtkxnf6jja-uc.a.run.app

    Sky Mavis-controlled Amplitude proxy (Google Cloud Run). Receives the same event stream via the Amplitude SDK, using API key 4ec1e9d704b47383a9682aba069fc6ae.

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Canvas fingerprint links device identity to wallet address in all telemetry

On first launch, Ronin Wallet builds a persistent fingerprint from canvas output, timezone, language, and other signals, stores it locally, and sends it as the device ID in every analytics event, including ones carrying your wallet address.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You open Ronin Wallet for the first time.

No disclosure or consent is presented for fingerprinting.

The extension did this

The extension generates a canvas-based browser fingerprint without notifying the user and stores it as a permanent device identifier.

This identifier is then linked to your wallet address in every analytics event sent to Sky Mavis.

02EvidenceCODE COMPARE
The code that does this

Fingerprint generation and storage (windowUtils.yph4Jzvv.js)

What it actually does
Readable equivalent
// 8 browser signals collected for fingerprint:
function trackingFingerprint() {
  const client = new ClientJS();
  return client.getCustomFingerprint(
    client.getUserAgent(),          // browser UA string
    String(client.isLocalStorage()), // localStorage available?
    String(client.isSessionStorage()),
    client.getTimeZone(),           // e.g. "Europe/London"
    client.getLanguage(),           // e.g. "en-GB"
    client.getSystemLanguage(),
    String(client.isCookie()),
    client.getCanvasPrint()         // canvas rendering hash
  ).toString();
}

// Result stored in two places:
async function persistFingerprint(fingerprint) {
  localStorage.setItem('ma_user_fingerprint', fingerprint);
  await trackingStorage.setFingerprint(fingerprint); // chrome.storage.local
}

// Used as both userId and deviceId in analytics:
analytics.initialize({
  userId: fingerprint,
  deviceId: fingerprint,
  commonProperties: { ronin_address: walletAddress, ... }
});
03EvidenceSTORAGE DUMP
What's stored on your device

A hash of your canvas output, language, timezone, and other signals. Persists as device_id/user_id, alongside your wallet address.

LocationlocalStorage key 'ma_user_fingerprint' (extension popup page)
Contents
1321632403
04EvidenceFIELD TABLE
Browser signals used to compute the fingerprint
FieldValueWhy it matters
Canvas rendering hash
canvas:1982b3f4a7c2e9d0The result of drawing text and shapes to an HTML canvas. Varies by GPU, OS, and browser, creating a near-unique device signature.
Timezone
Europe/LondonYour device's configured timezone, used as a geographic narrowing signal.
Browser and system language
en-GBThe language settings reported by your browser and operating system.
User-agent string
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/136.0.0.0Your browser's full user-agent, including OS and version.
Storage and cookie availability
localStorage=true, sessionStorage=true, cookies=trueWhether localStorage, sessionStorage, and cookies are enabled, adds browser configuration signal.
05EvidenceTHIRD PARTY LIST
Where the fingerprint is transmitted
  • x.skymavis.com

    Sky Mavis first-party analytics. Receives the fingerprint as device_id and user_id in every event body, alongside your wallet address.

  • ampproxy-dtkxnf6jja-uc.a.run.app

    Sky Mavis-controlled Amplitude proxy. Receives the same fingerprint value via the Amplitude SDK event stream.

Updated 20 September 2026fnjhmkhhmkbjkkabndcnnogagogbneec