Is Dark Mode Google Docs safe?

Medium risk

Dark Mode Google Docs is medium risk. On install, the extension generates a random UUID, saves it via storage.sync as user_id/pw-704-visitor-id, and POSTs it to appbox.space/api/track-event with the install event and wallId 704, syncing to every Chrome profile on your account.…

DarkModev4.9.65Chrome Web Store
47Risk

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

Publishers can request a review.

Findings

Install sends a persistent UUID to appbox.space

On install, the extension generates a random UUID, saves it via storage.sync as user_id/pw-704-visitor-id, and POSTs it to appbox.space/api/track-event with the install event and wallId 704, syncing to every Chrome profile on your account.

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

You install the extension for the first time.

chrome.runtime.onInstalled fires with reason INSTALL.

The extension did this

The extension creates a permanent random ID for you and reports it to appbox.space, the vendor's paywall platform.

The ID, install event, extension ID, and a wallId value are sent in a POST request to https://appbox.space/api/track-event.

Fields in the captured install-tracking request body
  • Event name
    install

    Tells appbox.space this request represents a fresh install.

  • Paywall ID (wallId)
    704

    Identifies this extension inside appbox.space's paywall platform, which the same vendor reuses across other extensions.

  • Extension ID
    iabnclnclchijjckhdljmocghgmgnnii

    The Chrome Web Store ID of the extension that sent the request.

  • Persistent user ID
    0c14b6fd-9a73-4753-b432-5365d43f4a73

    A random ID generated once on your device and reused on every future request, letting appbox.space recognize you across sessions.

Captured request
POSThttps://appbox.space/api/track-event

No response body was recorded for this endpoint; the extension does not read the response.

Headers
Content-Type
application/json
Body
{  "event": "install",  "wallId": 704,  "extensionId": "iabnclnclchijjckhdljmocghgmgnnii",  "userId": "0c14b6fd-9a73-4753-b432-5365d43f4a73"}
The code that does this

Install listener and trackEvent()/getUserId() in the shipped extension

Readable version

onInstalled listener calling trackEvent('install')

background.js:5323-5344
chrome.runtime.onInstalled.addListener((details) => {  if (details.reason === chrome.runtime.OnInstalledReason.INSTALL) {    // Code to be executed on first install    // eg. open a tab with a url    chrome.storage.sync.set({      welcomePageOpened: true    })    chrome.tabs.create({      url: 'https://ext.aitools.band/dark-mode-google-docs/congrats',    })    chrome.storage.sync.set({      deviceId: crypto.randomUUID()    })    // Save install date to identify new users for paywall    const installDate = new Date().toISOString();    chrome.storage.sync.set({ installDate });    // Track install event for paywall    trackEvent('install');  } else if (details.reason === chrome.runtime.OnInstalledReason.UPDATE) {

trackEvent() posts to appbox.space

background.js:5469-5483
function trackEvent(eventName, additionalData = {}) {  getUserId(userId => {    fetch('https://appbox.space/api/track-event', {      method: 'POST',      headers: { 'Content-Type': 'application/json' },      body: JSON.stringify({        event: eventName,        wallId: 704,        extensionId: chrome.runtime.id,        userId: userId,        ...additionalData,      }),    });  });}

getUserId() creates and persists the UUID

background.js:5496-5506
function getUserId(callback) {  chrome.storage.sync.get(['user_id'], result => {    if (result.user_id) {      callback(result.user_id);    } else {      const userId = crypto.randomUUID();      chrome.storage.sync.set({ user_id: userId, ['pw-704-visitor-id']: userId }, () => {        callback(userId);      });    }  });}
Hosts involved in install tracking
    • appbox.space

    Receives the install event, extension ID, wallId, and persistent UUID; also runs the vendor's paywall iframe (monetize.software), shared across the developer's other extensions.

Popup Sends Ad Impression and Click Beacons to Third-Party Server

Each time you open the popup, the extension POSTs to a Cloudflare Workers server (ext-ads-mvp.captain-products.workers.dev) logging a banner view.

Clicking sends a second POST before opening the Store listing for a sibling extension.

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

You open the extension popup.

Clicking the toolbar icon causes ui/popup/index.html to load, which includes banner.js via a script tag.

The extension did this

The extension without notifying the user posts an impression event to a third-party Cloudflare Workers endpoint.

banner.js calls sendImpression(), which POSTs {banner_id, timestamp_ms} to https://ext-ads-mvp.captain-products.workers.dev/impression with keepalive:true.

Captured request
POSThttps://ext-ads-mvp.captain-products.workers.dev/impression

Static analysis only; no live capture. Payload shape confirmed from banner.js:98-103 getEventPayload().

Headers
content-type
application/json
Body
{  "banner_id": "darkmodegdocs_to_darkmodechrome1504_v1",  "timestamp_ms": 1717430412381}
Fields sent in every impression and click POST
  • Banner campaign ID
    darkmodegdocs_to_darkmodechrome1504_v1

    Identifies which promotional campaign triggered the beacon, letting the server correlate impressions and clicks to a user population.

  • Client timestamp
    1717430412381

    Records the precise moment you opened the popup, letting the server reconstruct your usage patterns over time.

The code that does this

sendImpression and sendClick in banner.js

Readable version
function sendImpression(config) {  postEvent(    "impression",    config.apiBaseUrl + config.impressionPath,    getEventPayload(config)  );}function sendClick(config) {  postEvent(    "click",    config.apiBaseUrl + config.clickPath,    getEventPayload(config)  );}function getEventPayload(config) {  return {    banner_id: config.bannerId,    timestamp_ms: Date.now(),  };}
Endpoints receiving beacon data
    • ext-ads-mvp.captain-products.workers.dev

    Cloudflare Workers endpoint run by the developer. Receives impression events on every popup open and click events on banner clicks. Distinct from the appbox.space paywall domain.

Updated 21 September 2026iabnclnclchijjckhdljmocghgmgnnii