Is Нейромаркет - Реклама на Wildberries safe?
Нейромаркет - Реклама на 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.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
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.
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'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.
Token copied into a domain-wide cookie, then read back and reused for API calls:
// 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")
}
}// 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;// 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
);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.
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NzE5OTIxIiwic2VsbGVySWQiOiI3NzE5OTIxIiwiZXhwIjoxNzUxODAwMDAwfQ.4f8a9d2b6c1e3f7a8b9c0d1e2f3a4b5c6d7e8f9a
| Field | Value | Why 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 visit | Expires in 3 days, and is rewritten (resetting that clock) on every seller.wildberries.ru page load while the token is present. |
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.
// 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.');
})();
- 1Log into seller.wildberries.ru as a seller.
- 2Open DevTools (F12) Console.
- 3Paste the script, press Enter; it plants a marker and reloads.
- 4Console prints whether neuromarket-auth-v3 appeared, its value and domain.
- 5Token restored