Is Kixie PowerCall safe?
Kixie PowerCall is medium risk. The bundle initializes Mixpanel with full-URL tracking and localStorage persistence. Logged-in paths register account fields, identify the user by userid, and track User Identified with businessId. Observed: a POST to api-js.mixpanel.com.
Who publishes itKixie - no other listings under this identity, 6 shared hostnames
Kixie - no other listings under this identity, 6 shared hostnames
What this publisher told the store about itself, and the other listings that told it the same thing.
Shared hosts - 6 hostnames
Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Mixpanel analytics links Kixie activity to account identity
The bundle initializes Mixpanel with full-URL tracking and localStorage persistence.
Logged-in paths register account fields, identify the user by userid, and track User Identified with businessId.
Observed: a POST to api-js.mixpanel.com.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Dynamic sandbox
You open or use Kixie PowerCall while logged in.
The extension initializes Mixpanel, registers Kixie account fields, and sends analytics context to Mixpanel.
Observed traffic showed Mixpanel current-URL context; no businessId, User Identified event, session-recording payload, or request body was recorded for this capture.
- User identifieruserid: 482713 (illustrative)
Lets analytics events be tied back to your Kixie user account.
- Business accountbusinessId: 21594 (illustrative)
Links the analytics event to the Kixie business account you belong to.
- Profile fieldsalex.rivera@example.com, role: manager (illustrative)
Adds your name, email address, role, and trial status to the analytics profile.
- Current page URLhttps://app.kixie.com/dialpad (illustrative)
Shows which page was open when analytics context was prepared.
- Replay identifiersreplay_id: 018f7c20-2c3a-7b1a-98d1-0a4f2d4e6c19 (illustrative)
Connects recorded interaction batches to Mixpanel device and user identifiers when session recording is active.
Mixpanel account identification and request configuration
Readable account properties and User Identified event
deobfuscated/assets/app-41fd6bad.jsfunction mixpanelCreateUser(userSettings) { return { $name: `${userSettings?.fname} ${userSettings?.lname}`, $email: userSettings?.email, userid: userSettings?.userid, businessId: userSettings?.businessId, role: userSettings?.role, inTrial: userSettings?.inTrial };}function mixpanelRegisterUser(userSettings) { if (isMixPanelEnabled() && userSettings) { try { mixpanel.register(mixpanelCreateUser(userSettings)); } catch (error) { console.error("userTracking.ts: unable to register user", error); } }}function mixpanelRegisterTrialStatus(status = { trialwithcard: 1, paidpilot: 1 }) { if (isMixPanelEnabled() && status) { try { mixpanel.register(status); mixpanel.people.set(status); } catch (error) { console.error("userTracking.ts: unable to register trial status", error); } }}function mixpanelSetUser(userSettings) { const distinctId = userSettings?.userid?.toString?.(); if (isMixPanelEnabled() && distinctId) { try { mixpanel.identify(distinctId); mixpanel.people.set(mixpanelCreateUser(userSettings)); mixpanel.track("User Identified", { source: "mixpanelSetUser", businessId: userSettings?.businessId }); } catch (error) { console.error("userTracking.ts: unable to set user", error); } }}function mixpanelReset() { if (isMixPanelEnabled()) { try { mixpanel.reset(); } catch (error) { console.error("userTracking.ts: unable to reset Mixpanel", error); } }}function initializeMixpanel() { if (isMixPanelFeatureFlagged()) { try { mixPanelInitialized = true; mixpanel.init(window.processEnv.VITE_APP_MIXPANEL_TOKEN || "", { debug: true, track_pageview: "full-url", persistence: "localStorage", disable_cookie: true }); } catch (error) { console.error("userTracking.ts: unable to initialize Mixpanel", error); } }}Readable Mixpanel request and session-recording properties
deobfuscated/assets/app-41fd6bad.jsconst DEFAULT_API_ROUTES = { track: "track/", engage: "engage/", groups: "groups/", record: "record/" };const DEFAULT_CONFIG = { api_host: "https://api-js.mixpanel.com", api_routes: DEFAULT_API_ROUTES, api_method: "POST", api_transport: "XHR", api_payload_format: PAYLOAD_TYPE_BASE64, app_host: "https://mixpanel.com", cdn: "https://cdn.mxpnl.com", track_pageview: false, persistence: "cookie", disable_cookie: false, batch_requests: true, record_sessions_percent: 0, recorder_src: "https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js"};SessionRecording.prototype._sendRequest = function(replayId, properties, body, callback) { const onResponse = _.bind(function(response, responseBody) { if (response.status === 200 && this.replayId === replayId) { this.seqNo++; this.batchStartUrl = _.info.currentUrl(); } callback({ status: 0, httpStatusCode: response.status, responseBody, retryAfter: response.headers.get("Retry-After") }); }, this); win.fetch(this.getConfig("api_host") + "/" + this.getConfig("api_routes").record + "?" + new URLSearchParams(properties), { method: "POST", headers: { Authorization: "Basic " + btoa(this.getConfig("token") + ":"), "Content-Type": "application/octet-stream" }, body }).then(function(response) { response.json().then(function(responseBody) { onResponse(response, responseBody); }).catch(function(error) { callback({ error }); }); }).catch(function(error) { callback({ error, httpStatusCode: 0 }); });};SessionRecording.prototype._flushEvents = addOptOutCheckMixpanelLib(function(events, _, callback) { const eventCount = events.length; if (eventCount > 0) { var replayId = this.replayId; var batchStart = events[0].timestamp; if (this.seqNo === 0 || !this.replayStartTime) { if (this.seqNo !== 0) this.reportError("Replay start time not set but seqNo is not 0. Using current batch start time as a fallback."); this.replayStartTime = batchStart; } var replayLength = events[eventCount - 1].timestamp - this.replayStartTime; var properties = { $current_url: this.batchStartUrl, $lib_version: Config.LIB_VERSION, batch_start_time: batchStart / 1000, distinct_id: String(this._mixpanel.get_distinct_id()), mp_lib: "web", replay_id: replayId, replay_length_ms: replayLength, replay_start_time: this.replayStartTime / 1000, replay_start_url: this.replayStartUrl, seq: this.seqNo }; var encodedEvents = _.JSONEncode(events); var deviceId = this._mixpanel.get_property("$device_id"); if (deviceId) properties.$device_id = deviceId; var userId = this._mixpanel.get_property("$user_id"); if (userId) properties.$user_id = userId; if (CompressionStream) { var stream = new Blob([encodedEvents], { type: "application/json" }).stream(); var gzip = stream.pipeThrough(new CompressionStream("gzip")); new Response(gzip).blob().then(_.bind(function(blob) { properties.format = "gzip"; this._sendRequest(replayId, properties, blob, callback); }, this)); } else { properties.format = "body"; this._sendRequest(replayId, properties, encodedEvents, callback); } }});- api-js.mixpanel.com
Mixpanel analytics API host that received the observed POST and is configured for track, engage, groups, and record routes.
- mixpanel.com
Mixpanel application host configured by the bundled analytics library.
- cdn.mxpnl.com
Mixpanel CDN host configured for the session-recording loader.