Is Sensor Tower - Web Insights safe?

Medium risk

Sensor Tower - Web Insights is medium risk. Code analysis shows the extension uploads visited hostnames, paths, durations and referrers, plus stored query parameters, to webstats.st-panel-api.com every five minutes, keyed by an install ID and birth year.…

Strong link to a flagged operator: 2 of the 5 other listings from the same operator are rated high or critical for malicious behaviour. Flagged: StayFocusd (high), Luna Adblock (high).

Sensor Towerv2.3.0Chrome Web Store
58Risk
Who publishes it

Sensor Tower, Inc. - 5 other listings from the same operator, 4 of them carrying a finding

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
Sensor Tower
Declared legal entity
Sensor Tower, Inc.

Shared hosts - 2 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.

p.qljx.co
Also called by 3 other listings, including Luna Adblock for Youtube & Websites
sensortower.com
Also called by 5 other listings, including Luna Adblock for Youtube & Websites

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

Publishers can request a review.

Findings

Web Insights uploads visited hostnames and paths to its API every 5 minutes

Code analysis shows the extension uploads visited hostnames, paths, durations and referrers, plus stored query parameters, to webstats.st-panel-api.com every five minutes, keyed by an install ID and birth year.

Severity
High unwanted
Type
Unexpected
CWE
CWE-359
Source
Static analysis
What actually happens
You did this

You browse sites with the extension installed.

The extension did this

Every five minutes the extension posts the visited hosts and paths to webstats.st-panel-api.com.

The code that does this

Page view upload request body

Readable version
background.js
        throw r?.error(`Missing required parameter 'installId'`, i), Error(`Missing required parameter 'installId'`)      }      let i = (0, bt.default)(navigator?.userAgent);      await t(`/v1/page_views/upload`, {        method: `POST`,        retry: 0,        body: {          app_id: e.appId,          install_id: e.installId,          time_zone: Ke(),          device_name: n(i.browser?.name),          device_type: i.os.name,          birth_year: e.birthYear,          websites: e.websites,          diff_private_websites: e.diffPrivateWebsites        }      })    }
The code that does this

Upload interval configuration

