Is CG No Login Master - ChatGPT无法登陆特殊工具 safe?
CG No Login Master runs its popup script on every website visited, sending the page's origin and the user's IP to its vendor's server.
The extension's popup.js file is also registered as a content script matching all URLs, so an IP-lookup request it makes fires automatically whenever any page loads, not just when the popup is opened. This unencrypted request carries the default Referer header, which reveals the site being visited, to the vendor's API server. This happens regardless of whether the user has ever interacted with the extension or turned on its proxy feature.
Who publishes itletsmain - 8 other listings from the same operator, none carrying a finding
letsmain - 8 other listings from the same operator, none carrying a finding
What this publisher told the store about itself, and the other listings that told it the same thing.
Same store account
8 other listings published from this account, 713 users between them, none of them carrying a finding.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Popup script also runs as a content script on every site and leaks your IP
Code analysis shows the popup script also runs as a content script on every website.
Each page load calls the vendor's IP-lookup API, so the page's Referer header discloses the visited site to api.lm.234268.xyz over plain HTTP.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Static analysis
You open any website with the extension installed.
No popup click or proxy connection is required.
The extension's popup script, also registered as a content script for every site, sends your IP address and the visited site's origin to the vendor's API.
The request fires within seconds of the page loading and repeats on every new site you visit.
manifest.json registers the popup controller as a content script for every page
Deobfuscated manifest.json (content_scripts registration)
manifest.json{ "host_permissions": ["<all_urls>"], "permissions": ["cookies", "storage", "proxy", "declarativeNetRequest"], "background": { "service_worker": "background.js" }, "content_scripts": [{ "matches": ["<all_urls>"], "js": ["js/popup.js"] }]}Deobfuscated js/popup.js (config callback and getClientIP)
js/popup.js:80-127function setApiUrl() { if (configData.data.api.url) { apiUrl = configData.data.api.url; }}async function getClientIP() { const response = await fetch(apiUrl + '/services/opens/ips/format/json'); const data = await response.json(); clientIP = data.data.ip; if (isDebug == 'true') { console.log('Background clientIP->' + clientIP); } return clientIP;}chrome.storage.local.get(['config'], function(result) { configStr = result.config; configData = JSON.parse(configStr || null); chrome.storage.local.get(['platform'], function(result) { platform = result.platform; var lastVersion = configData['data']['base']['version'][platform]; if(version !== lastVersion) { var versionTips = chrome.i18n.getMessage('version_tips'); versionTips = versionTips.replace('{VERSION}', lastVersion); showAlert(versionTips, 15000); DelayVisit(configData['data']['base']['product_url'], 2000); } }); setApiUrl(); clientIP = getClientIP(); domain = configData.data.base.root_url; proxyUrls = configData['data']['base']['match']; $(function() { startUsageNode(); // jQuery-dependent UI wiring starts here; $ is not defined in the // content-script world, so this callback throws immediately below // -- but getClientIP() above has already fired. ... })});- Site you just visitedhttps://www.example.com/
Tells the vendor which website you opened, on every page load, whether or not you ever use the extension.
- Your public IP address203.0.113.42 (illustrative)
Ties this specific install, and the site above, to your network's public IP address.
- Request timingGET fired 5-10 seconds after each navigation
Shows the request fires automatically after every page load, not only when you open the extension popup.
- api.lm.234268.xyz
Receives your IP address and the origin of the page you just visited, over plain HTTP (not HTTPS), on every navigation.
Sends the same unauthenticated GET the extension's content script issues on every navigation, showing the plaintext request and the IP address it returns.
- curl
#!/bin/sh# Reproduces the exact unauthenticated GET that the extension's# mis-scoped content script (js/popup.js) fires on every page load,# on every website, once the service worker has cached a "config"# object in chrome.storage.local (normally within seconds of install).## No extension installation is required to run this: it demonstrates# the request/response shape and the fact that it travels in cleartext.TARGET_URL="http://api.lm.234268.xyz/v1/services/opens/ips/format/json"VISITED_SITE="https://www.example.com/"curl -sv \ -H "Referer: ${VISITED_SITE}" \ "${TARGET_URL}"- 1Run `sh referer-leak-repro.sh` from any shell with internet access.
- 2Note the Referer header travels in cleartext over HTTP.
- 3Inspect the JSON response body containing your public IP address.
Static analysis finding. This behaviour was identified by reading the shipped extension code and has not yet been reproduced in a live run. The trigger conditions and the exact data sent are read from the code, not from an observed capture.
Where it sends data
Destinations our analysis observed CG No Login Master - ChatGPT无法登陆特殊工具 contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.
- api.lm.234268.xyz
CG No Login Master - ChatGPT无法登陆特殊工具 sends data to api.lm.234268.xyz. 3 other extensions we have analyzed send data here.