Is Click&Clean safe?

Medium risk

Click&Clean is medium risk. Click&Clean's service worker counts your browsing history and sends the count, timezone, language, and a fingerprint to api64.com on install and every 3 hours, with no opt-out. A capture showed count=72, timezone, and language on the wire.…

www.hotcleaner.comv9.8.2.0Chrome Web Store
45Risk
Who publishes it

www.hotcleaner.com - 1 other listing from the same operator, none carrying a finding

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

Same store account

1 other listing published from this account, 400k+ users between them, none of them carrying a finding.

Shared hosts - 1 hostname

Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.

api64.com
Also called by 3 other listings, including Magic Actions for YouTube

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

Click&Clean Sends Browsing-History Count and Fingerprint to api64.com

Click&Clean's service worker counts your browsing history and sends the count, timezone, language, and a fingerprint to api64.com on install and every 3 hours, with no opt-out.

A capture showed count=72, timezone, and language on the wire.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You install Click&Clean, or your browser starts up with it already installed.

The extension did this

The service worker automatically counts your entire browsing history, gathers fingerprint data, and sends it to api64.com without asking.

This repeats on a fixed timer, independent of anything else you do in the browser.

02EvidenceTEMPORAL PATTERN
When this fires
Every 3 hours

Fires once on install (or first run after this version was installed), then again roughly every 3 hours for as long as the browser keeps the extension's service worker active.

03EvidenceFIELD TABLE
Fields confirmed in a captured check-in request
FieldValueWhy it matters
Browsing history count
72The number of pages Chrome has recorded in your history, up to 1,000. This is a count, not the URLs themselves.
Timezone offset
0Your local timezone relative to UTC, used as a fingerprinting signal.
Browser language
en-USYour browser's configured display language.
Browser brand/version fingerprint
Google Chrome 128.0.6613.84, WindowsBrowser brand, full version, platform, and Chromium build number, read via User-Agent Client Hints and sent in the same request.
04EvidenceCODE COMPARE
The code that does this

esw901.js, Xa() builds the payload, dc() gates when it fires

What it actually does
// Xa() — builds the telemetry payload and sends the periodic check-in
async function sendCheckIn(extraFields) {
  try {
    const [brandIndex, fullVersionParts, platformCode, chromiumVersionParts] = await getBrowserFingerprint();
    const historyResults = await chrome.history.search({ text: '', maxResults: 1000, startTime: 1 });
    const now = Date.now();
    const historyCount = historyResults?.length || 0;

    const payload = {
      // ...internal usage counters (a, b, c, d, r, s, t, u, v, w, x, y)...
      o: new Date().getTimezoneOffset() / 60,   // timezone offset in hours
      p: navigator.language || '',              // browser language
      q: historyCount,                          // TOTAL BROWSING HISTORY COUNT
      // ...browser brand/version/platform fingerprint fields (e, f, g, h, i, j, k, l, m, n)...
    };
    if (extraFields) Object.assign(payload, extraFields);

    const [configResponse, httpStatus] = await fetchJson(
      'https://api64.com/upd2',
      { method: 'POST', cache: 'no-store', body: JSON.stringify(payload), headers: { 'Content-Type': 'application/json' } },
      'json'
    );
    if (httpStatus === 0) await applyRemoteConfig(configResponse);
    return httpStatus || configResponse;
  } catch (e) {
    console.info(e);
    return 5;
  }
}

// dc() — gates sendCheckIn() to roughly once per 3-hour bucket
function checkThreeHourGate() {
  const msSinceAnchor = Date.now() - 1606687200000; // fixed anchor timestamp
  const bucket = msSinceAnchor < 10800000 ? 0 : Math.floor(msSinceAnchor / 10800000);
  if (storedState.uf !== bucket) {
    storedState.uf = bucket;
    sendCheckIn(null); // fires on the first run (bucket 0, i.e. fresh install) and every ~3 hours after
  }
}
05EvidenceTHIRD PARTY LIST
Where the data ends up
  • api64.com

    Receives history count, timezone, language, and device fingerprint from every install roughly every 3 hours, returning a remote-config payload the extension applies automatically.

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-829
SourceAI SANDBOX

api64.com Can Remotely Update Click&Clean's Domain Block List

When Click&Clean's check-in to api64.com succeeds, its response applies automatically, unconfirmed.

A capture added six hashed domains to the block list and set a region code.

Blocked domains, per source, get closed and purged from history.

01EvidenceCAUSE EFFECT
What actually happens
You did this

api64.com responds to the extension's periodic check-in with a JSON configuration payload.

The check-in itself is described in the companion finding on the same endpoint.

The extension did this

