Is Нейромаркет - Реклама на Wildberries safe?

Medium risk

Нейромаркет - Реклама на Wildberries is medium risk. Logged into seller.wildberries.ru, the extension copies your seller token from localStorage into a cookie, neuromarket-auth-v3, scoped to all of wildberries.ru not just the seller subdomain. A marker reappeared base64-encoded after reload.

Гельман С.Я.v1.29.4Chrome Web Store
45Risk

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

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-522
SourceAI SANDBOX

Seller Login Token Copied Into Domain-Wide Wildberries Cookie

Logged into seller.wildberries.ru, the extension copies your seller token from localStorage into a cookie, neuromarket-auth-v3, scoped to all of wildberries.ru not just the seller subdomain.

A marker reappeared base64-encoded after reload.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You log into your Wildberries seller account at seller.wildberries.ru.

Wildberries' own login flow stores a JWT access token in the page's localStorage under the key wb-eu-passport-v2.access-token.

The extension did this

The extension's content script copies that token out of localStorage and writes it into a new cookie scoped to the entire wildberries.ru domain.

The cookie (neuromarket-auth-v3) is set with domain=wildberries.ru rather than domain=seller.wildberries.ru, so it is technically readable by script running on any wildberries.ru subdomain, not only by this extension.

02EvidenceCODE COMPARE
The code that does this

Token copied into a domain-wide cookie, then read back and reused for API calls:

What it actually does
Cookie write on seller.wildberries.ru (annotated)js/inject.js:57-83
// Writes `name=value` as a cookie whose domain is forced to the eTLD+1
// (e.g. "wildberries.ru"), NOT the current subdomain.
function setCrossSubdomainCookie(name, value, days) {
  const assign = name + "=" + escape(value) + ";";
  const d = new Date();
  d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000)); // 3-day expiry, passed in below
  const expires = "expires=" + d.toUTCString() + ";";
  const path = "path=/;";
  // document.domain.match(/[^.]*\.[^.]*$/)[0] strips subdomains, leaving
  // just "wildberries.ru" — this is what makes the cookie cross-subdomain.
  const domain = "domain=" + (document.domain.match(/[^.]*\.[^.]*$/)[0]) + ";";
  document.cookie = assign + expires + path + domain;
}

// Only runs on cmp.wildberries.ru / cmp-new.wildberries.ru: loads the
// extension's own UI bundle into the page.
if (CMP_LOCATIONS.some((pattern) => location.href.startsWith(pattern))) {
  injectLocalScript("dist/bundle.js");
}

// Only runs on seller.wildberries.ru: reads the seller's Wildberries
// access token straight out of localStorage and re-exposes it as a
// domain-wide cookie. No validation of the token's shape, no scoping
// check — any truthy value is copied.
if (SELLER_LOCATIONS.some((pattern) => location.href.startsWith(pattern))) {
  try {
    const wbCaptchaKey = "wb-eu-passport-v2.access-token" // Wildberries' own localStorage key
    const storageData = localStorage.getItem(wbCaptchaKey)

    if (storageData) {
      const bToken = btoa(storageData) // base64-encode, not encrypt
      setCrossSubdomainCookie("neuromarket-auth-v3", bToken, 3) // 3-day cookie, domain-wide
    }
  } catch (e) {
    console.log("Something wrong with auth token")
  }
}
Cookie read + base64 decode on cmp.wildberries.ru (annotated)js/extension_cmp.js:31-44
// The extension's own UI (loaded on cmp.wildberries.ru) reads back the
// three cookies it wrote from other pages and decodes them.
let WB_TOKEN_RAW = getCookie("neuromarket-token") || null;
let WB_CAPTCHA_RAW = getCookie("neuromarket-captcha-token") || null;
let WB_AUTH_V3_RAW = getCookie("neuromarket-auth-v3") || null; // the seller access token, base64+URL-encoded

let WB_TOKEN = WB_TOKEN_RAW
  ? Base64.decode(decodeURIComponent(WB_TOKEN_RAW))
  : null;

let WB_CAPTCHA = WB_CAPTCHA_RAW
  ? Base64.decode(decodeURIComponent(WB_CAPTCHA_RAW))
  : null;

// Reverses the write side exactly: URL-decode, then base64-decode,
// to recover the raw JWT access token.
let WB_AUTH_V3 = WB_AUTH_V3_RAW
  ? Base64.decode(decodeURIComponent(WB_AUTH_V3_RAW))
  : null;
