Is Smart Adblocker safe?
Smart Adblocker is high risk. Each POST to smartadblocker.com includes the previous page's URL in field 'dr'. Across four requests, 'dr' matched the prior 'url': google.com to amazon.com to facebook.com, letting the vendor reconstruct page order within a session.…
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Per-Tab Referrer Chain Transmitted with Each Navigation Event
Each POST to smartadblocker.com includes the previous page's URL in field 'dr'.
Across four requests, 'dr' matched the prior 'url': google.com to amazon.com to facebook.com, letting the vendor reconstruct page order within a session.
You navigate to a second page in the same tab.
The extension reads the URL of the previous page from session storage and includes it as 'dr' (document referrer) in the POST to smartadblocker.com.
After each navigation, the new URL overwrites the stored value, so the next navigation will chain off of it. The session storage resets when the tab is closed.
| When | You did | Extension did |
|---|---|---|
| Request 1 | user Navigate to google.com | extension POST: url=https://www.google.com/, dr=undefined (first navigation) |
| Request 2 | user Navigate to amazon.com | extension POST: url=https://www.amazon.com/, dr=https://www.google.com/ |
| Request 3 | user Navigate to facebook.com | extension POST: url=https://www.facebook.com/, dr=https://www.amazon.com/ |
| Request 4 | user Navigate to facebook.com/checkpoint | extension POST: url=https://www.facebook.com/checkpoint/..., dr=https://www.facebook.com/ |
Referrer read, payload assembly, and referrer update (assets/index.js)
// D() = chrome.storage.session.get(key)
// F() = chrome.storage.session.set({key: value})
async function getTabReferrer(tabId) {
const referrers = await sessionGet('referrers') || {};
referrers[tabId] = referrers[tabId] || {};
return referrers[tabId];
}
// Inside onTabUpdated(tabId, tab):
const tabReferrer = await getTabReferrer(tabId);
const previousUrl = tabReferrer?.url; // undefined on first navigation
const payload = base64Encode({
url: tab.url,
userId,
dr: previousUrl, // sent as the 'document referrer'
plt: 0,
bc: blockedCount,
ts: Date.now()
});
// After POST: store current URL as referrer for the NEXT navigation
const referrers = await sessionGet('referrers') || {};
referrers[tabId] = { url: tab.url };
await sessionSet('referrers', referrers);The referrer chain is stored in `chrome.storage.session`, which resets when the browser closes. Navigation across different tabs does not chain — each tab maintains its own referrer entry keyed by tab ID. However, because the same persistent `userId` UUID appears in every request, the vendor can correlate navigation paths across sessions by matching that UUID.
Visited URL Transmitted to smartadblocker.com on Every Navigation
Dynamic analysis captured four POSTs from this ad blocker's worker to smartadblocker.com after each navigation.
Each body has the visited URL, a user ID, previous URL, blocked-ad count, and timestamp, base64-encoded, undisclosed in listing.
You navigate to any website while this extension is installed and active.
The extension encodes the URL you just visited, your persistent user ID, the previous URL for this tab, and a timestamp into a base64 payload, then POSTs it to smartadblocker.com.
Fires on every tab navigation that reaches status 'complete' and whose URL starts with 'http'. No allowlist or sampling, every page, every tab.
| credentials | include |
| Content-Type | application/json |
{
"payload": "eyJ1cmwiOiJodHRwczovL3d3dy5hbWF6b24uY29tLyIsInVzZXJJZCI6IjZhN2VjMGI4LWJhMGMtNDQzZi1hMTA1LWMyMTMwOTZjODBiZCIsImRyIjoiaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS8iLCJwbHQiOjAsImJjIjo0LCJ0cyI6MTc0NTk4MDQyNTExN30="
}The navigation data is JSON-serialized, URI-encoded, then base64-encoded before being placed in the 'payload' field. The encoding is reversible with standard browser APIs.
{
"url": "https://www.facebook.com/",
"userId": "6a7ec0b8-ba0c-443f-a105-c213096c80bd",
"dr": "https://www.amazon.com/",
"plt": 0,
"bc": 5,
"ts": 1745980438722
}| Field | Value | Why it matters | |
|---|---|---|---|
Page URL | https://www.amazon.com/gp/cart/view.html | The exact URL of the page you just navigated to, including any query parameters. | |
Persistent user ID | 6a7ec0b8-ba0c-443f-a105-c213096c80bd | A UUID generated on install and stored permanently. Ties every navigation event to you across sessions. | |
Previous page URL | https://www.google.com/search?q=laptop+deals | The URL of the page you were on before this one in the same tab. Enables reconstruction of your navigation path. | |
Blocked ad count | 4 | Number of ads the extension blocked on this tab. Sent alongside the URL. | |
Timestamp | 1745980425117 | Unix millisecond timestamp of when the navigation completed. |
Navigation listener and payload dispatch (assets/index.js)
// tn() = btoa(unescape(encodeURIComponent(JSON.stringify(data))))
// Qe = "https://smartadblocker.com/extension/rules/api/v2"
async function onTabUpdated(tabId, tab) {
const eulaAccepted = await getEulaAccepted(); // tt()
const userId = await localGet("userId"); // f()
const tabReferrer = await getTabReferrer(tabId); // ln()
const previousUrl = tabReferrer?.url;
if (tab.url && tab.url.startsWith("http")) {
const blockedCount = await getBadgeCount(tabId); // z()
const encodedPayload = base64Encode({
url: tab.url,
userId,
dr: previousUrl,
plt: 0,
bc: blockedCount,
ts: Date.now()
});
const enhancedProtection = await localGet("enhancedProtection");
if (encodedPayload && eulaAccepted && enhancedProtection === true) {
const response = await postJSON(RULES_API_URL, { payload: encodedPayload });
if (response?.rules) await applyDynamicRules(response.rules);
}
// Always update the referrer for next navigation
const referrers = await sessionGet("referrers") || {};
referrers[tabId] = { url: tab.url };
await sessionSet("referrers", referrers);
}
}- smartadblocker.com
Extension vendor's server. Receives per-navigation POSTs with URL, user ID, referrer, and ad-blocked count. Also hosts the config endpoint (c.smartadblocker.com/configuration).
Persistent UUID Assigned at Install and Sent with Every Navigation
Dynamic analysis confirmed the UUID 6a7ec0b8-ba0c-443f-a105-c213096c80bd in every POST to smartadblocker.com across all four navigations (google, amazon, facebook), generated at install via randomUUID(), linking visits to one install.
You install or update the extension; this happens once.
The extension generates a unique identifier using crypto.randomUUID() and saves it permanently to chrome.storage.local as 'userId'.
This ID is then attached to every navigation event sent to smartadblocker.com for the lifetime of the extension install.
The persistent identifier assigned to your install. Read on every navigation and sent to smartadblocker.com with the URL you're visiting.
chrome.storage.local key 'userId'6a7ec0b8-ba0c-443f-a105-c213096c80bd
| Content-Type | application/json |
{
"payload": "eyJ1cmwiOiJodHRwczovL3d3dy5mYWNlYm9vay5jb20vIiwidXNlcklkIjoiNmE3ZWMwYjgtYmEwYy00NDNmLWExMDUtYzIxMzA5NmM4MGJkIiwiZHIiOiJodHRwczovL3d3dy5hbWF6b24uY29tLyIsInBsdCI6MCwiYmMiOjUsInRzIjoxNzQ1OTgwNDM4NzIyfQ=="
}UUID generation and persistence (assets/index.js)
// f() = chrome.storage.local.get(key)
// G() = chrome.storage.local.set({key: value})
async function initializeUserId() {
const existingId = await localGet('userId');
if (existingId) return existingId; // reuse existing — never regenerates
const newId = crypto.randomUUID();
await localSet('userId', newId);
return newId;
}
// Called from both:
// chrome.runtime.onInstalled (line 1438)
// chrome.runtime.onStartup (line 1471)