Is Yandex search by image safe?

Low risk

Yandex search by image sends the URL, title, and referrer of every page you visit to Google Analytics with a persistent per-install ID.

On every page load, the extension's content script sends the page's full URL, title, and referrer to a vendor-operated Google Analytics 4 property, independent of whether the site is a shopping platform the extension is designed to work with. Each report is tagged with a persistent identifier generated once at install and stored locally, so page visits can be linked together over time. The same tracking logic also runs in the background service worker and is sent again every 3 seconds and when a page is closed.

aiprice4v26.0.0Chrome Web Store
29Risk
Who publishes it

aiprice4 - 19 other listings from the same operator, 2 of them carrying a finding

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

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

Publishers can request a review.

Findings

AiPrice sends every page you visit to Google Analytics with a persistent ID

Code analysis shows AiPrice's content script sends a page_view beacon to Google Analytics on every website you visit, not just shopping sites, carrying the page URL, title, referrer, and a persistent per-install ID.

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

You open any website in a tab, including one unrelated to shopping or price comparison.

AiPrice's content script is declared for http://*/* and https://*/* in the manifest.

The extension did this

The content script sends a page_view beacon to Google Analytics with the page URL, title, referrer, and a persistent per-install ID.

This path runs before any shopping-site match check and is not gated by the extension's privacy setting.

The code that does this

The unconditional analytics trigger inside the content script's initApp()

Readable version

initApp() fires the analytics module regardless of site match

assets/js/chunk-common.js:12045-12048
this.router.$off(), this.router = null, m.done && m.done(!1)})),// Fires unconditionally, in parallel with (not after) the site-match check abovePromise.resolve().then(a.bind(a, 98189)).then(({ default: e }) => {  e()})

Module 98189: queues a page_view event and starts the flush timer

assets/js/chunk-common.js:10972-10979
c = () => {  const e = () => {    globalThis[l] || (globalThis[l] = globalThis[l] || [],      navigator?.sendBeacon && (        globalThis[l].push(["page_view", "page_view", {          page_title: document.title,          page_location: document.location.href,          page_referrer: document.referrer        }]),        setInterval(() => {          T([...globalThis[l]]); globalThis[l] = []        }, 3000),        window.addEventListener("beforeunload", () => {          T([...globalThis[l]]); globalThis[l] = []        })      ))  };  e()};exports.default = c

The sendBeacon call carrying URL, title, referrer, and the persistent ID

