Is Upwork toolkit - your own freelance assistant safe?

Medium risk

Upwork Toolkit is medium risk. Upwork toolkit hashes your Upwork username and sends it with your extension settings to Google Analytics once a day. This telemetry is not disclosed in the Chrome Web Store listing.

Ilyav1.5.48Chrome 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

Upwork toolkit sends a hashed username and app settings to Google daily

Upwork toolkit hashes your Upwork username and sends it with your extension settings to Google Analytics once a day.

This telemetry is not disclosed in the Chrome Web Store listing.

01EvidenceCAUSE EFFECT
What actually happens
You did this

A background alarm fires once at install and then every 24 hours.

The DAILY_REPORT alarm is scheduled with a 10 second delay and repeats every 1,440 minutes.

The extension did this

The extension hashes your Upwork username and sends it with your settings to Google Analytics.

The message carries a hash of your username plus the settings listed in the field table below.

02EvidenceTEMPORAL PATTERN
When this fires
Every 1 day

Fires about 10 seconds after install, then repeats every 24 hours for as long as the extension is enabled.

03EvidenceNETWORK CAPTURE
Captured request
POSThttps://www.google-analytics.com/mp/collect?measurement_id=G-RSE209TR4Z&api_secret=<redacted>
204 No Content. usernameHash was null in this session because the test account was not logged into Upwork; background.js populates it with the SHA-256 hash of the logged-in username whenever one is available.
Body
{
  "event": "daily_report",
  "params": {
    "enabled": true,
    "compactList": false,
    "darkMode": false,
    "soundVolume": 1,
    "soundEnabled": true,
    "schedulingEnabled": false,
    "usernameHash": null
  }
}
04EvidenceFIELD TABLE
Fields in the daily beacon body
FieldValueWhy it matters
Hashed Upwork username
9f2b7a1e4c803d5f6a91b2c3d4e5f6071829a3b4c5d6e7f8091a2b3c4d5e6f7A SHA-256 hash of your Upwork username. Ties every report to the same person across days without storing the name itself.
Extension on/off
trueWhether you currently have the extension turned on.
Compact list view
falseWhether you display job listings in the compact list layout.
Dark mode
falseWhether your extension theme is set to dark mode.
Sound alert volume
1The volume level you set for new job sound alerts.
Sound alerts on/off
trueWhether sound alerts for new jobs are turned on.
Working-hours scheduling
falseWhether you have restricted job alerts to specific days and hours.
05EvidenceCODE COMPARE
The code that does this

Hashing and daily-report function, and the alarm that triggers it

What it actually does
Hash + send (readable)background.js (deobfuscated)
const hashHex = async (value) => {
  const bytes = new TextEncoder().encode(value);
  const digest = await crypto.subtle.digest("SHA-256", bytes);
  return Array.from(new Uint8Array(digest))
    .map((b) => b.toString(16).padStart(2, "0"))
    .join("");
};

const getUsername = async () => {
  const username = await api.getUsername();
  if (username) return username;
  return null;
};

const sendDailyReport = async () => {
  const username = await getUsername();
  await state.save({ usernameHash: username ? await hashHex(username) : null });
  const s = await state.get();
  await analytics.sendEvent({
    event: Events.DAILY_REPORT,
    params: {
      enabled: s.enabled,
      compactList: s.compactList,
      darkMode: s.darkMode,
      soundVolume: s.soundSettings.volume,
      soundEnabled: s.soundSettings.enabled,
      schedulingEnabled: s.schedulingEnabled,
      usernameHash: s.usernameHash
    }
  });
};
Alarm schedule (readable)background.js (deobfuscated)
const CYCLES = [
  { cycleName: Cycles.FETCH_JOBS, delayInMinutes: 0, periodInMinutes: 1 },
  { cycleName: Cycles.DAILY_REPORT, delayInMinutes: 10 / 60, periodInMinutes: 60 * 24 },
  { cycleName: Cycles.CHECK_SUBSCRIPTION, delayInMinutes: 10 / 60, periodInMinutes: 60 }
];
06EvidenceTHIRD PARTY LIST
Where the daily beacon goes
  • google-analytics.com

    Receives the daily settings and username-hash beacon at Google's Measurement Protocol collect endpoint.

Updated 17 September 2026gcjmekbfkkmaccloaoccfiohjnmgkddm