| 1 | Credential Theft | critical | background.js (line 1) | The background page receives email/password pairs from the content script, encrypts them with a hardcoded key, and stores them as `backgroundCredentials`. Persisting harvested website credentials inside the extension … | |
| 2 | Credential Theft | critical | background.js (line 1) | The background script intercepts messages containing user email and password credentials forwarded from the page_api.js bridge. Credentials are AES-encrypted with a hardcoded plaintext key ("niGKhB95YrpRpTjpaY9dyRNcCS… | |
| 3 | Credential Theft | critical | page_api.js (line 1) | This content script injects a script element into zenmate.com/zenmate.io pages that exposes window.__zm.updateWithCredentials — a globally accessible function any page-level script can call. When invoked with a creden… | |
| 4 | Credential Theft | critical | page_api.js (line 8) | The extension injects a script tag directly into every zenmate.com page's DOM, creating a global `window.__zm.updateWithCredentials` hook. When called, credentials are dispatched as a CustomEvent and forwarded to the … | |
| 5 | Credential Theft | critical | background.js (line 1) | When the background receives user credentials via runtime message, it encrypts them with CryptoJS AES using a hardcoded static key ('niGKhB95YrpRpTjpaY9dyRNcCSkn') and stores them in extension storage as 'backgroundCr… | |
| 6 | Credential Theft | critical | main.js (line 1) | The popup reads credentials from extension localStorage ('backgroundCredentials'), decrypts them with the hardcoded static AES key 'niGKhB95YrpRpTjpaY9dyRNcCSkn', auto-fills the login form, and submits it automaticall… | |
| 7 | Credential Theft | critical | main.js (line 1) | A component enumerates the active tab's cookies and silently deletes all cookies for `.cyberghostvpn.com` (a direct competitor VPN service) via `chrome.cookies.remove`. This would log the user out of the competing ser… | |
| 8 | Credential Theft | critical | page_api.js (line 1) | The content script runs at `document_start` on all zenmate.com/zenmate.io pages and injects a script element via `innerHTML` that exposes `window.__zm.updateWithCredentials(creds)` in the page context. Any code on the… | |
| 9 | Credential Theft | critical | background.js (line 1) | The extension intercepts user credentials (email and password) from message payloads and encrypts them with a hardcoded static AES key 'niGKhB95YrpRpTjpaY9dyRNcCSkn' before storing them in extension storage as 'backgr… | |
| 10 | Credential Theft | critical | page_api.js (line 1) | This content script, injected into all zenmate.com and zenmate.io pages at document_start, creates a JavaScript bridge object `window.__zm` in the page context by dynamically injecting a script tag into the DOM. This … | |
| 11 | Credential Theft | critical | background.js (line 1) | The background script captures email and password from the `updateWithCredentials` message, AES-encrypts the credential pair using a hardcoded key `"niGKhB95YrpRpTjpaY9dyRNcCSkn"` embedded in the source, and persists … | |
| 12 | Credential Theft | critical | main.js (line 1) | When the extension popup opens, it reads `backgroundCredentials` from storage, decrypts with the same hardcoded AES key, auto-populates the login form fields (username/password), and immediately calls `onSubmit()` — w… | |
| 13 | Other | critical | main.js (line 1) | The `removeAll()` method silently iterates over and deletes every cookie for `.cyberghostvpn.com`, which would immediately log the user out of a competing VPN product without any user action or disclosure. This is del… | |
| 14 | Unauthorized Data Collection | critical | main.js (line 1) | The extension explicitly targets CyberGhost VPN — a direct competitor — by querying chrome.history.search for ".cyberghostvpn.com" with maxResults:10000 to detect competitive product usage, then enumerating and deleti… | |
| 15 | Unauthorized Data Collection | critical | main.js (line 1921846) | This component reads the currently selected tab URL, enumerates all cookies for that domain, and also performs a `chrome.history.search` specifically targeting '.cyberghostvpn.com' (a competing VPN service) with up to… | |
| 16 | Code Injection | high | main.js (line 4810) | The extension includes a Script polyfill that implements runInThisContext using eval(). While used by internal libraries for dynamic function naming, the presence of an execution bridge combined with broad host permis… | |
| 17 | Code Injection | high | page_api.js (line 20) | The extension dynamically creates a script element and sets its innerHTML to a serialized function string, then appends it to the host page's DOM. This injects extension code into the page's main world JavaScript cont… | |
| 18 | Code Injection | high | page_api.js (line 20) | The content script dynamically injects executable code into the DOM via `script.innerHTML` before the page's own CSP is evaluated (runs at `document_start`). This circumvents the host page's Content Security Policy an… | |
| 19 | Code Injection | high | page_api.js (line 1) | The content script injects JavaScript into the page context by creating a script element with innerHTML set to a serialized function, bypassing the content script/page isolation boundary and exposing `window.__zm.upda… | |
| 20 | Code Injection | high | background.js (line 1) | The `exportPAC` method generates a PAC (Proxy Auto-Config) script by string-interpolating serialized engine state, JSON-encoded node dictionaries, and `pacScriptRegexp` directly into a JavaScript template without sani… | |
| 21 | Code Injection | high | manifest.json (line 48) | The manifest explicitly permits `'unsafe-eval'` in its Content Security Policy, allowing dynamic code evaluation via `eval()`, `new Function()`, or similar constructs anywhere inside the extension pages. This weakens … | |
| 22 | Credential Theft | high | page_api.js (line 8) | This content script injects a page-context helper and forwards arbitrary `email`/`password` data from the website into the privileged extension context. Even though the manifest limits this script to ZenMate-owned dom… | |
| 23 | Credential Theft | high | background.js (line 1037) | The background page persists captured credentials in extension storage after encrypting them with a hard-coded key embedded in the code. Hard-coded client-side encryption does not meaningfully protect secrets from any… | |
| 24 | Credential Theft | high | page_api.js (line 1) | This content script injects a page-context helper into `*.zenmate.com`/`*.zenmate.io` and forwards arbitrary `credentials` objects from the page into the extension background page. That is a credential capture bridge … | |
| 25 | Credential Theft | high | background.js (line 1) | The extension installs a blocking `chrome.webRequest.onAuthRequired` listener on `<all_urls>` that automatically responds to any proxy auth challenge with the device's `token` and `tokenSecret`. This means any server … | |
| 26 | Data Exfiltration | high | index.html (line 9) | The VPN extension popup loads Google Fonts stylesheets from fonts.googleapis.com every time it is opened. For users relying on ZenMate VPN for privacy, this causes their real IP address (or whatever network they're on… | |
| 27 | Data Exfiltration | high | background.js (line 1) | An ElasticSearch telemetry component enriches every behavioral event with the user's real IP country/city, subscription plan ID, and product ID, then POSTs to ZenMate's 'new-extension-feedback' endpoint every minute (… | |
| 28 | Data Exfiltration | high | background.js (line 1) | Every analytics event is enriched with the user's real country code, city (derived from their pre-VPN IP), subscription plan ID, and product ID before being POSTed to `zenmate.com/new-extension-feedback`. This pipelin… | |
| 29 | Data Exfiltration | high | background.js (line 1) | A persistent telemetry component automatically attaches the user's real country code, city, IP-derived geolocation, subscription plan details, and product ID to every behavioral event before POSTing them to `zenmate.c… | |
| 30 | Network Interception | high | manifest.json (line 36) | The extension requests extremely broad permissions including global host access (*://*/*), proxy settings control, and webRequestBlocking. These permissions allow the extension to intercept, modify, or redirect all br… | |
| 31 | Network Interception | high | background.js (line 444) | This code installs a blocking `webRequest.onAuthRequired` listener for `<all_urls>` and programmatically swaps the browser into PAC-script proxy mode. That gives the extension the ability to mediate essentially all br… | |
| 32 | Network Interception | high | background.js (line 372) | The background script answers proxy authentication challenges with a locally stored device token and secret. That means the extension maintains reusable credentials and automatically supplies them to network infrastru… | |
| 33 | Network Interception | high | background.js (line 444) | This code installs a blocking `onAuthRequired` handler for `<all_urls>` and then configures either a PAC script or fixed proxy settings. In practice, the extension is positioned to intercept and reroute essentially al… | |
| 34 | Network Interception | high | background.js (line 1) | This registers a blocking `onAuthRequired` handler for `<all_urls>` and dynamically replaces browser proxy settings with PAC/fixed proxy rules. That gives the extension full man-in-the-middle style control over networ… | |
| 35 | Network Interception | high | background.js (line 1) | The extension registers a blocking webRequest.onAuthRequired listener scoped to '<all_urls>', meaning it intercepts every HTTP authentication challenge in the entire browser — not just VPN proxy challenges. It automat… | |
| 36 | Other | high | assets/config/config.prod.json (line 1) | A static API key ('ZMEx4hfuto83htix763jf9cz3n59f73v659f') is hardcoded in the production config bundle and is identical to the dev key — meaning any user who unpacks the CRX has full API access. A hardcoded Infura pro… | |
| 37 | Other | high | assets/config/config.prod.json (line 13) | The production config includes Ethereum blockchain RPC endpoints (MyEtherWallet API and Infura with a hardcoded project ID) with `blockchainFallback: true`. A VPN extension has no disclosed legitimate use for Ethereum… | |
| 38 | Remote Code Loading | high | manifest.json (line 35) | The manifest combines high-risk traffic interception permissions with a CSP that explicitly allows remote scripts from Google Analytics and enables `unsafe-eval`. That combination increases the blast radius of any rem… | |
| 39 | Remote Code Loading | high | background.js (line 1) | The extension fetches remotely-controlled campaign configuration from an S3 bucket where the filename is determined server-side via a config key. This remote config drives OS notification triggers (triggerOsNotificati… | |
| 40 | Remote Code Loading | high | background.js (line 1) | Every 2 hours (marketing alarm with periodInMinutes:120), the extension fetches a remotely-controlled campaign configuration JSON from AWS S3. This config dictates which domains to monitor, notification content, and t… | |
| 41 | Remote Code Loading | high | main.js (line 1) | The extension implements a 'blockchain fallback' mechanism querying Ethereum RPC nodes (Infura/MyEtherWallet) to dynamically resolve VPN proxy endpoints from a smart contract. Because blockchain data is immutable and … | |
| 42 | Remote Code Loading | high | main.js (line 1) | The extension fetches remote campaign data that includes an `html` property and `styles` object, rendering this remotely-controlled HTML directly in the extension popup UI. A compromised or malicious campaign server c… | |
| 43 | Remote Code Loading | high | assets/events_track.js (line 1) | The extension popup dynamically loads the legacy Google Analytics library (`ga.js`) from `ssl.google-analytics.com` at runtime via DOM script injection. This constitutes both tracking (GA account UA-40329910-24 collec… | |
| 44 | Remote Code Loading | high | background.js (line 1) | Every 2 hours via an alarm, the extension fetches a campaign configuration JSON from a remote AWS S3 bucket at `zenmate-extension.s3-eu-west-1.amazonaws.com/cms/`. The fetched `campaignSettings` directly controls whic… | |
| 45 | Remote Code Loading | high | assets/events_track.js (line 1) | The extension dynamically injects the Google Analytics tracking script (ga.js) into the popup page at runtime by creating a script element. This loads third-party executable code from an external domain that was not b… | |
| 46 | Remote Code Loading | high | background.js (line 1) | The extension fetches a remote JSON configuration file from an AWS S3 bucket (`zenmate-extension.s3-eu-west-1.amazonaws.com`) on each run and uses its contents to control OS notification messages, titles, button text,… | |
| 47 | Tracking | high | background.js (line 1) | The extension registers a persistent affiliate tracking ID (zm_clickid) for each user by calling the zenmate.com feedback/affiliate API, then associates it with offer IDs and transaction IDs via PUT requests. Every VP… | |
| 48 | Tracking | high | assets/events_track.js (line 1) | The extension dynamically injects the legacy Google Analytics ga.js script (account UA-40329910-24) into its own popup UI via DOM manipulation. This transmits extension usage behavior to Google's servers. A VPN extens… | |
| 49 | Unauthorized Data Collection | high | background.js (line 1) | The extension maintains persistent behavioral tracking vectors including dailyDomainVisits (per-domain visit frequency map), dailyVisits, dailyConnection counts, and alltimeMarketingCounter. These are used to time mar… | |
| 50 | Unauthorized Data Collection | high | assets/config/config.prod.json (line 1) | The production config embeds Ethereum blockchain RPC node endpoints (MyEtherWallet Ropsten testnet and an Infura project with hardcoded project ID) alongside a blockchainFallback:true flag. A VPN extension has no legi… | |
| 51 | Unauthorized Data Collection | high | background.js (line 1) | On install, the extension silently queries a third-party IP geolocation service (extreme-ip-lookup.com) and stores the user's real IP address (the 'query' field), country code, and city in local storage. This real IP … | |
| 52 | Unauthorized Data Collection | high | background.js (line 1) | The extension hooks chrome.tabs.onUpdated to intercept every tab navigation across all URLs. For each navigation it records per-domain visit counts into 'dailyDomainVisits' (keyed by domain) and uses this browsing his… | |
| 53 | Unauthorized Data Collection | high | background.js (line 1) | chrome.cookies.getAll({}) is called with no domain filter, enumerating every cookie across all sites the user is logged into. The CookiesGateway also exposes clearBrowser() which can delete history, formData, localSto… | |
| 54 | Unauthorized Data Collection | high | main.js (line 1) | The extension silently auto-creates ZenMate accounts (autocreateUser) using empty captcha and hardcoded parameters without explicit user consent, then registers the browser as a device on ZenMate's remote API. Full ac… | |
| 55 | Unauthorized Data Collection | high | background.js (line 1) | On startup the extension calls the third-party IP geolocation service `extreme-ip-lookup.com`, storing the user's real IP address (`query` field), city, and country code. This real IP is then attached to every telemet… | |
| 56 | Unauthorized Data Collection | high | background.js (line 1) | The extension hooks `chrome.tabs.onUpdated` to track every domain visited, incrementing per-domain counters in `dailyDomainVisits`. The list of monitored domains (`domainsMonitor`) is remotely controlled via a campaig… | |
| 57 | Unauthorized Data Collection | high | main.js (line 1) | The extension searches the user's complete browsing history for visits to `.cyberghostvpn.com` (a competing VPN) with no start time limit and up to 10,000 results. While the callback is currently empty, this reads ful… | |
| 58 | Unauthorized Data Collection | high | background.js (line 1) | On every new browser window creation, the extension calls the third-party IP geolocation service `extreme-ip-lookup.com` and stores the user's real IP address (the `query` field), city, and country code locally. This … | |
| 59 | Unauthorized Data Collection | high | background.js (line 1) | The extension registers a `chrome.tabs.onUpdated` listener that monitors every active tab navigation and records visited domains in `dailyDomainVisits` storage. The set of tracked domains (`domainsMonitor`) is fetched… | |
| 60 | Unauthorized Data Collection | high | assets/config/config.prod.json (line 1) | The production config contains a hardcoded API key shared across both dev and production environments, bundled in plaintext inside the extension package. The config also references Ethereum blockchain RPC nodes (MyEth… | |
| 61 | Unauthorized Data Collection | high | background.js (line 1) | `chrome.cookies.getAll({})` is called with an empty filter object, meaning it enumerates cookies from every domain in the browser — not limited to VPN-related domains. While the extension has the `cookies` permission,… | |
| 62 | Code Injection | medium | manifest.json (line 38) | The Content Security Policy allows 'unsafe-eval', which permits the execution of arbitrary strings as code. This weakens the security of the extension and is often flagged as a risk factor for code injection vulnerabi… | |
| 63 | Credential Theft | medium | background.js (line 1025) | Captures and stores credentials (email/password) from the ZenMate website in the extension background storage. While likely for auto-login, background capture of plaintext credentials before encryption is a sensitive … | |
| 64 | Credential Theft | medium | background.js (line 1) | `chrome.cookies.getAll({})` with an empty filter retrieves every cookie from every domain in the browser — far broader than VPN functionality requires. The `clearBrowser` method can then wipe cookies, form data, histo… | |
| 65 | Credential Theft | medium | background.js (line 1) | A blocking `webRequest.onAuthRequired` listener on `<all_urls>` automatically responds to any HTTP 407/401 authentication challenge with the user's VPN device token and tokenSecret. Any server that issues a proxy auth… | |
| 66 | Credential Theft | medium | main.js (line 1) | Authentication JWT tokens are appended as plaintext `?auth=` query parameters in URLs opened in new tabs to the ZenMate account portal. Tokens in query strings are exposed in browser history, server access logs, refer… | |
| 67 | Credential Theft | medium | assets/config/config.prod.json (line 5) | A shared API key is hardcoded in plaintext in the extension bundle. This key is identical across dev and prod configs, meaning any user who downloads the extension can extract it and make authenticated API calls to Ze… | |
| 68 | Network Interception | medium | background.js (line 1) | The extension registers a blocking webRequest.onAuthRequired listener on all URLs (<all_urls>), intercepting HTTP authentication challenges across every website the user visits. While nominally used for VPN proxy auth… | |
| 69 | Network Interception | medium | background.js (line 1) | The extension modifies chrome.privacy.network.webRTCIPHandlingPolicy to control WebRTC IP leak behavior. While framed as a privacy feature, the enableWebRTC() method restores it to 'default', which can re-expose the u… | |
| 70 | Network Interception | medium | assets/config/index.js (line 4) | The extension makes outbound HTTP (not HTTPS) requests to multiple external domains to check connectivity, including two non-standard domains (`thinkdifferent.us` and `airport.us`) not affiliated with any major compan… | |
| 71 | Network Interception | medium | background.js (line 1) | The `webRequestBlocking` permission combined with `onAuthRequired` listener on `<all_urls>` means the extension intercepts HTTP authentication challenges for every URL the browser navigates to. The handler injects dev… | |
| 72 | Obfuscation | medium | background.js (line 1037) | The extension uses a hardcoded AES key to encrypt user credentials received from the website before storing them in local storage. While temporary (5-minute TTL), the use of a static, hardcoded key is a weak security … | |
| 73 | Other | medium | assets/config/config.prod.json (line 4) | A shared API key ('ZMEx4hfuto83htix763jf9cz3n59f73v659f') is hardcoded in plaintext for both v1 and v2 API endpoints at zenguard.biz. Any user who extracts the extension ZIP (trivially done from the Chrome Web Store) … | |
| 74 | Other | medium | assets/config/index.js (line 99) | The extension hardcodes a list of competitor domains ('appnord.xyz') and silently closes any browser tab that navigates to those hosts. This is covert browser navigation manipulation targeting a competitor — using the… | |
| 75 | Other | medium | assets/config/config.prod.json (line 1) | The production API key `ZMEx4hfuto83htix763jf9cz3n59f73v659f` is hardcoded in the config files and embedded in the bundled `background.js`. This key is identical across dev and prod environments, providing full API ac… | |
| 76 | Remote Code Loading | medium | assets/events_track.js (line 1) | This extension page loads Google Analytics by injecting a remote script at runtime instead of shipping all executed code locally. Remote script execution inside an extension is a classic supply-chain risk and also ena… | |
| 77 | Remote Code Loading | medium | assets/events_track.js (line 1) | The popup loads a remote Google Analytics script at runtime instead of bundling code locally. Remote script execution inside an extension UI is a classic remote-code-loading and tracking pattern because the publisher … | |
| 78 | Remote Code Loading | medium | manifest.json (line 35) | The manifest combines extremely powerful browser-wide permissions with a CSP that explicitly permits remote scripts from Google Analytics and `unsafe-eval`. That combination materially increases the impact of any remo… | |
| 79 | Remote Code Loading | medium | background.js (line 1) | A marketing campaign configuration JSON is fetched from a remote AWS S3 bucket every 2 hours and applied immediately. This remote config controls which domains are monitored, what visit thresholds trigger notification… | |
| 80 | Tracking | medium | background.js (line 2209) | The extension watches tab updates, parses visited URLs, records per-domain/protocol visit counts, and feeds that data into a marketing notification engine. This is browser activity tracking used to trigger promotional… | |
| 81 | Tracking | medium | assets/events_track.js (line 1) | The extension injects Google Analytics into its privileged extension UI and reports usage to a third party. Loading a remote analytics script inside an extension is risky because it enables user activity tracking and … | |
| 82 | Tracking | medium | assets/events_track.js (line 1) | This file dynamically creates a script element to inject the legacy Google Analytics ga.js library from ssl.google-analytics.com, associating it with account UA-40329910-24. Dynamic GA injection in a browser extension… | |
| 83 | Tracking | medium | background.js (line 1) | The extension reads affiliate tracking cookies (zm_clickid, zm_offer_id, zm_transaction_id) from zenmate.com, generates persistent cross-session click tracking IDs, and fires VPN connection events tied to offer/transa… | |
| 84 | Tracking | medium | background.js (line 1) | On first install, the extension silently writes install-date cookies and base64-encoded trial start timestamps to zenmate.com, fires a 'client_install' affiliate tracking event, then forcibly opens a new browser tab t… | |
| 85 | Tracking | medium | background.js (line 1) | The extension reads and writes affiliate tracking cookies (`zm_clickid`, `zm_offer_id`, `zm_transaction_id`) on zenmate.com, creating a persistent cross-session advertising identifier. Every user event is sent to `fee… | |
| 86 | Tracking | medium | index.html (line 9) | The extension popup loads fonts and icons from `fonts.googleapis.com` CDN on every popup open, leaking the user's IP address and popup timing to Google. Combined with the inline analytics script, every popup interacti… | |
| 87 | Tracking | medium | background.js (line 1) | The extension reads affiliate tracking cookies (`zm_clickid`, `zm_offer_id`, `zm_transaction_id`) from `zenmate.com` and uses them to attribute install and connection events to an affiliate tracking API at `feedback.z… | |
| 88 | Tracking | medium | main.js (line 1630811) | When a user initiates a signup or trial flow, the extension injects a tracking cookie (`zmTrialStart`) with a base64-encoded JSON payload containing a timestamp and `zm_extension` salt before the user navigates to the… | |
| 89 | Tracking | medium | assets/events_track.js (line 1) | This file is loaded directly in the extension popup (`index.html`) and dynamically injects the Google Analytics tracking library into every popup page view. This means user interactions with the extension UI (includin… | |
| 90 | Unauthorized Data Collection | medium | background.js (line 1920) | The telemetry component collects and exfiltrates detailed user location information, including the original country code and city, to a remote Elasticsearch endpoint (https://zenmate.com/new-extension-feedback). This … | |
| 91 | Unauthorized Data Collection | medium | page_api.js (line 8) | This content script injects a page-context helper and forwards arbitrary `creds` values from the web page into the extension over `chrome.runtime.sendMessage`. Even though it is limited to ZenMate domains, it is still… | |
| 92 | Unauthorized Data Collection | medium | main.js (line 55016) | Every request to the ZenGuard API is decorated with a persistent device identifier and a device secret pulled from local storage. This is a clear server-side tracking/authentication hook and exposes a long-lived secre… | |
| 93 | Unauthorized Data Collection | medium | index.html (line 9) | The extension popup loads CSS from Google Fonts CDN (fonts.googleapis.com) on every popup open, causing outbound HTTP requests to Google servers that leak the user's IP address and timing data. This is particularly ir… | |
| 94 | Unauthorized Data Collection | medium | index.html (line 1) | The popup HTML loads CSS fonts directly from Google Fonts via two link tags, causing HTTP requests to Google's servers that include the user's IP address and a Referer header pointing to the extension. For a privacy-f… | |
| 95 | Other | low | background.js (line 1106) | Implements functionality to clear extensive browsing data, including cookies, history, and cache. This is part of the "Stealth Connection" feature which can programmatically wipe user session traces. | |
| 96 | Other | low | assets/config/index.js (line 99) | The extension maintains a hardcoded list of domains (appnord.xyz) for which it silently closes any browser tab that attempts to navigate there. This silent tab-management authority is exercised without explicit user c… | |