assets/js/chunk-common.js:10913-10925
navigator.sendBeacon(buildUrl(GA_COLLECT_URL, {  v: "2",  tid: n,                              // GA4 measurement ID: G-RH4XHBMZR6  cid: o,                               // persistent per-install client ID  sid: i,                               // session ID  sr: `${screen.width}x${screen.height}`,  dl: document.location.href,           // the exact page you're on  dr: document.referrer,  dt: document.title,  ul: navigator.userLanguage || navigator.language,  sct: 1, seg: 1, _et: 100}), body)
What one page_view beacon carries to Google Analytics
  • The page you're on
    https://www.nytimes.com/2026/09/03/world/example-article.html

    The full address of the page you just loaded, on any site, not only shopping sites.

  • Persistent install ID
    d4pdemo-8050026030-N-3f9a21c8b6e4

    A stable ID created once when AiPrice was installed and reused for this same beacon on every site you visit.

  • Where you came from
    https://www.google.com/search?q=nyt+article

    The referring page, if your browser sent one.

  • Page title
    Example Article - The New York Times

    The text in the page's title bar.

  • GA4 property ID
    G-RH4XHBMZR6

    AiPrice's own Google Analytics account this beacon lands in.

When this fires

Every 3 seconds

The event queue flushes to Google Analytics every 3 seconds while the tab stays open, and again right before the tab closes.

Where the beacon lands
    • www.google-analytics.com

    Google's GA4 Measurement Protocol collector. Receives the page_view beacon under AiPrice's own GA4 property (G-RH4XHBMZR6), tagged with the persistent per-install client ID.

Check if you're affected

Scans a HAR export (from your browser's DevTools Network tab, saved as HAR) for AiPrice's page_view beacons and prints the URL and client ID each one carried.

Requires
  • Python 3.8+
flag_aiprice_beacons.py · py
#!/usr/bin/env python3import json, sysfrom urllib.parse import urlparse, parse_qsdef main(har_path):    with open(har_path, encoding="utf-8") as f:        har = json.load(f)    entries = har.get("log", {}).get("entries", [])    hits = 0    for entry in entries:        url = entry.get("request", {}).get("url", "")        if "google-analytics.com/g/collect" not in url:            continue        qs = parse_qs(urlparse(url).query)        if qs.get("tid", [""])[0] != "G-RH4XHBMZR6":            continue        hits += 1        print(f"[{hits}] page={qs.get('dl', [''])[0]}")        print(f"     title={qs.get('dt', [''])[0]}")        print(f"     referrer={qs.get('dr', [''])[0]}")        print(f"     client_id={qs.get('cid', [''])[0]}")        print()    if hits == 0:        print("No AiPrice (G-RH4XHBMZR6) beacons found in this capture.")    else:        print(f"{hits} beacon(s) found. Same client_id across different sites confirms a persistent, cross-site identifier.")if __name__ == "__main__":    if len(sys.argv) != 2:        print("usage: flag_aiprice_beacons.py <capture.har>")        sys.exit(1)    main(sys.argv[1])
How to run it
  1. 1In Chrome DevTools Network tab, browse a few unrelated sites with AiPrice on, then Save all as HAR.
  2. 2Run: python3 flag_aiprice_beacons.py capture.har
  3. 3Compare the printed client_id across sites.
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.

Every page you visit is beaconed to Google Analytics, not just shopping sites

Code analysis shows an analytics module loads on every page you visit, not only supported shopping sites, and sends the page's URL, title and referrer to a Google Analytics property tied to a persistent per-install ID.

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

You open any website in your browser, even one unrelated to shopping.

The extension did this

The extension sends that page's full URL, title, and referrer to a Google Analytics endpoint.

This runs on every page load, whether or not the site matches a supported shopping platform.

The code that does this

The analytics loader runs as a sibling call, not gated behind the platform-match check

Readable version

Content-script init: platform check and analytics loader run side by side

assets/js/chunk-common.js
g.findByURL(globalThis.Wext, m.url || c).then((t => {  t.hasMatch || "contentScript" !== this.scriptType ? (this.platform = this.platforms[t.site.name], this.platformSite = {    ...t.site  }, s(t.site, (() => {    e && d(e), m.done && m.done(!0)  }))) : (this.router.$off(), this.router = null, m.done && m.done(!1))})).catch((e => {  this.router.$off(), this.router = null, m.done && m.done(!1)})), Promise.resolve().then(a.bind(a, 98189)).then((({  default: e}) => {  e()}))

GA4 endpoint and sendBeacon call inside the loaded module

assets/js/chunk-common.js
const i = "https://www.google-analytics.com",  r = `${i}/g/collect`,  n = "G-8PV8X5MGYN",  _ = 30,  l = "dataLayerXap";...l.length > 0 && navigator.sendBeacon((0, s.Qqu)(r, {  v: "2",  tid: n,  cid: o,  sid: i,  sr: `${globalThis.screen.width}x${globalThis.screen.height}`,  dl: document.location.href,  dr: document.referrer,  dt: document.title,  ul: navigator.userLanguage || navigator.language,  sct: 1,  seg: 1,  _et: 100,  _p: (0, s.ZoU)(9, "0123456789"),  _s: ++A}), l)
Fields carried in every GA4 beacon
  • Page URL
    https://en.wikipedia.org/wiki/Special_relativity

    The full address of the page you're on, including any path or query string.

  • Persistent installation ID
    N4471829305

    A unique ID generated once and stored locally, letting Google link every beacon to the same install.

  • Page title
    Special relativity - Wikipedia

    The title shown in your browser tab for the page.

  • Referrer
    https://www.google.com/

    The page you came from, if any.

  • Screen resolution
    1920x1080

    Your display's pixel dimensions.

Where the beacon goes
    • www.google-analytics.com

    Google's GA4 Measurement Protocol collector. Receives the page URL, title, referrer and persistent install ID for every page you visit under measurement ID G-8PV8X5MGYN.

When this fires

Every 3 seconds

Queued page-view events flush to Google every 3 seconds, and again immediately when the tab closes.

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.

What it can do

Permissions this extension asks for, as declared in version 26.0.0. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.

  • Read and change your data on aiprice.com

    *://*.aiprice.com/*

  • Read and change your data on every site you visit

    <all_urls>

  • Schedule its own background tasks

    alarms

  • Add items to the right-click menu

    contextMenus

  • Read and change cookies, including the ones that keep you signed in

    cookies

  • Block and redirect the requests your browser makes

    declarativeNetRequest

  • See which of your requests its blocking rules matched

    declarativeNetRequestFeedback

  • Store data in your browser

    storage

Where it sends data

Destinations our analysis observed Яндекс поиск по фото 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

    Яндекс поиск по фото sends data to www.google-analytics.com. A widely used service: 372 other extensions we have analyzed send data here.

Updated 15 October 2026pfdofiecodmjocjnofddngckpaemfhag