Is Color Picker Chrome extension safe?
Color Picker reports the full URL and referrer of every page you visit to gopickcolors.com, keyed to a persistent ID.
A content script running on every site sends each page load and in-page navigation to the extension's background worker, which forwards the URL, referrer, and timestamp to gopickcolors.com/api/analytics/v2 tagged with a permanent random user ID. A fresh install asks for consent first, but when the extension updates it silently sets the consent flag to true, enabling this URL reporting for existing users without any prompt.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Color Picker Sends Every URL You Visit to Developer Server
Dynamic analysis captured three POSTs from Color Picker to gopickcolors.com/api/analytics/v2.
On every page load and SPA navigation, the content script sends the URL, referrer, a tracking UUID, and timestamp.
Consent can auto-set on update.
You visit any web page while the extension is installed and consent has been granted.
The extension records the full URL, where you came from, and a permanent tracking ID, and transmits them to gopickcolors.com.
This fires on initial page load and again on every single-page-app route change, without any further user interaction.
| Content-Type | application/json |
{
"uid": "15015237-87c7-4563-b993-fa9635338b77",
"uri": "https://www.google.com/",
"docref": null,
"timestamp": 1780880496833
}| Field | Value | Why it matters | |
|---|---|---|---|
The URL you are visiting | https://mail.google.com/mail/u/0/#inbox | The exact address of the page, including any query parameters or session tokens in the URL. | |
The page you came from | https://www.google.com/ | The URL of the previous page you were on, linking consecutive visits together. | |
Your permanent tracking ID | 15015237-87c7-4563-b993-fa9635338b77 | A UUID generated once and stored permanently in local storage. It ties all your page visits together across sessions and sites. | |
Timestamp | 1780880496833 | Millisecond-precision time of the visit, enabling reconstruction of your browsing timeline. |
Content script: URL capture and relay to service worker (content.js lines 653-683)
!(function () { "use strict"; let e = location.href; function n(n) { const t = performance.getEntriesByType("navigation")[0], o = e, r = { url: location.href, referrer: document.referrer || null, navigationType: t?.type || null, trigger: n, spaReferrer: "spa_navigation" === n ? o : null, }; e = location.href; try { chrome.runtime.sendMessage({ type: "PAGE_DATA", payload: r }); } catch (e) {} } n("page_load"); new MutationObserver(() => { location.href !== e && n("spa_navigation"); }).observe(document, { subtree: true, childList: true }); window.addEventListener("popstate", () => { location.href !== e && n("spa_navigation"); }); })();Service worker: assembles and POSTs the analytics payload (background.js lines 117-134)
const handlePageData = async (e, t) => { if (!t || !t.id) return; const { consentGiven: r } = await chrome.storage.local.get("consentGiven"); if (true !== r) return; if (!isValidPage(e.url)) return; if (t.incognito) return; if (shouldDrop(e)) return; if (!shouldEmit(t.id, e.url)) return; const a = { uid: await ensureUserId(), uri: e.url, docref: resolveReferrer(e), timestamp: Date.now(), }; await postData("https://gopickcolors.com/api/analytics/v2", a); };- gopickcolors.com
Developer-operated analytics endpoint. Receives full URL, referrer, persistent UUID, and timestamp on every page navigation.
Extension Update Auto-Enables URL Tracking Without User Consent
When Color Picker installs under reason='update', the worker writes consentGiven=true with no prompt, unlike a fresh install's Agree overlay.
Since the gate checks only this flag, updated users start sending history on the next navigation.
Chrome updates the Color Picker extension to a new version in the background.
The service worker writes consentGiven=true in local storage with no prompt, enabling URL tracking for every subsequent page visit.
If you had previously declined tracking by clicking Disagree, the update overwrites that choice unconditionally.
onInstalled handler, install vs update paths (background.js lines 73-77)
if ("install" === e.reason) { await ensureUserId(); // Opens gopickcolors.com/#how-it-works — popup.js shows consent overlay there chrome.tabs.create({ url: "https://gopickcolors.com/#how-it-works" }); } else if ("update" === e.reason) { await ensureUserId(); // No UI — directly writes consent=true, overwriting any prior value await chrome.storage.local.set({ consentGiven: true }); }After an update this is set to true with no user action. The analytics worker checks only this key; any true value starts URL POSTs.
chrome.storage.local key 'consentGiven'{
"consentGiven": true
}dynamic analysis (fresh install, reason='install') shows chrome.storage.local.set called only for the uid key — consentGiven is never set by the background script on install, and zero analytics POSTs to gopickcolors.com were observed. This confirms the update path is the sole mechanism that writes consentGiven=true without user interaction.
- gopickcolors.com
Developer-operated analytics endpoint. Receives full browsing URLs and stable per-install UUID after the update auto-sets consent.