| 1 | Privilege Escalation | critical | background.js (line 1) | The extension establishes a persistent chrome.runtime.connect() channel to a second 'CuteTab' extension whose ID is not hardcoded but is dynamically provided by the remote server (cuteTabExtensionId from the getConfig… | |
| 2 | Remote Code Loading | critical | js/background.js (line 5367) | On install/update, the extension sends a base64-encoded payload containing the extension ID, version, a persistent user ID, and timestamp to a remote server. The server response can contain an arbitrary URL which is t… | |
| 3 | Tracking | critical | background.js (line 20) | The extension generates a persistent UUID (user.id) on first install, stores it in chrome.storage, and transmits it together with the extension's own Chrome ID to the remote endpoint https://cp.cute-cursors.com/api/v2… | |
| 4 | Code Injection | high | background.js (line 1) | On first install, the extension imperatively queries ALL open browser tabs (chrome.tabs.query({})) and injects cursor-injector.js into every HTTP/HTTPS tab — the only exclusions being chrome.google.com, view-source:, … | |
| 5 | Code Injection | high | background.js (line 1) | On install, the background script calls chrome.tabs.query({}) with an empty filter to enumerate ALL currently open tabs, then programmatically injects cursor-injector.js into each using chrome.scripting.executeScript.… | |
| 6 | Code Injection | high | background.js (line 20) | On extension install, injectContentScripts() calls chrome.tabs.query({}) with no URL filter, enumerating ALL currently open browser tabs, then programmatically injects cursor-injector.js into each via chrome.scripting… | |
| 7 | Code Injection | high | js/background.js (line 5405) | On install, the extension iterates over ALL open tabs and programmatically injects content scripts into every matching tab using chrome.tabs.executeScript. This aggressive injection into pre-existing tabs goes beyond … | |
| 8 | Privilege Escalation | high | background.js (line 1) | The extension uses the optional management permission to silently connect to a second extension whose ID is supplied by the remote server (cuteTabExtensionId). chrome.management.get verifies the target is installed an… | |
| 9 | Remote Code Loading | high | js/background.js (line 5354) | The background script establishes a remote action endpoint at cursorstore.com/api/action/index.php and maintains a queue of actions to process. The server can respond with arbitrary URLs that the extension will open v… | |
| 10 | Tracking | high | background.js (line 1) | The getConfig() function transmits the extension's chrome.runtime.id (unique per user installation) and a locally-generated persistent user.id to the developer's remote server at https://cp.cute-cursors.com/api/v2/con… | |
| 11 | Tracking | high | cursor-injector.js (line 1) | The Sentry SDK in cursor-injector.js patches window.history.pushState and replaceState, and listens to popstate, capturing every in-page navigation as a breadcrumb with {from: previousUrl, to: newUrl}. This runs on ev… | |
| 12 | Tracking | high | js/background.js (line 5367) | On every install/update event, the extension sends a base64-encoded tracking payload (extension ID, version, generated user ID, timestamp) to cursorstore.com. The server response can contain a URL which is automatical… | |
| 13 | Unauthorized Data Collection | high | background.js (line 1) | On first run, the extension generates a persistent tracking ID via Math.random() + Date.now() (exported as module function 'b', called as Object(o.b)()), stores it in extension storage under user.id, and sends it to t… | |
| 14 | Unauthorized Data Collection | high | background.js (line 1) | The extension subscribes to chrome.management.onInstalled for ALL extensions, not just its own companion. Every time the user installs any new extension, getConfig() is called, which pings the remote server with the u… | |
| 15 | Unauthorized Data Collection | high | background.js (line 1) | On every startup the extension makes an authenticated GET request to https://cp.cute-cursors.com/api/v2/config/{extensionId}/{userId}, embedding the extension's own ID and a persistent per-user tracking ID in the URL … | |
| 16 | Unauthorized Data Collection | high | cursor-injector.js (line 1) | cursor-injector.js — injected into every page on all URLs — includes the full Sentry SDK which patches XMLHttpRequest.prototype.open and send with Proxy objects. These patches capture every XHR request's URL, HTTP met… | |
| 17 | Unauthorized Data Collection | high | cursor-injector.js (line 20) | The full Sentry SDK is bundled inside cursor-injector.js, the content script that runs on every page the user visits across all URLs. It is initialised with a DSN pointing to a self-hosted Sentry instance (solomon.cut… | |
| 18 | Unauthorized Data Collection | high | background.js (line 20) | The extension registers listeners on chrome.management.onEnabled, onInstalled, and onDisabled, which fire for every extension the user installs, enables, or disables — not just the extension's own companion. Criticall… | |
| 19 | Code Injection | medium | js/background.js (line 5405) | On install, the extension programmatically injects content.js into ALL currently open tabs that match http/https URLs. This goes beyond the declared content_scripts by retroactively injecting into tabs that were open … | |
| 20 | Obfuscation | medium | background.js (line 1) | Each of the five JavaScript files contains a nearly identical self-contained webpack bundle (1.27–2.15 MB each) embedding Vue.js 2.6.12, Vuex, Vue Router, axios, the Node.js buffer polyfill, and dozens of other librar… | |
| 21 | Obfuscation | medium | background.js (line 1) | All five JS files are fully minified into single lines totaling ~8.5MB — 85x larger than a typical cursor extension. The entire business logic is bundled with Sentry SDK, Axios, Vue.js, and Vuex into opaque single-lin… | |
| 22 | Other | medium | js/background.js (line 5427) | The background script listens for 'open_link' messages from content scripts and navigates the current active tab to any arbitrary URL provided in the message. Since content scripts run on all pages, a compromised or m… | |
| 23 | Phishing | medium | js/background.js (line 5429) | The background script handles 'open_link' messages by navigating the current active tab to any URL sent via message. Combined with the content scripts running on all pages, any compromised or malicious content script … | |
| 24 | Privilege Escalation | medium | background.js (line 1) | The background service worker exposes an unbounded chrome.runtime.onMessage listener that accepts messages from any content script or page in the extension. The 'CUTETAB_CONNECT' action triggers getConfig() (which cal… | |
| 25 | Privilege Escalation | medium | background.js (line 1) | The management permission (declared optional but actively requested) is used to monitor install, enable, and disable events for a remotely-specified extension ID. This creates a surveillance loop: any extension the se… | |
| 26 | Privilege Escalation | medium | background.js (line 20) | The remote configuration endpoint (cp.cute-cursors.com/api/v2/config) returns a cuteTabExtensionId field that dictates which Chrome extension to establish a persistent connection to via chrome.runtime.connect(). The s… | |
| 27 | Privilege Escalation | medium | manifest.json (line 32) | A content script named 'app-site-controller.js' is injected at document_start on the publisher's own domain (cute-cursors.com) and localhost:4200. This is a well-known pattern where the publisher's website can postMes… | |
| 28 | Privilege Escalation | medium | manifest.json (line 15) | The extension requests the `management` permission as an optional permission. For a cursor-customization extension, the ability to enumerate, enable, disable, or uninstall other installed extensions is not justified b… | |
| 29 | Privilege Escalation | medium | manifest.json (line 32) | A dedicated content script (`app-site-controller.js`) runs at `document_start` on the vendor's own domain (`cute-cursors.com`) and a local dev URL. This pattern is commonly used to bridge the extension's privileged AP… | |
| 30 | Privilege Escalation | medium | manifest.json (line 18) | The extension injects content.js into every single webpage the user visits via <all_urls> match pattern, combined with broad host permissions (http://*/* and https://*/*) and tabs permission. For a cursor customizatio… | |
| 31 | Privilege Escalation | medium | manifest.json (line 18) | Content script injects into every webpage the user visits. While the content script itself only modifies cursor styles, this broad injection scope combined with the background page's remote command capability means th… | |
| 32 | Tracking | medium | background.js (line 1) | On first run the extension generates a persistent pseudo-random user ID (Math.random + Date.now entropy, random case mixing) and stores it permanently in chrome.storage.local. This ID is included in every startup requ… | |
| 33 | Tracking | medium | js/background.js (line 5386) | Sets an uninstall URL that transmits user tracking data (user ID, extension ID, version, timestamp) to the developer's server when the extension is removed. This tracks users even during uninstallation and the payload… | |
| 34 | Tracking | medium | js/background.js (line 5354) | The extension phones home to cursorstore.com/api/action/index.php on every install and update event. This establishes a tracking/C2-like channel with a remote server that can respond with arbitrary URLs to open (see n… | |
| 35 | Tracking | medium | js/background.js (line 5386) | Sets an uninstall URL with base64-encoded user tracking data (persistent user ID, extension ID, version, timestamp). This tracks individual users across uninstall events, enabling persistent user profiling. | |
| 36 | Unauthorized Data Collection | medium | background.js (line 1) | Sentry is initialized in the background script with skipBrowserExtensionCheck:true — explicitly bypassing Sentry's own safeguard that blocks browser extensions from sending data to prevent privacy leakage. The DSN poi… | |
| 37 | Unauthorized Data Collection | medium | manifest.json (line 15) | The extension requests the optional 'management' permission in addition to scripting + tabs + <all_urls>. For a cursor-customization tool there is no legitimate need to enumerate or disable other installed extensions;… | |
| 38 | Unauthorized Data Collection | medium | js/background.js (line 5469) | Generates and persists a unique user identifier (via random string + timestamp) in chrome.storage.local on first load. This ID is sent with every server communication, enabling persistent cross-session user tracking w… | |
| 39 | Unauthorized Data Collection | medium | js/background.js (line 5469) | Generates and persists a unique user ID on first load, stored in chrome.storage.local. This ID is then sent with every phone-home request, enabling cross-session user tracking without consent. | |
| 40 | Other | low | manifest.json (line 38) | The CSP whitelists ssl.google-analytics.com for script execution, but there is no Google Analytics code in the extension bundle. This unnecessarily relaxes the content security policy and could be used as a vector for… | |
| 41 | Other | low | manifest.json (line 38) | The CSP allows scripts from Google Analytics domain, which while commonly used for analytics, expands the trusted script origin surface beyond 'self'. If ssl.google-analytics.com were compromised or the extension abus… | |