Is SelectorsHub safe?

Medium risk

SelectorsHub is medium risk. SelectorsHub's install handler fetches a link list from selectorshub.info, opens the URLs as new tabs, and sets the uninstall page via setUninstallURL. Observed live: onInstalled fired, got a 200, opened the URL from a live server.…

Sanjay Kumar | SelectorsHub Founderv5.8.3Chrome Web Store
45Risk
Who publishes it

SelectorsHub Tech Pvt Ltd - 15 other listings from the same operator, 3 of them carrying a finding

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

Publisher
Sanjay Kumar | SelectorsHub Founder
Declared legal entity
SelectorsHub Tech Pvt Ltd
Registered address
Hebbal, Bengaluru, Karnataka 560094, IN
Registered contact
SelectorsHub

Same store account

1 other listing published from this account, 80k+ users between them, none of them carrying a finding.

Shared hosts - 2 hostnames

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.

testproject.io
Also called by 5 other listings, including SelectorsHub
shubads.testcasehub.net
Also called by 9 other listings, including SelectorsHub

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

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-829
SourceAI SANDBOX

SelectorsHub opens remote-selected tabs and sets its uninstall page on install

SelectorsHub's install handler fetches a link list from selectorshub.info, opens the URLs as new tabs, and sets the uninstall page via setUninstallURL.

Observed live: onInstalled fired, got a 200, opened the URL from a live server.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You install or update SelectorsHub.

chrome.runtime.onInstalled fires with reason 'install' the first time you add the extension.

The extension did this

The extension fetches a link list from its own server and opens whatever URLs that response contains as new tabs, then reuses the response to set the extension's uninstall page.

The request includes the extension's product slug and browser platform so the server can pick which URLs to return.

02EvidenceNETWORK CAPTURE
Captured request
GEThttps://selectorshub.info/nodeapp/api/link-ads?type=on_install&extension=SH&browsers=chrome
200 response with on_install and on_uninstall URL arrays, followed by chrome.tabs.create using the exact on_install URL from that response.
03EvidenceFIELD TABLE
Values sent in the install-time request
FieldValueWhy it matters
Extension product code
extension=SHA fixed short code identifying this extension product to the server; it is not tied to your account or device.
Browser platform
browsers=chromeWhich browser family you're running, used to select platform-appropriate links.
04EvidenceCODE COMPARE
The code that does this

The install handler fetches a remote link list and opens/redirects based on the response

What it actually does
Opens a URL as a new inactive tabbackground.js
function openLink(a) {
  browserType.tabs.create({
    url: a,
    active: !1
  })
}
Install handler: fetch, open tabs, set uninstall URLbackground.js
const installedListener2 = async a => {
  let c = "";
  try {
    if ("install" === a.reason) {
      c = "on_install";
      const b = await (await fetch(`${newAPiUrl}link-ads?type=${c}&extension=${EXT_SLUG}&browsers=${platform}`)).json();
      Array.isArray(b[c]) && b[c].forEach(d => openLink(d));
      Array.isArray(b.on_uninstall) && 0 < b.on_uninstall.length && browserType.runtime.setUninstallURL(b.on_uninstall[0])
    } else "update" === a.reason && browserType.storage.local.get(["ttlt", "expiry_date", "has_free_access"], async b => {
      if ("undefined" == typeof b.ttlt || "undefined" ==
        b.ttlt || null == b.ttlt || "" == b.ttlt)
        if (b.expiry_date) new Date > new Date(b.expiry_date) && fetchUpdates();
        else try {
          fetch(endpoint + "user/limit").then(d => d.json()).then(d => {
            if (!d || "number" !== typeof d.free_access) return !0;
            const e = new Date,
              f = new Date(e);
            f.setDate(e.getDate() + d.free_access);
            if (isNaN(f.getTime())) return !0;
            browserType.storage.local.set({
              start_date: e.toISOString(),
              expiry_date: f.toISOString(),
              has_free_access: !0,
              free_days: d.free_access
            }, () => {
              if (!browserType.runtime.lastError) return new Date > new Date(b.expiry_date) &&
                fetchUpdates(), !1
            })
          }).catch(d => {})
        } catch (d) {} else getUserV2(b.ttlt)
    })
  } catch (b) {
    console.error(`Error during ${c} fetch:`, b)
  }
};
browserType.runtime.onInstalled.addListener(installedListener2);
SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

SelectorsHub reads all cookies to check one login cookie

When you open the SelectorsHub devtools panel, the extension asks for every cookie it can access, then loops through that set for one named selectorshub authentication.

All-URLs access exposes other sites' cookies unnecessarily.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You open the SelectorsHub panel in developer tools.

The devtools page creates a SelectorsHub sidebar pane and points it at shub-panel.html.

The extension did this

The panel script asks the browser for every accessible cookie before checking for one named cookie.

The empty cookie filter means the browser is not asked to limit the result to selectorshub.com.

02EvidenceFIELD TABLE
Cookie data made available to the panel callback
FieldValueWhy it matters
All accessible browser cookies
idp_session=s3A9f2e81c0d4f77 (illustrative)Can include cookies from sites other than SelectorsHub, depending on what your browser has stored and what the extension can access.
SelectorsHub login marker
selectorshub authentication=trueThis is the one cookie the code actually checks for after requesting the broader cookie list.
Site scope
host_permissions: ["<all_urls>"]The manifest allows the cookie query to cover every site pattern instead of a single SelectorsHub domain.
03EvidenceNETWORK CAPTURE
Captured request
GEThttps://shub.selectorshub.info/user/limit
Observed during dynamic analysis as a panel-page fetch; privileged cookie API calls from the devtools panel were not observable in that test setup.
04EvidenceCODE COMPARE
The code that does this

The panel asks for all cookies and then searches for one cookie name

What it actually does
The devtools sidebar loads the panel pagedevtools-panel/devtools.js
var isFirefox = "undefined" !== typeof InstallTrigger,
  browserType = chrome;
isFirefox && (browserType = browser);
var connectBackgroundPage = browserType.runtime.connect({
  name: "devtools-page"
});
browserType.devtools.panels.elements.createSidebarPane("SelectorsHub", function(a) {
  a.setPage("../devtools-panel/shub-panel.html");
  a.onShown.addListener(openedTab);
  a.onHidden.addListener(closedTab)
});

function openedTab() {
  browserType.runtime.sendMessage({
    message: "generate-selector"
  })
}

function closedTab() {
  connectBackgroundPage.postMessage({
    name: "highlight-element",
    tabId: browserType.devtools.inspectedWindow.tabId,
    xpath: ["xpath", "//sanjay", !1]
  })
};
The readable cookie check uses an empty filter objectdevtools-panel/devtools-script.js
window.onload = function() {
  let a = !1;
  browserType.cookies.getAll({}, function(c) {
    for (const d of c) "selectorshub authentication" == d.name && (a = !0);
    a || setCookies()
  });
  const b = getExtensionInfo();
  if (b && b.version) {
    const c = document.querySelector("#version"),
      d = document.querySelectorAll(".requestHeader #version")[1];
    c && (c.innerText = `v${b.version}`, d.innerText = `v${b.version}`)
  }
};

function setCookies() {
  const a = Math.floor(Date.now() / 1E3) + 63072E4;
  isFirefox ? browser.storage.sync.set({
    cookie: "authenticated"
  }, function() {}) : chrome.cookies.set({
    url: "https://selectorshub.com/",
    name: "selectorshub authentication",
    value: "true",
    secure: !0,
    expirationDate: a
  })
}
Updated 30 September 2026ndgimibanhlabgdgjcpbbndiehljcpfh