Is Upwork toolkit - your own freelance assistant safe?
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.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
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.
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 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.
Fires about 10 seconds after install, then repeats every 24 hours for as long as the extension is enabled.
{
"event": "daily_report",
"params": {
"enabled": true,
"compactList": false,
"darkMode": false,
"soundVolume": 1,
"soundEnabled": true,
"schedulingEnabled": false,
"usernameHash": null
}
}| Field | Value | Why it matters | |
|---|---|---|---|
Hashed Upwork username | 9f2b7a1e4c803d5f6a91b2c3d4e5f6071829a3b4c5d6e7f8091a2b3c4d5e6f7 | A SHA-256 hash of your Upwork username. Ties every report to the same person across days without storing the name itself. | |
Extension on/off | true | Whether you currently have the extension turned on. | |
Compact list view | false | Whether you display job listings in the compact list layout. | |
Dark mode | false | Whether your extension theme is set to dark mode. | |
Sound alert volume | 1 | The volume level you set for new job sound alerts. | |
Sound alerts on/off | true | Whether sound alerts for new jobs are turned on. | |
Working-hours scheduling | false | Whether you have restricted job alerts to specific days and hours. |
Hashing and daily-report function, and the alarm that triggers it
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
}
});
};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 }
];- google-analytics.com
Receives the daily settings and username-hash beacon at Google's Measurement Protocol collect endpoint.