Is North Ad-Block safe?

Critical risk

North Ad-Block transmits open-tab domains to its server on install and allows that server to push arbitrary JavaScript into every browsed page.

On installation, the extension collects the hostnames of all open browser tabs and sends them to api.n-adb.com, then continues forwarding per-site ad-block counts and tab domains every 60 seconds. The server can respond with inline JavaScript code that the extension injects and executes in the main world of each page the user visits, giving the server full access to page content, credentials, and session data. A separate message handler in the content script accepts storage writes from any web page without validating the origin, which can allow a malicious site to overwrite authentication tokens used by the extension.

x00lyx00v1.0.22Chrome Web Store
100Risk

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

Publishers can request a review.

Findings

SeverityCRITICAL
ClassUNWANTED
TypeUnexpected
CWECWE-829
SourceAI SANDBOX

The vendor server can run arbitrary JavaScript on every site you visit

This ad blocker periodically checks in with api.n-adb.com.

A reply header x-fetch-scriptlets triggers a rules download whose lines run as raw JavaScript in the page (MAIN world), with the site's own script access.

DA confirmed it.

01EvidenceCAUSE EFFECT
What actually happens
You did this

The vendor server replies to a routine check-in with a header that points to a rules file.

The x-fetch-scriptlets header on the /heartbeat response tells the extension to download /rules/scriptlets.txt.

The extension did this

On your next page load, JavaScript from that file runs inside the page with the same access the website's own scripts have.

Lines marked with #%# are stored as inline code and executed in the page's MAIN world.

02EvidenceCODE COMPARE
The code that does this

Server-supplied lines are parsed as JavaScript, then executed in the page

What it actually does
The chain, in plain terms
// 1. Routine /heartbeat reply includes x-fetch-scriptlets.
// 2. Extension downloads /rules/scriptlets.txt from the same server.
// 3. Any line like  example.com#%#<JS>  is stored as runnable code for example.com.
// 4. When you open example.com, the extension runs <JS> in the page's
//    MAIN world via new Function(<JS>) - same access as the page's own scripts.
// 5. The content script is granted <all_urls>, so this works on any site.
03EvidenceARTIFACT
Reproduce it yourself

Shows the exact storage shape the extension produces from a server-supplied scriptlets.txt line, and the line of server text that produces it. Confirms a single server-controlled line becomes JavaScript that runs in the page.

scriptlets-rule-shape.js · js
// A single line in /rules/scriptlets.txt served by api.n-adb.com:
const serverLine = "example.com#%#window.__marker='ran'; document.title='changed';";

// transformScriptletTextToObject() turns that line into this storage entry:
const storedRule = {
  "scriplet_example.com": [
    {
      code: "window.__marker='ran'; document.title='changed';",
      isOnlyForMainFrame: false,
      type: "inline"
    }
  ]
};

// On navigation to example.com, adBlocking.js executes, in the page's MAIN world:
//   new Function(storedRule['scriplet_example.com'][0].code)()
// i.e. the server-supplied string runs as page JavaScript.
console.log(JSON.stringify(storedRule, null, 2));
How to run it
  1. 1
    Run: node scriptlets-rule-shape.js.
  2. 2
    Compare output to the shape from transformScriptletTextToObject() in rulesManager.js.
  3. 3
    The 'code' value runs via new Function() in the page's MAIN world by executeScriptletInjections().
04EvidencePLAIN NOTE
Why MAIN-world execution matters

Code run in the MAIN world shares the page's JavaScript context. It can read and modify anything the website's own scripts can: page content, form inputs, and the logged-in session for whatever site you are on. Because the content script is granted access to all URLs, the same mechanism applies to every site you visit, and the code that runs is chosen by the server at request time rather than fixed in the published extension.

SeverityHIGH
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Domains of every open tab sent to api.n-adb.com the moment you install

On install, this ad blocker reads every open tab's domain (e.g. chatgpt.com, x.com) and sends that list in its first request to api.n-adb.com.

DA confirmed both domains were stored, then transmitted, a snapshot an ad blocker doesn't need.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You install the ad blocker while other tabs are already open.

The extension did this

The extension reads the domain of every open tab and sends that list to its vendor server.

It runs chrome.tabs.query({}) on the install event, skips chrome:// and extension pages, and keeps the unique domain of every other tab.

02EvidenceCODE COMPARE
The code that does this

The install handler collects open-tab domains and includes them in the first server request

What it actually does
What it does, in plain terms
// 1. On install, list every open tab.
// 2. Throw away chrome:// and extension URLs.
// 3. Reduce each remaining URL to its domain (chatgpt.com, x.com).
// 4. Save that list, then POST it to https://api.n-adb.com/initialize
//    inside the initialTabDomains field of the first request body.
03EvidenceNETWORK CAPTURE
Captured request
POSThttps://api.n-adb.com/initialize
Observed during dynamic analysis with chatgpt.com and x.com open at install time. The server returned 204 and the same initialTabDomains list was retained for later requests.
Headers
Content-Typeapplication/json
Body
{
  "blockedCounts": {},
  "initialTabDomains": [
    "chatgpt.com",
    "x.com"
  ]
}
04EvidenceFIELD TABLE
What the install request reveals about you
FieldValueWhy it matters
Domains of your open tabs
["chatgpt.com", "x.com"]The website of every tab you had open when you installed the ad blocker, captured as a one-time snapshot of what you were doing.
SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Open-tab domains and per-site block counts sent to api.n-adb.com on a timer

Beyond the install report, this ad blocker posts to api.n-adb.com/heartbeat roughly every 60 seconds, an interval the server can change.

The payload has install-time tab domains plus a per-site count of blocked ads.

01EvidenceCAUSE EFFECT
What actually happens
You did this

A repeating alarm fires roughly once a minute.

configureSynchronizationAlarm sets the period; the server can change it via x-heartbeat-interval.

The extension did this

The extension sends your install-time tab domains and per-site block counts to its vendor server.

buildTelemetryPayload assembles the report and POSTs it to api.n-adb.com/heartbeat.

02EvidenceTEMPORAL PATTERN
When this fires
Every 1 minute

A synchronization alarm POSTs a telemetry payload to api.n-adb.com/heartbeat about every 60 seconds. The interval defaults to 60s and is overridden by the x-heartbeat-interval header the server returns, so the vendor controls how often reporting happens.

03EvidenceNETWORK CAPTURE
Captured request
POSThttps://api.n-adb.com/heartbeat
Observed during dynamic analysis: repeated POSTs to api.n-adb.com/heartbeat over the session, each carrying initialTabDomains and a blockedCounts map. The response may set x-heartbeat-interval to re-time future reports.
Headers
Content-Typeapplication/json
AuthorizationBearer <redacted>
Body
{
  "blockedCounts": {},
  "initialTabDomains": [
    "chatgpt.com",
    "x.com"
  ]
}
04EvidenceFIELD TABLE
What each heartbeat reports
FieldValueWhy it matters
Install-time tab domains
["chatgpt.com", "x.com"]The domains of the tabs you had open when the extension was installed, re-sent on every heartbeat.
Per-site block counts
{"nytimes.com": 14, "youtube.com": 7}How many ad requests were blocked on each site. Because counts only accrue on sites you open, this map reveals which sites you visit.

Data recipients

api.n-adb.com
Updated 17 September 2026bmgfhambolgekpleooignbnnpdcnlien