Is Ad block & Adblocker - No Ads extension safe?
NoAds is medium risk. Dynamic analysis found a UUID stored under `userId` in Chrome sync storage after install. The extension sends it with the page URL on every navigation to `smartadblocker.com/extension/rules/api`, tying your browsing to one ID.…
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Persistent ID is sent with visited URLs
Dynamic analysis found a UUID stored under `userId` in Chrome sync storage after install.
The extension sends it with the page URL on every navigation to `smartadblocker.com/extension/rules/api`, tying your browsing to one ID.
You install the extension and then browse normally.
No separate account sign-in is needed for this identifier to be created.
The extension saves a UUID in Chrome sync storage and posts it with page URLs.
Dynamic analysis observed the same UUID in storage and in repeated requests to smartadblocker.com.
| Field | Value | Why it matters | |
|---|---|---|---|
Your persistent ID | 15ec1e59-45fd-465e-b91f-57db2c6de34d | This stable value lets browsing events be associated with the same browser profile over time. | |
Current page URL | https://www.amazon.com/ | The page address reveals what you were viewing when the request was sent. | |
Chrome sync storage key | userId | Storing the ID in synced browser storage can carry the same identifier across sessions and synced Chrome profiles. |
Background script creates the ID and sends it with page URLs
const r = function(t, s, r) {
if (e.randomUUID && !s && !t) return e.randomUUID();
const o = (t = t || {}).random || (t.rng || a)();
if (o[6] = 15 & o[6] | 64, o[8] = 63 & o[8] | 128, s) {
r = r || 0;
for (let e = 0; e < 16; ++e) s[r + e] = o[e];
return s
}
return function(e, t = 0) {
return (n[e[t + 0]] + n[e[t + 1]] + n[e[t + 2]] + n[e[t + 3]] + "-" + n[e[t + 4]] + n[e[t + 5]] + "-" + n[e[t + 6]] + n[e[t + 7]] + "-" + n[e[t + 8]] + n[e[t + 9]] + "-" + n[e[t + 10]] + n[e[t + 11]] + n[e[t + 12]] + n[e[t + 13]] + n[e[t + 14]] + n[e[t + 15]]).toLowerCase()
}(o)
};chrome.runtime.onInstalled.addListener((async function(e) {
"install" == e.reason ? (chrome.storage.sync.set({
userId: r(),
switchOn: !1
}), chrome.declarativeNetRequest.getEnabledRulesets((e => {
chrome.storage.sync.set({
defaultRuleIds: e
}, (() => {
chrome.declarativeNetRequest.getEnabledRulesets((e => {
chrome.declarativeNetRequest.updateEnabledRulesets({
disableRulesetIds: e
})
}))
}))
})), chrome.storage.sync.set({
totalBlockedCount: 0
})) : "update" == e.reason && (chrome.storage.sync.set({
totalBlockedCount: 0
}), chrome.storage.sync.get("userId", (e => {
e.userId || chrome.storage.sync.set({
userId: r(),
switchOn: !1
})
})))
}));chrome.tabs.onUpdated.addListener((async (e, t, a) => {
const {
status: n
} = t, {
url: r,
id: o
} = a;
if ("complete" === n) {
let t = {
url: r,
userId: await s("userId")
};
const a = await (async (e, t) => await (async (e, t = {}) => {
try {
const s = await fetch(e, {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(t)
});
return await s.json()
} catch (e) {}
})("https://smartadblocker.com/extension/rules/api", t))(0, t);
if (!a) return;
for (const t in a)("id" === t || "genericId" === t) && a[t] && a[t].length > 0 ? chrome.tabs.sendMessage(e, {
message: "remove-id-div",
idList: a[t],
hostname: a.hostname
}, (function(e) {
d()
})) : ("class" === t || "genericClass" === t) && a[t] && a[t].length > 0 ? chrome.tabs.sendMessage(e, {
message: "remove-class-div",
classList: a[t]
}, (function(e) {
d()
})) : "innerText" === t && a[t] && a[t].length > 0 ? chrome.tabs.sendMessage(e, {
message: "remove-innerText-div",
innerText: a[t]
}, (function(e) {
d()
})) : "rules" === t ? a.updateRules && c(a[t], a.rule_scope, e) : "cc" === t && a[t] && chrome.storage.sync.get(["ctCode", "cArr"], (e => {
let s = e.ctCode || "",
n = e.cArr || [];
a[t] == s && n.length == a.acc.length || chrome.storage.sync.set({
cArr: [...a.acc],
ctCode: a[t]
})
}))
}
}));- smartadblocker.com
Receives POST requests to `/extension/rules/api` containing the current page URL and the stored user identifier.
Synced UUID tracks browsing across sessions
DA found the extension creating a UUID `userId` in Chrome sync storage, reused on every navigation.
POST bodies to smartadblocker.com/extension/rules/api included the visited URL and same UUID, tying activity to one identifier.
You add the extension and continue visiting websites.
The observed requests occurred during normal navigation to google.com, noads.day, and amazon.com.
The extension sends the visited page URL together with a UUID saved in Chrome sync storage.
The same UUID appeared in all 10 captured POST bodies during dynamic analysis.
{
"url": "https://www.amazon.com/",
"userId": "15ec1e59-45fd-465e-b91f-57db2c6de34d"
}| Field | Value | Why it matters | |
|---|---|---|---|
Persistent browser ID | 15ec1e59-45fd-465e-b91f-57db2c6de34d | This stable identifier lets separate browsing events be associated with the same browser profile. | |
Visited page URL | https://www.amazon.com/ | The request includes the page address that was open when the extension contacted its server. | |
Observed navigation set | google.com, noads.day, amazon.com | Multiple page visits can be tied to the same identifier when the value stays unchanged. |
Background script persists and reuses the UUID
const r = function(t, s, r) {
if (e.randomUUID && !s && !t) return e.randomUUID();
const o = (t = t || {}).random || (t.rng || a)();
if (o[6] = 15 & o[6] | 64, o[8] = 63 & o[8] | 128, s) {
r = r || 0;
for (let e = 0; e < 16; ++e) s[r + e] = o[e];
return s
}
return function(e, t = 0) {
return (n[e[t + 0]] + n[e[t + 1]] + n[e[t + 2]] + n[e[t + 3]] + "-" + n[e[t + 4]] + n[e[t + 5]] + "-" + n[e[t + 6]] + n[e[t + 7]] + "-" + n[e[t + 8]] + n[e[t + 9]] + "-" + n[e[t + 10]] + n[e[t + 11]] + n[e[t + 12]] + n[e[t + 13]] + n[e[t + 14]] + n[e[t + 15]]).toLowerCase()
}(o)
};chrome.runtime.onInstalled.addListener((async function(e) {
"install" == e.reason ? (chrome.storage.sync.set({
userId: r(),
switchOn: !1
}), chrome.declarativeNetRequest.getEnabledRulesets((e => {
chrome.storage.sync.set({
defaultRuleIds: e
}, (() => {
chrome.declarativeNetRequest.getEnabledRulesets((e => {
chrome.declarativeNetRequest.updateEnabledRulesets({
disableRulesetIds: e
})
}))
}))
})), chrome.storage.sync.set({
totalBlockedCount: 0
})) : "update" == e.reason && (chrome.storage.sync.set({
totalBlockedCount: 0
}), chrome.storage.sync.get("userId", (e => {
e.userId || chrome.storage.sync.set({
userId: r(),
switchOn: !1
})
})))
}));chrome.tabs.onUpdated.addListener((async (e, t, a) => {
const {
status: n
} = t, {
url: r,
id: o
} = a;
if ("complete" === n) {
let t = {
url: r,
userId: await s("userId")
};
const a = await (async (e, t) => await (async (e, t = {}) => {
try {
const s = await fetch(e, {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(t)
});
return await s.json()
} catch (e) {}
})("https://smartadblocker.com/extension/rules/api", t))(0, t);
if (!a) return;
for (const t in a)("id" === t || "genericId" === t) && a[t] && a[t].length > 0 ? chrome.tabs.sendMessage(e, {
message: "remove-id-div",
idList: a[t],
hostname: a.hostname
}, (function(e) {
d()
})) : ("class" === t || "genericClass" === t) && a[t] && a[t].length > 0 ? chrome.tabs.sendMessage(e, {
message: "remove-class-div",
classList: a[t]
}, (function(e) {
d()
})) : "innerText" === t && a[t] && a[t].length > 0 ? chrome.tabs.sendMessage(e, {
message: "remove-innerText-div",
innerText: a[t]
}, (function(e) {
d()
})) : "rules" === t ? a.updateRules && c(a[t], a.rule_scope, e) : "cc" === t && a[t] && chrome.storage.sync.get(["ctCode", "cArr"], (e => {
let s = e.ctCode || "",
n = e.cArr || [];
a[t] == s && n.length == a.acc.length || chrome.storage.sync.set({
cArr: [...a.acc],
ctCode: a[t]
})
}))
}
}));- smartadblocker.com
Receives `/extension/rules/api` POST bodies containing visited URLs and the persistent userId.
What it can do
Permissions this extension asks for, as declared in version 1.9.7. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to. The current listed version is 1.9.8, which we have not unpacked yet.
Read and change your data on every site you visit
<all_urls>
Block and redirect the requests your browser makes
declarativeNetRequest
See which of your requests its blocking rules matched
declarativeNetRequestFeedback
Store data in your browser
storage
See the address and title of every tab you have open
tabs