Is StockGlow by Upstox: Live Stock Prices & Charts safe?

Medium risk

StockGlow sends each visited page's domain and path plus stock-detection events to Mixpanel with a persistent extension ID.

StockGlow runs a content script on all websites and registers the current page domain and path with Mixpanel alongside a persistent extension user ID. Its automatic scanner sends stock-detection events to Mixpanel, and its feature-request flow can send ratings, free-text descriptions, and optional page details to a Slack webhook.

Upstoxv4.18.0Chrome Web Store
49Risk
Who publishes it

RKSV SECURITIES INDIA PVT. LTD. - no other listings under this identity, 1 shared hostname

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
Upstox
Declared legal entity
RKSV SECURITIES INDIA PVT. LTD.
Registered address
SUNSHINE TOWER, 30th Floor, Senapati Bapat Marg, Dadar, Mumbai, Maharashtra 400013, IN
Registered contact
Upstox

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.

service.upstox.com
Also called by 1 other listing: Zing Trade

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

Publishers can request a review.

Findings

StockGlow sends every page you visit to Mixpanel with a persistent ID

StockGlow's content script runs on every website you visit and reports that page's domain and full URL to Mixpanel, tagged with an ID that stays the same across every site so your visits can be linked together.

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

You open any webpage with StockGlow installed.

The content script runs on every site because the extension is granted <all_urls> access.

The extension did this

The extension sends that page's domain and full URL to Mixpanel, tagged with an ID that never changes.

The same ID is reused across every site you visit, letting Mixpanel link your visits into one profile.

Properties sent with every page visit
  • Site domain
    moneycontrol.com

    The hostname of the page you have open.

  • Full page address
    https://www.moneycontrol.com/india/stockpricequote/tcs

    The complete URL of the page, not just the domain, showing exactly what you're reading.

  • Your tracking ID
    2799c70e-1417-434e-a981-1179eb96b93a

    A random ID created once and stored in your browser forever, sent unchanged on every site so Mixpanel can link your visits together.

  • Stock tickers found
    1442

    How many stock symbols the extension detected on the current page.

Captured request
POSThttps://api-js.mixpanel.com/track/
Body
{  "event": "Scrips Detected",  "properties": {    "token": "62597aa51842e6e2c56b97d96e4c5f8a",    "distinct_id": "2799c70e-1417-434e-a981-1179eb96b93a",    "Source Domain": "moneycontrol.com",    "Source URL": "https://www.moneycontrol.com/india/stockpricequote/tcs",    "Scrip count": 1,    "Feature": "Extension"  }}
The code that does this

Mixpanel is initialized and the page is reported on every load (content.js)

Readable version

Mixpanel initializes with a persistent per-browser ID

const MIXPANEL_TOKEN = "62597aa51842e6e2c56b97d96e4c5f8a";function initMixpanel() {  mixpanel.init(MIXPANEL_TOKEN, {    debug: false,    persistence: "localStorage",    track_pageview: false,    loaded: (mp) => {      chrome.storage.local.get(["_uid", "upstoxIdentity"], (stored) => {        const uid = stored._uid ?? crypto.randomUUID();        if (!stored._uid) chrome.storage.local.set({ _uid: uid });        mp.identify(uid);      });    },  });  mixpanelReady = true;}

Domain and URL are registered on every load

registerSuperProperties({  extension_version: manifestVersion,  Feature: "Extension",  "Source Domain": window.location.hostname,  "Source URL": window.location.origin + window.location.pathname,  Browser: browserName,  "Browser Version": browserVersion,});

The event fired after the page is scanned

if (scripCount > 0) {  trackEvent("Scrips Detected", { "Scrip count": scripCount, Feature: "Extension" });}
Third-party destinations
    • api-js.mixpanel.com

    Mixpanel's analytics ingestion endpoint. Receives the domain and full URL of every page you visit through StockGlow, plus your persistent tracking ID.

StockGlow ships a working Notion API credential in its background script

StockGlow's background script hardcodes a Notion internal-integration credential in plaintext and uses it to query Notion's API on install, startup, and roughly every 30 minutes.

Notion's API accepted it and returned real data.

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

StockGlow's background service worker starts, from a fresh install, a browser restart, or a recurring alarm.

The same call also runs on demand if a BANNER_FETCH message is sent to the background script.

The extension did this

It authenticates to Notion's API using a credential that is hardcoded in the extension's own shipped code.

The request fetches a promotional-banner record and stores the result for the popup to display.

The hardcoded credential and its target
  • Notion integration credential
    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

    A working authentication token for a Notion internal integration, shipped in plaintext inside the extension's own code.

  • Notion database queried
    3988c42f4d7580a2a6cdcfada3811e7a

    The specific Notion database this credential is used to read a promotional-banner record from.

  • Call frequency
    Install, startup, and every ~30 minutes

    How often the extension re-sends the credential to Notion while your browser is running.

Captured request
POSThttps://api.notion.com/v1/databases/3988c42f4d7580a2a6cdcfada3811e7a/query

200 OK. Notion returned a real page object (id 3988c42f-4d75-801a-969f-d94f35195b02, created by user 6935def0-1bcd-4d74-bea8-f6f4ab50bf98), confirming the hardcoded credential is a live, currently valid credential.

Headers
Content-Type
application/json
Authorization
Bearer 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
Notion-Version
2022-06-28
Body
{  "page_size": 1}
The code that does this

The credential, its endpoint, and the authenticated call (background.js)

Readable version

The endpoint and credential, declared as constants

const NOTION_QUERY_URL = "https://api.notion.com/v1/databases/3988c42f4d7580a2a6cdcfada3811e7a/query";const NOTION_TOKEN = "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";const NOTION_VERSION = "2022-06-28";

The authenticated fetch call

async function fetchBannerConfig() {  try {    const res = await fetch(NOTION_QUERY_URL, {      method: "POST",      headers: {        Authorization: `Bearer ${NOTION_TOKEN}`,        "Notion-Version": NOTION_VERSION,        "Content-Type": "application/json",      },      body: JSON.stringify({ page_size: 1 }),    });    if (!res.ok) return;    const page = (await res.json()).results?.[0];    // ...store banner fields to chrome.storage.local...  } catch {}}

Called on install, startup, and a 30-minute alarm

chrome.runtime.onInstalled.addListener(() => {  fetchBannerConfig();});chrome.runtime.onStartup.addListener(() => {  fetchBannerConfig();});chrome.alarms.onAlarm.addListener((alarm) => {  if (alarm.name === "checkBannerConfig") fetchBannerConfig();});

Where it sends data

Destinations our analysis observed StockGlow by Upstox: Live Stock Prices & Charts 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.

  • api-js.mixpanel.comwidely used

    StockGlow by Upstox: Live Stock Prices & Charts sends data to api-js.mixpanel.com. A widely used service: 47 other extensions we have analysed send data here.

  • hooks.slack.com

    StockGlow by Upstox: Live Stock Prices & Charts sends data to hooks.slack.com. 5 other extensions we have analysed send data here.

Updated 30 September 2026gedldgbbikhdlaeleapcnlhnilajfmff