Is SelectorsHub safe?
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.…
Who publishes itSelectorsHub Tech Pvt Ltd - 15 other listings from the same operator, 3 of them carrying a finding
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.
Same store account
1 other listing published from this account, 80k+ users between them, none of them carrying a finding.
Same operator - 14 listings
Published under a different store account, but sharing the registered address, contact or declared legal entity this one gave the store.
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.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
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.
You install or update SelectorsHub.
chrome.runtime.onInstalled fires with reason 'install' the first time you add the extension.
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.
| Field | Value | Why it matters | |
|---|---|---|---|
Extension product code | extension=SH | A fixed short code identifying this extension product to the server; it is not tied to your account or device. | |
Browser platform | browsers=chrome | Which browser family you're running, used to select platform-appropriate links. |
The install handler fetches a remote link list and opens/redirects based on the response
function openLink(a) {
browserType.tabs.create({
url: a,
active: !1
})
}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);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.
You open the SelectorsHub panel in developer tools.
The devtools page creates a SelectorsHub sidebar pane and points it at shub-panel.html.
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.
| Field | Value | Why 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=true | This 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. |
The panel asks for all cookies and then searches for one cookie name
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]
})
};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
})
}