Is CrxMouse: Mouse Gestures safe?
CrxMouse is medium risk. Installing CrxMouse v7.0.5+ and stepping through welcome screens posts your device ID, browser type/version, OS, screen size, A/B variants to Mixpanel, no consent prompt. Gate is whether the Mixpanel token is present. Absent in v6.4.2.…
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Device Fingerprint Posted to Mixpanel on Install (v7.0.5+)
Installing CrxMouse v7.0.5+ and stepping through welcome screens posts your device ID, browser type/version, OS, screen size, A/B variants to Mixpanel, no consent prompt.
Gate is whether the Mixpanel token is present.
Absent in v6.4.2.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Dynamic sandbox
You install CrxMouse v7.0.5 or open your browser with the extension installed.
Additional events fire each time you navigate a welcome or permission screen during the onboarding flow.
The extension posts your persistent device ID, browser fingerprint, screen size, and experiment assignments to api.mixpanel.com without a consent prompt.
The Mixpanel project token (Yi = f95c8e6a85eba548d664b71b7ebe0ee6) is hardcoded in service_worker.js. The send gate Ji = Boolean(Yi) evaluates to true at parse time and is not user-controllable. The ip=1 query parameter instructs Mixpanel to record the sender's IP for geolocation.
200 OK; Mixpanel accepted the event.
- accept
- text/plain
- content-type
- application/json
[ { "event": "Welcome Page", "properties": { "token": "f95c8e6a85eba548d664b71b7ebe0ee6", "$device_id": "e7a3b1f2-c94d-4812-b6e5-2f0d8a7c3e91 (illustrative)", "$user_id": "e7a3b1f2-c94d-4812-b6e5-2f0d8a7c3e91 (illustrative)", "$browser": "Chrome", "$browser_version": "148.0.0.0", "$version": "7.0.5", "$os": "Linux", "$screen_width": 1280, "$screen_height": 800, "SP Platform": "Extension", "SP Permissions": [], "SP Has Mouse Gestures Enabled": true, "SP Experiments": [ "New Redesign" ], "SP Feature flags": { "default_cheese_cursor": "false", "smart_swipe_modal": "true" }, "crx_event_key": "onboarding_welcome_page_view" } }]- Persistent device IDe7a3b1f2-c94d-4812-b6e5-2f0d8a7c3e91
A stable UUID created on first install and reused every session, letting Mixpanel link every future event to this browser install.
- User IDe7a3b1f2-c94d-4812-b6e5-2f0d8a7c3e91
Set to the same value as the device ID on first install and can be updated if the extension later links an account.
- Sender IP address (via ip=1)203.0.113.42
Mixpanel is instructed to record and geolocate the IP of each request, associating your approximate location with your device ID.
- Browser name and versionChrome 148.0.0.0
The browser name and full version are included in every event, narrowing which device you are using.
- Operating systemLinux
Your operating system name is transmitted as part of the device fingerprint.
- Screen dimensions1280 × 800
Your screen's pixel width and height are included, further contributing to device fingerprinting.
- A/B experiment assignmentsNew Redesign: enrolled
The GrowthBook experiment variants and feature flags active on your installation are sent to Mixpanel on every onboarding event.
- Extension version7.0.5
The installed extension version is included in every Mixpanel event.
Qi(), Mixpanel track sender with hardcoded token and ip=1 parameter (service_worker.js:4751-4777)
// service_worker.js:4751-4777const Ki = 'https://api.mixpanel.com';const Yi = 'f95c8e6a85eba548d664b71b7ebe0ee6'; // hardcoded Mixpanel project tokenconst Ji = Boolean(Yi); // evaluates true at parse time — the only send gateconst Qi = async (eventKey, eventData, { signal, plugin } = {}) => { if (!Ji) return; // gate: token is non-empty string, not user consent const { mixpanelEventName, props = {} } = zi(eventKey, eventData, plugin); if (!(props.$user_id || props.$device_id)) throw new Error('user id missing'); const body = JSON.stringify([{ event: mixpanelEventName, properties: { token: Yi, ...props // base props from Hi() + event-specific fields } }]); await fetch(`${Ki}/track?ip=1`, { // ip=1: instruct Mixpanel to geolocate sender IP signal, method: 'POST', headers: { accept: 'text/plain', 'content-type': 'application/json' }, body });};- api.mixpanel.com
Mixpanel Inc. (Twilio). Receives onboarding events and device fingerprint via /track?ip=1 and /engage#profile-set. ip=1 makes Mixpanel record the originating IP for geolocation.
Browsing History Sent to Developer Server on Opt-In
With opt-in 'Mouse Gestures' enabled, CrxMouse records every visited URL, the referrer, redirect chain, and link clicks, POSTing to api.mousegesturesapi.com.
DA confirmed a planted URL sent across navigations to several major sites.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Dynamic sandbox
You navigate to any web page after enabling the opt-in tracking feature.
The 'optedin' flag in chrome.storage.sync must be truthy for data to be transmitted.
The extension POSTs the page URL, referring URL, redirect chain, and external link clicks to api.mousegesturesapi.com.
The payload is assembled by SendRequestForTab._getTabData() and dispatched via a CustomEvent to As(), which performs the fetch call with the packed body.
200 OK; response body contains gesture data for the visited domain.
- xr3r
- 1715428800000
- Content-Type
- application/x-www-form-urlencoded
q=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2Fen.wikipedia.org/wiki/CrxMouse&prev=https%3A%2F%2Fwww.google.com%2F&hreferer=https%3A%2F%2Fwww.google.com%2F&tt=link&ts=1715428800000- Current page URLhttps://app.example.com/dashboard?token=abc123
The full URL of every page you visit is recorded and transmitted.
- Previous page URLhttps://www.google.com/search?q=example
The URL you navigated from, revealing your browsing sequence.
- Referrer headerhttps://www.google.com/search?q=sensitive+query
The HTTP referrer sent by the browser, which can include search query parameters.
- External link clickshttps://accounts.google.com/signin
Links you clicked that took you to a different domain are recorded.
- Redirect chainhttp://example.com/ → https://example.com/
Server and client-side redirects along the navigation path.
- Timestamp1715428800000
The precise time of each navigation, allowing a timeline of your activity to be reconstructed.
Top-level CustomEvent listener that gates sending on opt-in status
// service_worker.js:5637-5639self.addEventListener('cpw2ef3k', async t => { // 'p' is the 'optedin' storage key (line 312) await e.get(p) && As(t.detail) // only sends if optedin is truthy});- api.mousegesturesapi.com
Developer-controlled analytics server for crxMouse. Receives browsing history (URL, referrer, redirects, link clicks) via /ms/gs. Overrideable via Proconstantinator config.
Daily Telemetry Beacon Sent to Google Analytics Without Opt-In Gate
Once a day, CrxMouse sends a 'LIVE' event to Google Analytics regardless of opt-in tracking, including a stable UUID, browser/OS details, screen size, version, GrowthBook assignments.
DA confirmed it fires unconditionally every 24 hours.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You use your browser normally, no special action required.
The beacon fires once per 24 hours driven solely by a time check on tab navigation, regardless of opt-in status.
The extension sends your persistent client ID, browser fingerprint, and A/B experiment assignments to Google Analytics.
ns('LIVE') runs the full telemetry pipeline: builds the event body with userId, browser, OS, screen dimensions, and GrowthBook experiment data, then POSTs to google-analytics.com/mp/collect using hardcoded credentials decoded from Base64.
Every 1 day
The LIVE beacon fires at most once per 24 hours. The time of last send is stored in chrome.storage.sync under 'lastLiveSent'. The check runs on every chrome.tabs.onUpdated event with status='complete'.
204 No Content (GA4 Measurement Protocol accepted).
- Content-Type
- application/json
{ "client_id": "cc2feb24-4f66-4189-adc2-4d5ea868fd59", "events": [ { "name": "LIVE", "params": { "optin": true, "SP Platform": "Extension", "SP Has Mouse Gestures Enabled": true, "SP Experiments": [ "redesign" ], "SP Feature flags": { "default_cheese_cursor": "false", "smart_swipe_modal": "true" } } } ]}The GA4 measurement ID and API secret are stored as Base64-encoded strings in service_worker.js and decoded at runtime using a custom decoder function qi().
Measurement ID: G-DTT9W53FG1API Secret: -uexKC9OT9ulAlBqGI15KA- Persistent client IDcc2feb24-4f66-4189-adc2-4d5ea868fd59
A stable UUID created on first install and stored locally, letting Google Analytics link every daily beacon to this install for years.
- Browser and versionChrome 124.0.6367.60
The name and version of your browser, contributing to a device fingerprint.
- Operating systemWindows
Your OS is transmitted alongside the browser details.
- Screen dimensions1920 × 1080
Your screen width and height are included, further narrowing device fingerprinting.
- A/B experiment assignmentsredesign: true, smart_swipe_modal: true
The GrowthBook feature flags and experiment variants active on your installation are reported, revealing which UI tests you are enrolled in.
- Extension version and install channel7.0.5 / web_store
The installed version and the channel through which the extension was installed.
LIVE beacon trigger, no optedin check at this call site
// service_worker.js:5635 — inside chrome.tabs.onUpdated listener// S = 'LIVE' (line 322); e = chrome.storage.sync accessor// p = 'optedin' key — NOT checked hereconst lastSent = await e.get('lastLiveSent') || 0;const now = Date.now();if (now - lastSent > 86400000) { await e.set('lastLiveSent', now); ns('LIVE'); // fires regardless of opt-in status}- www.google-analytics.com
Google Analytics 4 (Measurement Protocol). Receives the LIVE event via /mp/collect with the hardcoded measurement ID and API secret. Google's retention policies apply.
+1 more finding not shown