The service worker applies the payload immediately: it can rewrite the domain block list, change internal flags, and clear cookies/cache for hotcleaner.com, without notifying you.

The extension trusts any HTTP 200 response body from this one endpoint.

02EvidenceFIELD TABLE
Fields in a captured api64.com/upd2 response, and what the code does with them
FieldValueWhy it matters
New domain block-list entries ('goa')
[372951892, -1323393189, -1200674118, -1371159776, 1891317919, 1120470599]Six hashed values sent by the server are appended permanently to the extension's domain block list.
Default-site variant code ('dc')
13Selects which region's 'default' sites the extension treats specially, set by the server, not shown to you.
Ready flag ('sf')
1Tells the extension the response is valid config; the block-list fields above are only applied when this is present.
03EvidenceCODE COMPARE
The code that does this

esw901.js, cc() applies the server's response; ob()/nb() later enforce the block list it builds

What it actually does
cc() — remote-config processor (confirmed via captured traffic)
// cc() — applies whatever the server sent, unconditionally, on HTTP 200
async function applyRemoteConfig(config) {
  if ('sf' in config) {
    if ('gg' in config) state.gg = config.gg;             // "site guard" flag
    if ('gf' in config) state.gf = config.gf;             // "path guard" flag
    if ('goc' in config) state.blockedOrigins.length = 0;  // clear origin block list
    if ('gpc' in config) state.blockedPaths.length = 0;    // clear path block list
    if ('gor' in config) removeEntries(state.blockedOrigins, config.gor);
    if ('gpr' in config) removeEntries(state.blockedPaths, config.gpr);
    if ('goa' in config) appendUnique(state.blockedOrigins, config.goa); // ADD hashed origins to block list
    if ('gpa' in config) appendUnique(state.blockedPaths, config.gpa);
  }
  if ('dc' in config) state.defaultSiteVariant = config.dc; // selects region "default sites" set
  if ('sm' in config) {
    // Feature-flag branch — only reachable if the response ALSO carries 'sm'.
    if ('mr' in config) state.mr = config.mr;
    if ('ma' in config) state.ma = config.ma;
    if ('ml' in config) state.ml = config.ml;
    if ('mt' in config && state.mt !== config.mt) { /* toggle a history-visit listener */ }
  }
  if ('rtc' in config) await chrome.browsingData.remove({ origins: ['https://hotcleaner.com'] }, { cookies: true, cache: true, localStorage: true });
  if ('op' in config) await setOptOutCookie(config.op); // sets an opt-out cookie on doubleclick.net
  await persistState();
}
ob()/nb() — block-list enforcement on every history visit (code review only, not separately re-verified in this DA session)
// ob()/nb() — the block list built by applyRemoteConfig() is enforced here,
// on every browsing-history visit event (not independently verified in this
// dynamic-analysis session; shown from code review of the same file).
function checkAgainstBlockList(visitedUrl) {
  const url = new URL(visitedUrl);
  if (state.blockedOrigins.includes(hash(url.origin))) {
    closeMatchingTabsAndForgetHistory(url.origin + '/');
  } else if (state.blockedPaths.includes(hash(url.origin + url.pathname))) {
    closeMatchingTabsAndForgetHistory(url.origin + url.pathname);
  }
}

function closeMatchingTabsAndForgetHistory(urlPrefix) {
  chrome.tabs.query({ url: urlPrefix + '*' }, (tabs) => {
    if (tabs.length > 0) {
      chrome.tabs.create({ url: 'chrome://newtab' });
      for (const tab of tabs) {
        chrome.tabs.remove(tab.id);
        chrome.history.deleteUrl({ url: tab.url });
      }
    }
  });
}
04EvidenceTEMPORAL PATTERN
When this fires
Every 3 hours

The config-processing step runs synchronously whenever the api64.com/upd2 check-in succeeds, which itself fires on install and roughly every 3 hours the browser is active.

05EvidenceTHIRD PARTY LIST
Who controls the extension's behavior
  • api64.com

    Its response to the check-in is applied to the domain block list and internal flags unconditionally on HTTP 200, no allowlist of safe fields, no on-screen disclosure.

What it can do

Permissions this extension asks for, as declared in version 9.8.2.0. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.

  • Read and change your data on every site you visit

    http://*/*

  • Read and change your data on every secure site you visit

    https://*/*

  • See the address and title of every tab you have open

    tabs

  • Clear your browsing history, cache and cookies

    browsingData

  • Read and change your full browsing history

    history

  • Read and change cookies, including the ones that keep you signed in

    cookies

  • Run its own code inside the pages you visit

    scripting

  • Store data in your browser

    storage

  • Add items to the right-click menu

    contextMenus

Updated 30 September 2026ghgabhipcejejjmhhchfonmamedcbeod