Decoded token used to mint a new Wildberries API token (annotated)js/extension_cmp.js:7018-7057 (createApiToken)
// Uses the token recovered from the cookie to call Wildberries' OWN
// token-generation endpoint, creating a persistent, named API token
// scoped to "contentanalytics" and "advert", read-only.
createApiToken() {
  try {
    return new Promise((resolve, reject) => {
      const onResponse = (response) => {
        if (response?.result?.token?.accessToken) {
          resolve(response.result.token.accessToken); // the newly minted API token
        } else {
          reject(false);
        }
      };
      const options = {
        headers: {
          accept: "*/*",
          "content-type": "application/json",
          "sec-fetch-site": "same-origin",
        },
        referrer:
          "https://seller.wildberries.ru/supplier-settings/access-to-api",
        referrerPolicy: "strict-origin-when-cross-origin",
        // Requests a read-only token named for the extension, scoped to
        // content-analytics and advertising APIs.
        body: '{"params":{"name":"[Нейромаркет] Реклама","scopes":["contentanalytics","advert"],"isReadOnly":true},"jsonrpc":"2.0","id":"json-rpc_70"}',
        method: "POST",
        mode: "cors",
        credentials: "include",
      }

      // The token recovered from the domain-wide cookie authenticates
      // this request to Wildberries' own API.
      if (WB_AUTH_V3) {
        options.headers['AuthorizeV3'] = WB_AUTH_V3
      }

      // Relayed through the background service worker rather than
      // fetched directly from the page.
      window.chrome.runtime.sendMessage(
        NEUROMARKET_CHROME_ID,
        {
          type: "fetchJson",
          url: "https://seller.wildberries.ru/ns/manage/api-tokens/api/tokens/generateToken",
          options,
        },
        onResponse
      );
03EvidenceOPAQUE REVEAL
Why you can't catch this in DevTools

The cookie value is not encrypted, it's the token run through btoa() (browser-native base64), which anyone can reverse with a single line of code.

What's actually being sent
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NzE5OTIxIiwic2VsbGVySWQiOiI3NzE5OTIxIiwiZXhwIjoxNzUxODAwMDAwfQ.4f8a9d2b6c1e3f7a8b9c0d1e2f3a4b5c6d7e8f9a
04EvidenceFIELD TABLE
What ends up in the domain-wide cookie, and how long it lasts:
FieldValueWhy it matters
Your Wildberries seller access token
neuromarket-auth-v3=ZXlKaGJHY2lPaUpTVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5...%3D (illustrative)Your Wildberries seller-portal login token, copied from localStorage, re-exposed as a plain base64 cookie on any wildberries.ru subdomain.
Cookie domain scope
domain=wildberries.ru; path=/Written with domain=wildberries.ru, not seller.wildberries.ru, so it's sent to and readable by scripts on every wildberries.ru subdomain.
Cookie lifetime
3 days from last seller.wildberries.ru visitExpires in 3 days, and is rewritten (resetting that clock) on every seller.wildberries.ru page load while the token is present.
05EvidenceARTIFACT
Check if you're affected

Plants a harmless marker value in the same localStorage key the extension reads, reloads the page once, then shows you whether, and where, the extension copied it into a domain-wide cookie. Restores your real token afterward.

RequiresChrome or Firefox DevToolsAn active Wildberries seller login on seller.wildberries.ruNeuromarket extension installed and enabled
wildberries-auth-cookie-detector.js · js
// wildberries-auth-cookie-detector.js
// Run in DevTools Console (F12) on a https://seller.wildberries.ru/* page
// while logged in as a Wildberries seller with the Neuromarket extension
// installed. Two-phase: plants a marker, reloads, then reports.
(function () {
  const KEY = 'wb-eu-passport-v2.access-token';
  const FLAG = '__wb_cookie_detector_marker';
  const BACKUP = '__wb_cookie_detector_original';

  const pendingMarker = sessionStorage.getItem(FLAG);

  if (!pendingMarker) {
    // Phase 1: plant a marker and reload.
    const marker = 'DETECTOR.' + Math.random().toString(36).slice(2) + '.marker';
    const original = localStorage.getItem(KEY);
    if (original !== null) sessionStorage.setItem(BACKUP, original);
    localStorage.setItem(KEY, marker);
    sessionStorage.setItem(FLAG, marker);
    console.log('[DETECTOR] Marker planted in localStorage["' + KEY + '"]. Reloading in 1s so the extension re-runs...');
    setTimeout(() => location.reload(), 1000);
    return;
  }

  // Phase 2: after reload, check whether the extension copied the marker.
  const match = document.cookie.match(/(?:^|; )neuromarket-auth-v3=([^;]*)/);

  if (!match) {
    console.warn('[DETECTOR] No neuromarket-auth-v3 cookie found after reload. Either the extension is not active on this page, or nothing was copied.');
  } else {
    const rawCookieValue = decodeURIComponent(match[1]);
    const decoded = atob(rawCookieValue);
    console.log('[DETECTOR] Found cookie neuromarket-auth-v3. Decoded value:', decoded);
    console.log('[DETECTOR] Matches planted marker:', decoded === pendingMarker);
    const scope = document.domain.match(/[^.]*\.[^.]*$/)[0];
    console.log('[DETECTOR] This cookie is scoped to domain=' + scope + ' — readable by script on any ' + scope + ' subdomain, not just this page.');
  }

  // Cleanup: restore the original token (or clear the key) and reset flags.
  const original = sessionStorage.getItem(BACKUP);
  if (original !== null) {
    localStorage.setItem(KEY, original);
  } else {
    localStorage.removeItem(KEY);
  }
  sessionStorage.removeItem(FLAG);
  sessionStorage.removeItem(BACKUP);
  console.log('[DETECTOR] Original localStorage value restored. Reload once more to return to a normal session.');
})();
How to run it
  1. 1
    Log into seller.wildberries.ru as a seller.
  2. 2
    Open DevTools (F12) Console.
  3. 3
    Paste the script, press Enter; it plants a marker and reloads.
  4. 4
    Console prints whether neuromarket-auth-v3 appeared, its value and domain.
  5. 5
    Token restored
Updated 17 September 2026blkidjnfpdkelkkelhlongdbiiabfojn