Is Gmail Message Preview by cloudHQ safe?

Medium risk

Gmail Message Preview sends every signed-in Gmail address it finds to cloudHQ's servers.

When Gmail loads, the extension checks /mail/u/N/ pages to discover each Google account signed in to the browser, then posts the full list of addresses to cloudHQ. The check repeats roughly every two weeks and runs without a separate consent step.

Strong link to a flagged operator: 3 of the 17 other listings from the same operator are rated high or critical for malicious behaviour. Flagged: Export Emails to Sheets by cloudHQ (high), Email Signature Generator by cloudHQ (high), Mobile Text Alerts (high).

cloudHQv1.0.3.4Chrome Web Store
49Risk
Who publishes it

cloudHQ LLC - 17 other listings from the same operator, 8 of them carrying a finding

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

Publisher
cloudHQ
Declared legal entity
cloudHQ LLC
Registered address
2247 29th Ave, San Francisco, CA 94116-1738, US
Registered contact
cloudHQ LLC

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

Publishers can request a review.

Findings

cloudHQ Gmail extension sends all signed-in Gmail addresses to cloudhq.net

Code analysis shows the content script probes mail/u/0..20 to list every signed-in Gmail account, then POSTs the list to cloudhq.net/main_pre_user/check, with no consent step.

Severity
High unwanted
Type
Unexpected
CWE
CWE-359
Source
Static analysis
What actually happens
You did this

You open Gmail while signed in to one or more Google accounts.

The extension did this

The extension lists every signed-in address and sends the list to www.cloudhq.net.

The code that does this

Pre-check POST carrying the account list

Readable version

fn_pre_user_check

content.js
  fn_pre_user_check = function(e) {    var t = this;    try {      var n = t.g_email_or_login + t.g_cloudHQ_feature_name + "_pre_check_obj",        r = ((new Date).getTime(), {          value: "true",          timestamp: (new Date).getTime()        }),        i = {};      i[n] = r, chrome.storage.local.get(n, (function(r) {        if (!r || !r[n] || !r[n].timestamp || r[n].timestamp < t.g_two_weeks_ago_timestamp) try {          t.fn_get_switcher_account_emails((function() {            t.fn_ajax({              type: "POST",              url: t.g_server_url + "main_pre_user/check",              dataType: "json",              data: {                email: t.g_email_or_login,                email_switcher_list: t.g_switcher_account_emails,                email_or_login: t.g_email_or_login,                chrome_extension_name: t.g_cloudHQ_feature_name,                switch_login: "1"              },              complete: function(e, t) {                if (-1 === ["error", "timeout", "abort"].indexOf(t)) try {                  chrome.storage.local.set(i, (function() {}))                } catch (e) {}              }            })          }), e)        } catch (e) {          console.log("e:", e)
The code that does this

Account probing across mail/u/N

Readable version

Probe loop and URL

content.js
  fn_get_switcher_account_emails = function(e, t) {    var n = this;    if (n.g_switcher_account_emails_index > n.g_switcher_account_emails_max_tries) return n.g_email_or_login && -1 == n.g_switcher_account_emails.indexOf(n.g_email_or_login.toLowerCase()) && n.g_switcher_account_emails.push(n.g_email_or_login.toLowerCase()), void e();    try {              for (var a = 0; a < o.length; a++)                if (o[a] && n.fn_validate_email(o[a].replaceAll('"', ""))) {                  var s = o[a].replaceAll('"', "").toLowerCase();                  return n.g_switcher_account_emails && n.g_switcher_account_emails[0] && n.g_switcher_account_emails[0] == s ? (n.g_email_or_login && -1 == n.g_switcher_account_emails.indexOf(n.g_email_or_login.toLowerCase()) && n.g_switcher_account_emails.push(n.g_email_or_login.toLowerCase()), void e()) : (-1 == n.g_switcher_account_emails.indexOf(s) && n.g_switcher_account_emails.push(s), void n.fn_get_switcher_account_emails(e))
Fields in the POST body
  • Primary address
    jane.doe@gmail.com (illustrative)

    Address of the Gmail account in the active tab.

  • All signed-in accounts
    ["jane.doe@gmail.com","jane@acme-corp.com"] (illustrative)

    Every address found by probing mail/u/0 to mail/u/20.

  • Extension name
    chrome_extension_name

    Which cloudHQ extension sent the check.

  • Switch login flag
    1

    Constant flag sent with the request.

Where the data goes
    • www.cloudhq.net

    Receives POST /main_pre_user/check via the background PROXY_AJAX relay, which allow-lists this host.

Observation

Static analysis finding. This behaviour was identified by reading the shipped extension code and has not yet been reproduced in a live run. The trigger conditions and the exact data sent are read from the code, not from an observed capture.

What it can do

Permissions this extension asks for, as declared in version 1.0.3.4. 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 mail.google.com

    https://mail.google.com/

  • Read and change your data on www.cloudhq.net

    https://www.cloudhq.net/

  • Run its own code inside the pages you visit

    scripting

  • Store data in your browser

    storage

  • Keep running in the background while your browser is open

    background

Where it sends data

Destinations our analysis observed Gmail Message Preview by cloudHQ 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.

  • www.cloudhq.netwidely used

    Gmail Message Preview by cloudHQ sends data to www.cloudhq.net. A widely used service: 79 other extensions we have analysed send data here.

Updated 15 October 2026iencecfjahgolpojakafmnobbkfgcehp