Readable version
background.js
        getAppId: () => dn,        dev: !1,        uploadIntervalInMs: 3e5,        pageViews: {          lastUploadedAtStorageKey: `@webstats/page-views-last-uploaded-at-key`,
Fields in the upload body
  • websites.host.path
    news.example.com /politics/story-123

    Each visited hostname and path with its page views.

  • page_views[].referrer
    https://www.google.com/

    Where you came from for each visit.

  • install_id
    b7e2c1f0-5a3d-4e8b-9c11-2f6d0a7e4b90

    Persistent identifier for this install.

  • birth_year
    1985

    Birth year supplied by the user.

  • device_type
    Windows

    Operating system name.

Hosts named in the code path
    • webstats.st-panel-api.com

    Receives page views, sessions and query parameters at /v1/page_views/upload, /v1/web/upload, /v1/query_params/upload.

Observation

Static analysis finding. This behaviour was identified by reading the shipped extension code and has not yet been reproduced in a live run. The trigger conditions and the exact data sent are read from the code, not from an observed capture.

Remote-config finders read AI chat page text and upload it to the vendor API

Code analysis shows finders delivered by remote config run a query language on AI chat sites, and text from config-chosen elements is uploaded to webstats.st-panel-api.com as interactionDetails.

Severity
High unwanted
Type
Unexpected
CWE
CWE-359
Source
Static analysis
What actually happens
You did this

The remote config defines a finder or interaction selector for an AI chat site.

The extension did this

The extension reads matching page text and uploads it to webstats.st-panel-api.com.

The code that does this

Interaction collection by cardSelector

Readable version
content-scripts/usage-helper.js
      for (let e of g) r.add(e.id);      let _ = [];      n?.interactions && (Object.entries(n.interactions).forEach(([t, n]) => {        n.forEach(n => {          Array.from(document.querySelectorAll(n.cardSelector)).forEach(i => {            let a = n.skipInteractionDetails ? `` : i.textContent || ``,              o = `unknown`;            if (n.appName) o = n.appName;            else if (n.appNamePattern) {              let e = new RegExp(n.appNamePattern),                t = i.textContent?.match(e);              t && t[1] && (o = t[1].trim())            }            let s = rd(a),              l = rd(c + t + s);            r.has(l) || (_.push({              id: l,              contentHash: s,              timestamp: m,
The code that does this

Interactions upload

Readable version
background.js
    }    async function fe(e) {      await t(`/v1/ai/interactions`, {        method: `POST`,        retry: 0,        body: {          app_id: e.appId,          install_id: e.installId,          interactions: e.interactions        }      })
Fields sent to the AI endpoints
  • interactionDetails
    Model: GPT-4o

    Text of elements matched by a config-supplied selector.

  • install_id
    b7e2c1f0-5a3d-4e8b-9c11-2f6d0a7e4b90

    Persistent identifier for this install.

  • model / plan
    gpt-4o / premium

    Model name and subscription tier detected on the page.

Hosts named in the code path
    • webstats.st-panel-api.com

    Serves shared-web-config and receives /v1/ai/interactions, /v1/ai/analytics and /v1/ai/links.

Observation

Static analysis finding. This behaviour was identified by reading the shipped extension code and has not yet been reproduced in a live run. The trigger conditions and the exact data sent are read from the code, not from an observed capture.

Ad-finder hooks fetch and XHR on every site and uploads crawl data to p.qljx.co

Code analysis shows an ad-finder script is injected on supported sites, patches fetch and XHR, applies server-delivered rules, and uploads compressed crawl data with user agent and extension ID to p.qljx.co.

Severity
High unwanted
Type
Unexpected
CWE
CWE-359
Source
Static analysis
What actually happens
You did this

You open a page with display ads.

The extension did this

The extension uploads ad crawl data with your browser, language and extension ID to p.qljx.co.

The code that does this

Crawl upload to p.qljx.co

Readable version
background.js
  var Oh = class {      config;      fetch;      constructor(e) {        this.config = e, this.fetch = Dh(e)      }      async upload(e) {        if (!await this.config.isEnabled()) return;        let t = this.prepareData(e);        this.config.logger?.info(`Uploading data:`, t);        let n = await this.fetch(this.config.crawlUploadUrl, {          method: `POST`,          body: bh.default.compressToUint8Array(JSON.stringify(t)),          headers: {            "Content-Type": `application/octet-stream`          }        }).then(e => this.config.logger?.info({          status: e.status        })).catch(this.config.logger?.error);        this.config.logger?.info(`Response:`, n)      }      prepareData(e) {        return {          ...e,          PartnerVersion: R.runtime.getManifest().version,          ExtensionId: R.runtime.id,          ExtensionVersion: this.config.extensionVersion,          AdFinderVersion: `5.0.0`,          UserAgent: navigator.userAgent,
The code that does this

Upload and config endpoints

Readable version
background.js
      extensionVersion: p.runtime.getManifest().version,      extensionId: dn,      crawlUploadUrl: `https://p.qljx.co/Ajax0001/IPD`,      pmExternalConfigUrl: `https://p.qljx.co/Ajax0001/Config`,      panelPartnerId: 0
Fields added to each upload
  • ExtensionId
    nebpklfkdokhobloogjbbgajhddfjcbk

    Identifies the installed extension.

  • UserAgent
    Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/124.0.0.0

    Your browser and OS string.

  • BrowserLanguage
    en-US

    Your browser language.

  • crawlUrl
    https://news.example.com/article

    Page where the ad was found.

Hosts named in the code path
    • p.qljx.co

    Serves rules at /Ajax0001/Config and receives crawl uploads at /Ajax0001/IPD.

Observation

Static analysis finding. This behaviour was identified by reading the shipped extension code and has not yet been reproduced in a live run. The trigger conditions and the exact data sent are read from the code, not from an observed capture.

Updated 15 October 2026nebpklfkdokhobloogjbbgajhddfjcbk