Is Ad block & Adblocker - No Ads extension safe?

Medium risk

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.…

NoAds applicationv1.9.8Chrome Web Store
45Risk

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

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.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You install the extension and then browse normally.

No separate account sign-in is needed for this identifier to be created.

The extension did this

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.

02EvidenceFIELD TABLE
Fields linked in the request flow
FieldValueWhy it matters
Your persistent ID
15ec1e59-45fd-465e-b91f-57db2c6de34dThis 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
userIdStoring the ID in synced browser storage can carry the same identifier across sessions and synced Chrome profiles.
03EvidenceNETWORK CAPTURE
Captured request
POSThttps://smartadblocker.com/extension/rules/api
Dynamic analysis captured repeated POST requests; the stored UUID appeared in every captured body.
04EvidenceCODE COMPARE
The code that does this

Background script creates the ID and sends it with page URLs

What it actually does
UUID generatordeobfuscated/js/bg.js
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)
};
Install handlerdeobfuscated/js/bg.js
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
    })
  })))
}));
Navigation handlerdeobfuscated/js/bg.js
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]
      })
    }))
  }
}));
05EvidenceTHIRD PARTY LIST
Destination receiving the URL and identifier
  • smartadblocker.com

    Receives POST requests to `/extension/rules/api` containing the current page URL and the stored user identifier.

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

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.

01EvidenceCAUSE EFFECT
What actually happens
You did this

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 did this

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.

02EvidenceNETWORK CAPTURE
Captured request
POSThttps://smartadblocker.com/extension/rules/api
Dynamic analysis recorded 10 POST bodies with the same userId value.
Body
{
  "url": "https://www.amazon.com/",
  "userId": "15ec1e59-45fd-465e-b91f-57db2c6de34d"
}
03EvidenceFIELD TABLE
Concrete fields observed in storage and traffic
FieldValueWhy it matters
Persistent browser ID
15ec1e59-45fd-465e-b91f-57db2c6de34dThis 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.comMultiple page visits can be tied to the same identifier when the value stays unchanged.
04EvidenceCODE COMPARE
The code that does this

Background script persists and reuses the UUID

What it actually does
UUID generatordeobfuscated/js/bg.js
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)
};
Install handlerdeobfuscated/js/bg.js
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
    })
  })))
}));
Navigation handlerdeobfuscated/js/bg.js
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]
      })
    }))
  }
}));
05EvidenceTHIRD PARTY LIST
Destination receiving the browsing record
  • 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

Updated 30 September 2026gbdjcgalliefpinpmggefbloehmmknca