Security Alert: Confirmed Malware
Click Translator
ID: pmlpcplomjofbnlcihpacmcaahellokg
Supported Languages
Extension Info & Metadata
Publisher Contextual Analysis
- Author
- Click TranslatorView Profile
- Privacy
- Privacy Policy
- MX records exist
- Yes
- Domain exists
- Yes
- Is disposable
- No
- Is role-based
- No
- Mailbox exists
- Yes
One click translate on web page. Select a text and click the 'Translator' icon
Overlay translate provides translation with a single click. Click on the icon near the selected text and get a translation within 1 second. Features: โฐ One-click translation on any page โฐ Set the translation language from the popup ! You should select the translation language in the extension's popup.
The declarativeNetRequest rule removes both casing variants of X-Frame-Options from Google Translate responses, deliberately dismantling the clickjacking protection Google set on its own domain. This is a prerequisite for UI redressing attacks: the extension frames translate.google.com in its popup, and this rule surgically removes the header that would prevent that framing โ Google never consented to being embedded this way.
[ { "id": 1, "priority": 1, "action": { "type": "modifyHeaders", "responseHeaders": [ { "header": "X-Frame-Options", "operation": "remove" }, { "header": "x-frame-options", "operation": "remove" } ], "requestHeaders": [ { "header": "cookie", "operation": "remove" }, { "header": "sec-ch-ua", "operation": "remove" }, { "header": "sec-ch-ua-mobile", "operation": "remove" }, { "header": "sec-ch-ua-platform", "operation": "remove" }, { "header": "sec-fetch-mode", "operation": "remove" }, { "header": "sec-fetch-site", "operation": "remove" }, { "header": "upgrade-insecure-requests", "operation": "remove" }, { "header": "user-agent", "operation": "remove" }, { "header": "x-client-data", "operation": "remove" } ] }, "condition": { "urlFilter": "*://translate.google.com/*", "resourceTypes": [ "sub_frame" ] } }]On install, the extension generates a persistent UUID ('cid') stored in chrome.storage.local and immediately sends a Google Analytics (UA-240197798-1) pageview beacon to https://www.google-analytics.com/collect, including the cid, the extension's chrome.runtime.id, and a document host. This constitutes undisclosed user tracking: a stable cross-session identifier tied to the specific installed extension instance is exfiltrated to a third-party analytics property without user consent.
async function l() { const Fz = await new Promise((Fz => { chrome.storage.local.get(["cid"], (yC => { Fz(yC) })) })); let { cid: yC } = Fz; return yC || (yC = (0, LL.v4)(), chrome.storage.local.set({ cid: yC })), yC}async function Cy(Fz) { const yC = undefined, yQ = { v: "1", tid: Fz, cid: await l(), t: "pageview", dp: "/background", dt: "background", dh: `chrome-extension://${chrome.runtime.id}` }, LL = `https://www.google-analytics.com/collect?${new URLSearchParams(yQ).toString()}`; await fetch(LL, { method: "POST", body: "" }), chrome.alarms && chrome.alarms.create("ga3", { periodInMinutes: 60 * 24 })}On first install, the background script queries ALL open tabs (chrome.tabs.query({})) with no URL filtering and immediately injects content.js and content.css into every tab including allFrames:true. This gives the extension immediate DOM access to all already-open pages โ including sensitive pages like banking, email, and password managers โ before the user has configured or consciously activated the extension.
chrome.runtime.onInstalled.addListener((async Fz => { if ("install" === Fz.reason) { const Fz = "js/content.js", yC = await chrome.tabs.query({}); for (const yQ of yC) if (yQ.id) try { await chrome.scripting.executeScript({ target: { tabId: yQ.id, allFrames: !0 }, files: [Fz] }), await chrome.scripting.insertCSS({ target: { tabId: yQ.id, allFrames: !0 }, files: ["css/content.css"] }) } catch (Fz) {} }}));The rule strips the cookie request header from all sub-frame requests to translate.google.com, forcing every embedded Google Translate interaction to be unauthenticated and stripping the user's Google session identity from those requests. Combined with removing sec-fetch-mode, sec-fetch-site, and upgrade-insecure-requests, the extension degrades the browser's CORS and mixed-content integrity signals without user knowledge or consent.
[{"id":1,..."requestHeaders":[{"header":"cookie","operation":"remove"},{"header":"sec-fetch-mode","operation":"remove"},{"header":"sec-fetch-site","operation":"remove"},{"header":"upgrade-insecure-requests","operation":"remove"},...],"condition":{"urlFilter":"*://translate.google.com/*","resourceTypes":["sub_frame"]}}]Stripping user-agent, x-client-data (Google's client-integrity header), and all sec-ch-ua client hints removes Google's browser-fingerprint and client-integrity signals from requests to translate.google.com sub-frames. This bypasses Google's abuse-detection mechanisms that rely on these headers to identify and rate-limit non-browser or extension-embedded traffic using the unofficial 'gtx' scraper client.
[{"id":1,..."requestHeaders":[...,{"header":"sec-ch-ua","operation":"remove"},{"header":"sec-ch-ua-mobile","operation":"remove"},{"header":"sec-ch-ua-platform","operation":"remove"},{"header":"user-agent","operation":"remove"},{"header":"x-client-data","operation":"remove"}],...}]After the initial analytics ping, a daily repeating alarm named 'ga3' is created (periodInMinutes: 1440), yet no chrome.alarms.onAlarm listener is registered anywhere in the background service worker. This is a pattern consistent with dormant or placeholder C2 beacon infrastructure where a future update could register a handler to act on the alarm; the alarm persists across browser restarts.
chrome.alarms && chrome.alarms.create("ga3", { periodInMinutes: 60 * 24})The content script injects a floating UI widget into every page body (matching <all_urls>) and continuously monitors all text selections via a global mouseup event listener. Every piece of text a user selects on any webpage โ including passwords shown as text, email content, or private documents โ is captured into selectionNode and held in memory, ready to be transmitted on click. This persistent selection monitoring on all URLs is beyond what an on-demand translation use case requires.
document.addEventListener("mouseup", (Fz => { if (Fz.target.closest("#translator-container")) return; selectionNode = null; const yC = window.getSelection(); if (yC && "Range" === yC.type && 0 !== yC.toString().length) try { ...selectionNode = yC;... } catch (Fz) {}}));Selected text from any webpage is sent to Google's unofficial scraper client endpoint using client:'gtx' (an unauthorized scraper identifier, not an approved API key). The translation response is then inserted via translateSpan.innerHTML += Fz.trans without sanitization, creating a reflected XSS vector if the translation endpoint were ever compromised or substituted by the declarativeNetRequest rules.
$.ajax({ url: "https://translate.googleapis.com/translate_a/single?dt=t&dt=bd&dt=qc&dt=rm&dt=ex", type: "GET", dataType: "json", ...data: { client: "gtx", hl: Fz, sl: "auto", tl: Fz, q: selectionNode.toString(), ... }, success: yC => { ... for (const Fz of yC.sentences) Fz.trans && (translateSpan.innerHTML += Fz.trans); }});The popup embeds the full Google Translate mobile interface in an iframe. Companion declarativeNetRequest rules strip X-Frame-Options headers from Google Translate responses specifically to enable this framing, deliberately bypassing a clickjacking protection that Google itself set. Any text the user types into the embedded iframe is sent directly to Google without the extension disclosing this data flow.
const iframe = document.createElement("iframe");iframe.src = "https://translate.google.com/m", iframe.addEventListener("load", (() => { document.getElementById("loader").style.display = "none", iframe.style.display = "block"})), setTimeout((() => { $("#wrapper").append(iframe)}), 100)The entire jQuery 3.4.1 library (~96 KB of the 97 KB file) has been re-obfuscated with custom non-standard variable names (Fz, yC, yQ, LL instead of the conventional minification patterns used in the official jQuery dist). Standard minifiers do not rename variables this way; this is a deliberate obfuscation pass that makes static analysis harder and is a strong indicator that the file was processed to evade detection tools rather than for legitimate build optimization.
! function(Fz, yC) { "use strict"; "object" == typeof module && "object" == typeof module.exports ? module.exports = Fz.document ? yC(Fz, !0) : function(Fz) { if (!Fz.document) throw new Error("jQuery requires a window with a document"); return yC(Fz) } : yC(Fz)}("undefined" != typeof window ? window : this, (function(Fz, yC) { "use strict"; var yQ = [], LL = Fz.document, l = Object.getPrototypeOf, Cy = yQ.slice, ... var bu = "3.4.1", Pb = function(Fz, yC) { return new Pb.fn.init(Fz, yC) }The content script stylesheet loads an external Google Fonts resource on every page where the content script injects (i.e., all URLs). This causes a network request to Google's servers on every page visit, which acts as a passive tracking beacon allowing Google (or a network observer) to correlate the user's full browsing history across all sites. A privacy-respecting extension would self-host the font instead.
@import url(https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap);By severity
Versions scanned
Showing 8 of 10 scanned versions with more than one unique finding. Counts are unique findings that include each version.
| Extension Version | Code Review Findings |
|---|---|
| 0.3.7 | 7 |
| 0.3.6 | 7 |
| 0.3.5 | 3 |
| 0.3.4 | 11 |
| 0.3.3 | 10 |
| 0.3.2 | 12 |
| 0.3.1 | 9 |
| 0.3.0 | 4 |
Files with findings
6 distinct paths โ top paths by unique finding count:
- js/background.js26
- js/content.js12
- rules/translator.json11
- js/popup.js9
- css/content.css4
- manifest.json1
URLs
View the external URLs this extension communicates with to understand its network activity and data interactions.
Gain full insight into all external connections.
Upgrade for full visibility.
Gain full insight into all external connections.
Upgrade for full visibility.
Code Diff
Compare extension code between any two versions.
No comparable text files found between these versions.
Browse and explore files within this extension package
Gain full insight into all external connections.
Upgrade for full visibility.