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
45Risk

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

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

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.

01EvidenceCAUSE EFFECT
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.

02EvidenceFIELD TABLE
Fields in the captured install-tracking request body
FieldValueWhy it matters
Event name
installTells appbox.space this request represents a fresh install.
Paywall ID (wallId)
704Identifies this extension inside appbox.space's paywall platform, which the same vendor reuses across other extensions.
Extension ID
iabnclnclchijjckhdljmocghgmgnniiThe Chrome Web Store ID of the extension that sent the request.
Persistent user ID
0c14b6fd-9a73-4753-b432-5365d43f4a73A random ID generated once on your device and reused on every future request, letting appbox.space recognize you across sessions.
03EvidenceNETWORK CAPTURE
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-Typeapplication/json
Body
{
  "event": "install",
  "wallId": 704,
  "extensionId": "iabnclnclchijjckhdljmocghgmgnnii",
  "userId": "0c14b6fd-9a73-4753-b432-5365d43f4a73"
}
04EvidenceCODE COMPARE
The code that does this

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

What it actually does
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.spacebackground.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 UUIDbackground.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);
      });
    }
  });
}
05EvidenceTHIRD PARTY LIST
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.

SeverityLOW
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

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.

01EvidenceCAUSE EFFECT
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.

02EvidenceNETWORK CAPTURE
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-typeapplication/json
Body
{
  "banner_id": "darkmodegdocs_to_darkmodechrome1504_v1",
  "timestamp_ms": 1717430412381
}
03EvidenceFIELD TABLE
Fields sent in every impression and click POST
FieldValueWhy it matters
Banner campaign ID
darkmodegdocs_to_darkmodechrome1504_v1Identifies which promotional campaign triggered the beacon, letting the server correlate impressions and clicks to a user population.
Client timestamp
1717430412381Records the precise moment you opened the popup, letting the server reconstruct your usage patterns over time.
04EvidenceCODE COMPARE
The code that does this

sendImpression and sendClick in banner.js

What it actually does
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(),
  };
}
05EvidenceTHIRD PARTY LIST
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