Is Stop Ads Now safe?
Stop Ads Now collects hardware fingerprints and visited domain history from every page and sends them to stopads-now.com.
On every page load across all sites, the extension gathers a hardware fingerprint — including canvas data, GPU identifiers, CPU and memory figures, battery status, and screen resolution — and transmits it to stopads-now.com/stopads.php along with a running list of up to 50 visited domains. At install time it also captures the hostnames of all open tabs and includes them in the first sync. Additionally, the backend can push new network-blocking rules at any time, dynamically controlling which URLs the browser blocks or allows for all users.
Who publishes itStop Ads - no other listings under this identity
Stop Ads - no other listings under this identity
What this publisher told the store about itself, and the other listings that told it the same thing.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Visited domain history periodically transmitted to stopads-now.com
DA captured POSTs to stopads-now.com/stopads.php with every domain visited plus visit counts.
The content script runs on every load, records the domain, then a sync sends the history, sent within seconds of navigation.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You navigate to any website.
The content script is injected at document_start on every top-level page load across all URLs.
The extension records the domain in local storage and, 5 seconds later, includes your full visited-domain history in a POST to stopads-now.com.
This happens on every navigation, not just on install. Each sync carries the running tally of domains and visit counts.
Server responds with updated config including a rules array. Body ~3.9 MB.
- Content-Type
- application/json
{ "core_visited_sites": { "en.wikipedia.org": 1 }, "coredetails": "eyJhbGciOiJIUzI1NiJ9...", "extid": "caeeihoelgmdmafbmlgoebfjnmgpfend", "core_last_sync": 1747569244261}A rolling map of up to 50 visited domains with visit counts each, included verbatim in every POST to stopads-now.com after each navigation.
- Location
- chrome.storage.local key 'core_visited_sites'
{ "github.com": 7, "mail.google.com": 12, "en.wikipedia.org": 3, "stackoverflow.com": 5, "news.ycombinator.com": 2}Domain history tracking, content/broker.js lines 195-245
(async function recordVisitedDomain() { const isTop = (() => { try { return window.top === window; } catch { return true; } })(); if (!isTop) return; const domain = normHost(location.hostname); if (!domain) return; try { const result = await chrome.storage.local.get(["core_visited_sites"]); let data = result?.core_visited_sites; if (!data || typeof data !== "object" || Array.isArray(data)) data = {}; if (Object.prototype.hasOwnProperty.call(data, domain)) { data[domain] = (Number(data[domain]) || 0) + 1; } else { data[domain] = 1; const keys = Object.keys(data); if (keys.length > 50) { const sorted = Object.entries(data).sort(([, a], [, b]) => (Number(a) || 0) - (Number(b) || 0)); const toDelete = Math.min(10, sorted.length); for (let i = 0; i < toDelete; i++) delete data[sorted[i][0]]; } } await chrome.storage.local.set({ core_visited_sites: data }); setTimeout(async () => { try { await chrome.runtime.sendMessage({ eventName: "CHECK_AND_FETCH_DATA", params: { domain } }); } catch {} }, 5000); } catch {}})();- stopads-now.com
Receives the visited-domain history map each navigation. Combined with the fingerprint identity set at install, builds a persistent profile. Not disclosed in the listing.
Hardware fingerprint collected on every page and sent to stopads-now.com
DA captured a POST to stopads-now.com/stopads.php with a hardware fingerprint: GPU, canvas output, CPU cores, RAM, battery, resolution, timezone, language.
Fires on first load, before consent.
Fingerprints survive clearing cookies.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Dynamic sandbox
You install the extension and navigate to any webpage.
The content script runs at document_start on the very first top-frame page load.
The extension renders a off-screen canvas, queries your GPU, reads CPU and RAM counts, and sends the full fingerprint to stopads-now.com.
This runs once, only when no coredetails token is stored, but the fingerprint creates a persistent identity that cannot be cleared by deleting cookies.
Server responds with a coredetails token and a rules array for declarativeNetRequest. Body ~3.9 MB.
- Content-Type
- application/json
{ "cpu_cores": 12, "ram_gb": 32, "gpu_vendor": "Google Inc. (Google)", "gpu_renderer": "ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero) (0x0000C0DE)))", "canvas_data": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAAAyCAYAAAAZUl3oAAAAAXNSR...", "lang": "en-GB", "color_depth": 24, "timezone": "UTC", "screen_res": "1920x1080", "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36", "touch_points": 0, "bat_charging": 1, "bat_level": 0.8, "an": null, "cid": null, "sid": null, "extid": "caeeihoelgmdmafbmlgoebfjnmgpfend"}- Canvas rendering outputdata:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAAAy...
A PNG snapshot of text rendered in an off-screen canvas. The pattern is unique to your GPU and fonts, surviving cleared cookies or a VPN.
- GPU vendor and rendererANGLE (Google, Vulkan 1.3.0 (SwiftShader Device))
Your graphics card make and driver string. Combined with canvas output, this narrows device identity to a small fingerprint space.
- CPU core count12
Number of logical CPU cores reported by your browser.
- RAM size32
Device memory in GB as reported by the browser.
- Battery statecharging: true, level: 0.8
Whether your device is charging and current battery level, narrows device type on mobile.
- Screen resolution and color depth1920x1080, 24-bit
Physical screen dimensions and color bit depth.
- Timezone and languageUTC, en-GB
Your local timezone identifier and browser language setting.
Fingerprint collection, content/broker.js
(async function collectFingerprint() { const isTop = (() => { try { return window.top === window; } catch { return true; } })(); if (!isTop) return; try { const stored = await chrome.storage.local.get(["coredetails"]); if (stored.coredetails && stored.coredetails !== "") { console.log("❌ FP ok, skipping"); return; } const vars = await chrome.storage.local.get(["an", "cid", "sid"]); const fpData = await gatherFingerprint(vars); chrome.runtime.sendMessage({ type: "CORE_FINGERPRINT_READY", payload: fpData }); } catch {}})();async function gatherFingerprint(vars) { const gpu = getGPUDetails(); let batCharging = "unknown"; let batLevel = "unknown"; try { if ("getBattery" in navigator) { const battery = await navigator.getBattery(); batCharging = battery.charging ? 1 : 0; batLevel = battery.level; } } catch {} return { cpu_cores: navigator.hardwareConcurrency || "unknown", ram_gb: navigator.deviceMemory || "unknown", gpu_vendor: gpu.vendor, gpu_renderer: gpu.renderer, lang: navigator.language || "unknown", color_depth: screen.colorDepth || "unknown", timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || "unknown", canvas_data: getCanvasFingerprint(), touch_points: navigator.maxTouchPoints || 0, an: vars.an || null, cid: vars.cid || null, sid: vars.sid || null, screen_res: `${screen.width}x${screen.height}`, user_agent: navigator.userAgent, bat_charging: batCharging, bat_level: batLevel, };}- stopads-now.com
Receives the fingerprint POST, returns an identity token (coredetails); also delivers DNR rules and history sync. Not disclosed in the Chrome Web Store listing.
Remote server controls which URLs Chrome blocks or allows via pushed rules
DA captured the server response to stopads.php returning 33 declarativeNetRequest rules, applied verbatim with no validation.
One rule redirected http(s) requests matching 4,600+ domains to the blocked page, server-controlled.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-829
- Source
- Dynamic sandbox
The remote server includes a rules array in its response to the extension's sync POST.
This occurs on every fetchData() cycle, at startup and 5 seconds after each page navigation.
The extension replaces all of Chrome's dynamic declarativeNetRequest rules with whatever the server provided, without validating the rule contents.
Any valid DNR rule object, including redirects, blocks, header modifications, or URL rewrites, is applied immediately.
3.9 MB JSON response. Contains rules array at offset ~1.5 MB with 33 declarativeNetRequest rule objects. Rule id=1002 redirects http(s) URLs with requestDomains matching 4,637 entries to the extension's own blocked.html page.
- Content-Type
- application/json
{ "coredetails": "eyJhbGciOiJIUzI1NiJ9...", "extid": "caeeihoelgmdmafbmlgoebfjnmgpfend", "core_last_sync": 1747569244261}Server-controlled rule application, background.js lines 337-347
async function updateDnrRules() { const rules = await storage.get("rules"); if (!rules || !Array.isArray(rules)) return; const existing = await dnr.getDynamicRules(); await dnr.updateDynamicRules({ removeRuleIds: existing.map((r) => r.id), addRules: rules, }); log("Currently applied DNR rules:", await dnr.getDynamicRules());}- Rule action typeredirect
Redirect; the browser sends the user to a different page instead of the original destination.
- Redirect targetchrome-extension://caeeihoelgmdmafbmlgoebfjnmgpfend/pages/blocked/blocked.html?url=\0
Requests matching this rule are sent to the extension's own blocked page, which the extension controls entirely.
- URL pattern matched^http.+
Any http or https URL; the rule is not limited to known ad domains.
- Domains in requestDomains list4,637
Number of domains in this single rule's allow-list at time of capture. The server can update this list on any sync cycle.
- stopads-now.com
Delivers the DNR rule set applied on every sync. Same endpoint receives hardware fingerprints and browsing history. Not disclosed in the Chrome Web Store listing.
+1 more finding not shown
Where it sends data
Destinations our analysis observed Stop Ads Now 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.
- stopads-now.com
Stop Ads Now sends data to stopads-now.com. No other extension we have analysed sends data here.