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.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
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.
Request 1
You didNavigate to google.com
The extension didPOST: url=https://www.google.com/, dr=undefined (first navigation)
Request 2
You didNavigate to amazon.com
The extension didPOST: url=https://www.amazon.com/, dr=https://www.google.com/
Request 3
You didNavigate to facebook.com
The extension didPOST: url=https://www.facebook.com/, dr=https://www.amazon.com/
Request 4
You didNavigate to facebook.com/checkpoint
The extension didPOST: url=https://www.facebook.com/checkpoint/..., dr=https://www.facebook.com/
Referrer read, payload assembly, and referrer update (assets/index.js)
Readable version
// 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 navigationconst 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 navigationconst 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.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
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.
Server optionally returns JSON with a 'rules' array of declarativeNetRequest dynamic rules; if present they are applied via updateDynamicRules().
- 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}- Page URLhttps://www.amazon.com/gp/cart/view.html
The exact URL of the page you just navigated to, including any query parameters.
- Persistent user ID6a7ec0b8-ba0c-443f-a105-c213096c80bd
A UUID generated on install and stored permanently. Ties every navigation event to you across sessions.
- Previous page URLhttps://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 count4
Number of ads the extension blocked on this tab. Sent alongside the URL.
- Timestamp1745980425117
Unix millisecond timestamp of when the navigation completed.
Navigation listener and payload dispatch (assets/index.js)
Readable version of the payload builder
// 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.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Dynamic sandbox
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.
- Location
- chrome.storage.local key 'userId'
6a7ec0b8-ba0c-443f-a105-c213096c80bdOptionally returns dynamic blocking rules. The userId in the payload allows the server to attribute this and all prior navigation events to one install.
- Content-Type
- application/json
{ "payload": "eyJ1cmwiOiJodHRwczovL3d3dy5mYWNlYm9vay5jb20vIiwidXNlcklkIjoiNmE3ZWMwYjgtYmEwYy00NDNmLWExMDUtYzIxMzA5NmM4MGJkIiwiZHIiOiJodHRwczovL3d3dy5hbWF6b24uY29tLyIsInBsdCI6MCwiYmMiOjUsInRzIjoxNzQ1OTgwNDM4NzIyfQ=="}UUID generation and persistence (assets/index.js)
Readable version
// 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)