Is Ad Block Ninja safe?

High risk

Ad Block Ninja records each top-level site visit and sends visited-domain history plus device fingerprint signals to ninja-block.com.

Ad Block Ninja injects a content script on all sites, records the hostname of each top-level page after a short delay, and stores per-domain visit counts. When syncing, it sends those visited domains along with hardware and browser fingerprint signals such as CPU cores, RAM, WebGL details, canvas and audio fingerprints, timezone, language, screen size, user agent, battery state, and webdriver status to ninja-block.com.

Ninja Blockv2.2Chrome Web Store
72Risk
Who publishes it

Ninja Block - no other listings under this identity

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
Ninja Block
Registered address
Esplanade de Pont-Rouge 9a, Lancy 1212, CH
Registered contact
WestHive

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

Publishers can request a review.

Findings

Visited-Site History and Device Fingerprint Sent to ninja-block.com

A content script sends each page's hostname to the background worker, keeping a per-domain visit count.

On install/refresh it collects CPU/RAM/GPU, canvas/audio fingerprints, timezone, user agent, POSTed to ninja-block.com/ninja-adb21.php.

Severity
High unwanted
Type
Unexpected
CWE
CWE-359
Source
Dynamic sandbox
What actually happens
You did this

You visit any ordinary website with Ad Block Ninja installed.

No interaction with the extension itself is required.

The extension did this

The extension records the page's hostname and, on the next sync, sends it plus device fingerprint signals to ninja-block.com.

This happens on every top-level page load, in every tab.

Fields observed in the sync payload to ninja-block.com
  • Visited hostnames and counts
    {"amazon.com":2,"bing.com":1,"example.com":1}

    Lets ninja-block.com reconstruct which sites you visited and how often, tied to your installation.

  • Canvas fingerprint
    data:image/png;base64,iVBORw0KGgo... (4,958 bytes on the wire, illustrative)

    A rendering-based image hash that, combined with other signals, can distinguish your device from others.

  • Audio fingerprint
    124.0434752 (illustrative, 18 bytes on the wire)

    An audio-rendering hash that adds another distinguishing signal to the device fingerprint.

  • CPU core count
    10

    Part of the hardware profile used to help distinguish your device from others.

  • Installed RAM
    16 GB

    Another hardware signal folded into the device fingerprint.

  • Timezone
    UTC

    Narrows down your rough geographic region as part of the device fingerprint.

Captured request
POSThttps://ninja-block.com/ninja-adb21.php

Observed during dynamic analysis; the request was captured on the wire. No response body was recorded in the evidence for this session.

Headers
Content-Type
application/json
Body
{  "ninja_fp": null,  "ninja_ext_v": "2.2",  "ninja_install_sites": [],  "ninja_visited_sites": {},  "ninja_last_sync": null,  "ninja_sync": null,  "an": null,  "cid": null,  "sid": null,  "extid": "ppfadpgpccljindldolejmgkhgaficka",  "user_defined_whitelist": [],  "user_defined_blocked": [],  "ninja_acceptable_ads": true,  "ninja_fp_needs_migration": false,  "ninja_fingerprint_data": {    "cpu_cores": 10,    "ram_gb": 16,    "gpu_vendor": "Google Inc. (Intel)",    "gpu_renderer": "ANGLE (Intel, Intel(R) UHD Graphics 620, OpenGL 4.5)",    "lang": "en-US",    "color_depth": 24,    "timezone": "UTC",    "canvas_data": "data:image/png;base64,iVBORw0KGgo... (4,958 bytes total, illustrative)",    "touch_points": 0,    "an": null,    "cid": null,    "sid": null,    "audio_fp": "124.0434752 (illustrative, 18 bytes on the wire)",    "screen_res": "1920x1080",    "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",    "bat_charging": "unknown",    "bat_level": "unknown",    "webdriver_present": 0,    "gl_ext_count": 28  }}
Captured request
POSThttps://ninja-block.com/ninja-adb21.php

Observed during dynamic analysis; the request was captured on the wire. No response body was recorded in the evidence for this session.

Headers
Content-Type
application/json
Body
{  "ninja_fp": null,  "ninja_ext_v": "2.2",  "ninja_install_sites": [],  "ninja_visited_sites": {    "amazon.com": 2,    "bing.com": 1,    "example.com": 1  },  "ninja_last_sync": 1735599600000,  "ninja_sync": null,  "an": null,  "cid": null,  "sid": null,  "extid": "ppfadpgpccljindldolejmgkhgaficka",  "user_defined_whitelist": [],  "user_defined_blocked": [],  "ninja_acceptable_ads": true,  "ninja_fp_needs_migration": false}
The code that does this

Hostname capture and outbound sync request

Readable version

content.js — queues the hostname 3s after page load

js/content.js
// Domain-visit tracking — top frame only.// Fires after a short delay so it never races with the blocking logic above.(function recordVisit() {    try {        const isTop = (window.self === window.top);        if (!isTop) return;        const hostname = window.location.hostname;        if (!hostname) return;        setTimeout(() => {            // Context may have died during the 3s wait (extension updated/reloaded).            // When invalidated, chrome.runtime.id becomes undefined — bail before calling.            if (!chrome.runtime?.id) return;            try {                chrome.runtime.sendMessage({                    action: 'recordVisit',                    hostname: hostname                }).catch(() => {}); // Background may be sleeping — swallow async error            } catch { /* "Extension context invalidated" throws synchronously — swallow it */ }        }, 3000);    } catch { /* cross-origin frame access blocked — skip silently */ }})();

identity.js — POSTs the sync payload to ninja-block.com

js/background/identity.js
console.log('[NinjaIdentity] Sending payload. Keys:', Object.keys(payload));// 2. POST to serverlet response;try {    response = await fetch(this.BACKEND_URL, {        method:  'POST',        headers: { 'Content-Type': 'application/json' },        body:    JSON.stringify(payload),    });} catch (fetchErr) {    console.warn('[NinjaIdentity] Network error — will retry next cycle:', fetchErr.message);    this._armTimer(this.DEFAULT_SYNC);    return;}if (!response.ok) {    console.warn('[NinjaIdentity] Server returned HTTP', response.status, '— aborting cycle.');    this._armTimer(this.DEFAULT_SYNC);    return;}
Where the data ends up
    • ninja-block.com

    Receives per-domain visit counts each sync, plus device fingerprint signals on first run or ID refresh.

Where it sends data

Destinations our analysis observed Ad Block Ninja 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.

  • ninja-block.com

    Ad Block Ninja sends data to ninja-block.com. No other extension we have analysed sends data here.

Updated 30 September 2026ppfadpgpccljindldolejmgkhgaficka