Is Free VPN for Chrome: Secure VPN Proxy in One Click safe?
Free VPN is high risk. Clicking Connect on the Free VPN profile builds a PAC config from hardcoded hosts via Chrome's proxy settings. Non-localhost traffic routes through HTTPS hosts on port 443, exposing your IP, destination host, timing, and HTTP content.…
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Activated VPN routes browsing through proxy host pools
Clicking Connect on the Free VPN profile builds a PAC config from hardcoded hosts via Chrome's proxy settings.
Non-localhost traffic routes through HTTPS hosts on port 443, exposing your IP, destination host, timing, and HTTP content.
- Severity
- Critical unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You press the extension's connect button for the Free VPN profile.
The popup maps the default profile to a background message with profileId set to free.
The extension applies a browser-wide proxy rule from hardcoded host pools.
The rule excludes only localhost and otherwise returns HTTPS proxy hosts on port 443.
- Destination siteexample.internal:443 (illustrative)
Lets the proxy endpoint see which site your browser is trying to reach.
- Browsing sequencemail.example.com, docs.example.com, crm.example.com (illustrative)
Lets the proxy endpoint build a timeline of sites requested while the VPN profile is connected.
- Your network address198.51.100.24 (illustrative)
Identifies the network location that is making the proxied browser requests.
- Unencrypted HTTP request detailsGET http://example.test/account?view=billing (illustrative)
For plain HTTP pages, the proxy route can receive the requested URL path and headers your browser sends.
The shipped background code builds and applies the PAC proxy rule
Hardcoded proxy host pools
js/background.jsconst v = ["efr-marktplatz.club", "voteshirleysew.club", "carolinafreigh.fun", "purposebydesig.club", "mmgr.club", "webdrone.club", "ictabernacle.info", "jewelscollecti.icu", "berniesbodybla.fun", "fullmanfirm.icu", "miamigoskennel.fun", "goedkoopgeluid.icu", "tzoa.fun", "kimberlymilano.icu", "crosscards.site", "jgwynphotoarts.pro", "indextraub.online", "purecambogiasl.live", "zebpay.site", "southwestcoast.pro"], S = ["www.mohegansuncasi.online", "www.hullwiper.live", "www.anokhiiwade.info", "www.tecnopay.online", "www.i-mopachores.live", "www.wpfaststart.info", "www.art1p.pro", "www.roccosiffredi.online", "www.saifrizvi.live", "www.rmtonthebeach.info", "www.donelikeyester.space", "www.yoakumselfstor.website", "www.passportsusa.space", "www.uatgc.website", "www.ahikeleher.site", "www.helpinghandsof.space", "www.onedaijo.website", "www.templarknights.site", "www.aoeah.space", "www.stratfordrc.website", "www.all4women.space", "www.keukataxi.website", "www.carimflex.site", "www.peacefulbodies.xyz", "www.vogelsenmeer.xyz", "www.9ts3tpia.world", "www.ruimte-18.xyz", "www.nogielectric.world", "www.bodrumexpresso.xyz", "www.jaqandlelights.world"];PAC script generator
js/background.jsfunction O(e) { return { value: { mode: "pac_script", pacScript: { data: `function FindProxyForURL(url, host) {if (host === 'localhost') { return 'SYSTEM;'; }return '${e.map(o=>`HTTPS ${o}:443`).join("; ")}';}`, mandatory: !0 } } }}Proxy settings applied
js/background.jsasync function P(e) { if (e < 0 || e >= c.length) return console.log(`[PROXY][cycle ${n}] No more attempts available (index=${e}).`), !1; e === l && i < l && console.log(`[PROXY][cycle ${n}] Switching from pool A to pool B.`); const t = m(e); return i = e, console.log(`[PROXY][cycle ${n}] Applying pool ${t.pool} round ${t.round}: ${t.hosts.join(", ")}`), await chrome.proxy.settings.set(O(t.hosts)), !0}Free profile connection path
js/background.jsasync function b() { n += 1, d = Date.now(); const e = g(v), t = g(S); return c = [...e, ...t], i = -1, console.log(`[PROXY][cycle ${n}] Generated A groups:`, e), console.log(`[PROXY][cycle ${n}] Generated B groups:`, t), u = null, await P(0), await w(!0, "free"), await y(!0), { success: !0 }}Connect message handler
js/background.jsconst T = new Set(["connect", "disconnect", "getStatus", "rotateProxy"]);chrome.runtime.onMessage.addListener((e, t, o) => T.has(e.action) ? ((async () => { try { switch (e.action) { case "connect": { const r = e.profileId ?? "free"; r === "free" ? await b() : await x(r), o({ success: !0, status: await f() }); break } case "disconnect": { await p(), o({ success: !0, status: await f() }); break } case "getStatus": { o({ success: !0, status: await f(), cycleInfo: h() }); break } case "rotateProxy": { const r = await C(); o({ success: !0, rotated: r, cycleInfo: h() }); break } } } catch (r) { console.error("[ProxyManager] Error:", r), o({ success: !1, error: r.message }) }})(), !0) : !1);The popup button sends the connect message that activates the background path
Popup connect handler
assets/index-BKA750bI.jsconst d = s === "default" ? "free" : s;try { chrome.runtime.sendMessage({ action: "connect", profileId: d }, p => { i(!1), !chrome.runtime.lastError && p != null && p.success && r(!0) })} catch { i(!1)}- efr-marktplatz.club
- voteshirleysew.club
- carolinafreigh.fun
- purposebydesig.club
- mmgr.club
- webdrone.club
- ictabernacle.info
- jewelscollecti.icu
- berniesbodybla.fun
- fullmanfirm.icu
Candidate HTTPS proxy host in pool A.
- www.mohegansuncasi.online
- www.hullwiper.live
- www.anokhiiwade.info
- www.tecnopay.online
- www.i-mopachores.live
- www.wpfaststart.info
- www.art1p.pro
- www.roccosiffredi.online
- www.saifrizvi.live
- www.rmtonthebeach.info
Candidate HTTPS proxy host in pool B.
All browser traffic routed through 50 anonymous hardcoded proxy hosts
In free mode, Connect routes every request through one of 50 hardcoded hostnames (e.g. efr-marktplatz.club, voteshirleysew.club, mohegansuncasi.online) with no verifiable link to the operator.
The PAC script picks three at random.
- Severity
- Critical unwanted
- Type
- Unexpected
- CWE
- CWE-506
- Source
- Dynamic sandbox
You click Connect in the extension popup without selecting a named proxy profile (free mode).
The extension immediately applies a mandatory PAC script routing all your browser traffic through three randomly-chosen hosts from a hardcoded pool of 50 unverified domains.
The proxy setting is marked mandatory:true, preventing you or any other extension from overriding it.
PAC script generation and proxy application
// Pool A: 20 hosts (TLDs: .club .fun .info .icu .site .pro .online .live)const poolA = [ "efr-marktplatz.club", "voteshirleysew.club", "carolinafreigh.fun", "purposebydesig.club", "mmgr.club", "webdrone.club", "ictabernacle.info", "jewelscollecti.icu", "berniesbodybla.fun", "fullmanfirm.icu", "miamigoskennel.fun", "goedkoopgeluid.icu", "tzoa.fun", "kimberlymilano.icu", "crosscards.site", "jgwynphotoarts.pro", "indextraub.online", "purecambogiasl.live", "zebpay.site", "southwestcoast.pro"];// Pool B: 30 hosts (TLDs: .online .live .info .pro .space .website .site .xyz .world)const poolB = [ "www.mohegansuncasi.online", "www.hullwiper.live", "www.anokhiiwade.info", // ... 27 more ... "www.jaqandlelights.world"];// On free-mode Connect:function b() { const groupsA = shuffle(poolA).slice(0, 9); // 3 groups of 3 const groupsB = shuffle(poolB).slice(0, 9); // 3 groups of 3 rotationQueue = [...groupsA, ...groupsB]; // up to 6 rounds applyProxy(rotationQueue[0]); // immediate activation}// PAC script builder — mandatory:true locks the proxy for the sessionfunction buildPAC(hosts) { return { value: { mode: "pac_script", pacScript: { data: `function FindProxyForURL(url, host) { if (host === 'localhost') { return 'SYSTEM;'; } return '${hosts.map(h => `HTTPS ${h}:443`).join("; ")}'; // e.g. HTTPS efr-marktplatz.club:443; HTTPS crosscards.site:443; HTTPS southwestcoast.pro:443}`, mandatory: true // user cannot override this proxy } } };}- efr-marktplatz.club
- voteshirleysew.club
- carolinafreigh.fun
- purposebydesig.club
- mmgr.club
- webdrone.club
- ictabernacle.info
- jewelscollecti.icu
- berniesbodybla.fun
- fullmanfirm.icu
Pool A proxy host, all browser traffic tunneled at :443; no disclosed operator
- www.mohegansuncasi.online
- www.hullwiper.live
- www.anokhiiwade.info
- www.tecnopay.online
- www.i-mopachores.live
- www.wpfaststart.info
- www.art1p.pro
- www.roccosiffredi.online
- www.saifrizvi.live
- www.rmtonthebeach.info
Pool B proxy host, all browser traffic tunneled at :443; no disclosed operator
Reproduces the proxy pool shuffle and PAC script generation locally, no browser required. Outputs the PAC script string and pool assignments that would be applied on Connect.
- Node.js 18+
// Reproduce the proxy pool shuffle and PAC assignment from background.js// Run with: node reproduce-proxy-pool.jsconst poolA = [ "efr-marktplatz.club", "voteshirleysew.club", "carolinafreigh.fun", "purposebydesig.club", "mmgr.club", "webdrone.club", "ictabernacle.info", "jewelscollecti.icu", "berniesbodybla.fun", "fullmanfirm.icu", "miamigoskennel.fun", "goedkoopgeluid.icu", "tzoa.fun", "kimberlymilano.icu", "crosscards.site", "jgwynphotoarts.pro", "indextraub.online", "purecambogiasl.live", "zebpay.site", "southwestcoast.pro"];const poolB = [ "www.mohegansuncasi.online", "www.hullwiper.live", "www.anokhiiwade.info", "www.tecnopay.online", "www.i-mopachores.live", "www.wpfaststart.info", "www.art1p.pro", "www.roccosiffredi.online", "www.saifrizvi.live", "www.rmtonthebeach.info", "www.donelikeyester.space", "www.yoakumselfstor.website", "www.passportsusa.space", "www.uatgc.website", "www.ahikeleher.site", "www.helpinghandsof.space", "www.onedaijo.website", "www.templarknights.site", "www.aoeah.space", "www.stratfordrc.website", "www.all4women.space", "www.keukataxi.website", "www.carimflex.site", "www.peacefulbodies.xyz", "www.vogelsenmeer.xyz", "www.9ts3tpia.world", "www.ruimte-18.xyz", "www.nogielectric.world", "www.bodrumexpresso.xyz", "www.jaqandlelights.world"];// Fisher-Yates shuffle (mirrors function k() in background.js)function shuffle(arr) { const t = [...arr]; for (let i = t.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [t[i], t[j]] = [t[j], t[i]]; } return t;}// Slice into groups of 3, take 3 groups (mirrors function g())function makeGroups(pool, groupSize = 3, numGroups = 3) { const sliced = shuffle(pool).slice(0, groupSize * numGroups); const groups = []; for (let i = 0; i < sliced.length; i += groupSize) { groups.push(sliced.slice(i, i + groupSize)); } return groups;}// Build PAC script (mirrors function O() in background.js)function buildPAC(hosts) { return `function FindProxyForURL(url, host) {if (host === 'localhost') { return 'SYSTEM;'; }return '${hosts.map(h => `HTTPS ${h}:443`).join("; ")}';}` ;}const groupsA = makeGroups(poolA); // 3 groups from pool Aconst groupsB = makeGroups(poolB); // 3 groups from pool Bconst rotationQueue = [...groupsA, ...groupsB];console.log(`Total pool hosts: ${poolA.length + poolB.length}`);console.log(`Rotation rounds: ${rotationQueue.length}`);console.log('');rotationQueue.forEach((hosts, idx) => { const pool = idx < 3 ? 'A' : 'B'; const round = idx < 3 ? idx + 1 : idx - 2; console.log(`Round ${idx + 1} (Pool ${pool}, group ${round}):`); console.log(' Hosts:', hosts.join(', ')); console.log(' PAC:', buildPAC(hosts)); console.log('');});console.log('Active PAC script on Connect (round 1):');console.log(buildPAC(rotationQueue[0]));console.log('mandatory: true — browser cannot override this proxy setting.');- 1Install Node.js 18+.
- 2Save as reproduce-proxy-pool.js.
- 3Run: node reproduce-proxy-pool.js.
- 4Observe the printed pool assignments and PAC script; these match what the extension applies on Connect in free mode.
Chrome safety infrastructure blocked via declarativeNetRequest rules
The extension ships static rules blocking Chrome's own update and security servers.
Rule 1 blocks clients2.google.com (updates, CRLSet, Safe Browsing).
Rule 2 blocks googleapis.com and crash.google.com.
Both activate on install.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You install the extension.
No further interaction is required for the blocking rules to take effect.
The extension's declarativeNetRequest rules activate and block Chrome's requests to its own update and security servers.
Chrome can no longer contact clients2.google.com/service/update2/crx for extension integrity checks, CRLSet revocation data, or Safe Browsing lookups, and cannot reach googleapis.com or crash.google.com.
rules.json, the two blocking rules
Rule 1 decoded — regex matches the Chrome extension update URL
rules.json rule 1// /^https?:\/\/clients[0-9]+\.google\.com\/.*/.test(// 'https://clients2.google.com/service/update2/crx'// ) === true//// Chrome uses clients2.google.com/service/update2/crx for:// - Extension update checks// - CRLSet certificate revocation list downloads// - Safe Browsing data fetches// Rule blocks ALL 13 resource types, so no request type can bypass it.- clients2.google.com
Chrome extension update server (service/update2/crx), CRLSet revocation list distribution, and Safe Browsing API lookups. Blocked by rule 1.
- googleapis.com
Google API gateway used by Chrome for token validation and Sign-In. Blocked by rule 2.
- crash.google.com
Chrome crash reporting endpoint. Blocking suppresses browser crash telemetry that could surface extension-related instability. Blocked by rule 2.
On every browser startup
The declarativeNetRequest ruleset is enabled in the manifest and applies from the moment the extension is installed. It does not require a browser restart or user action to activate.
Tests whether Chrome's extension update endpoint is reachable. A fetch failure or ERR_BLOCKED_BY_EXTENSION response indicates the blocking rule is active.
- Chrome browser with the extension installed
// Run in DevTools console while the extension is installed.// Open DevTools on any page (F12), paste into the Console tab.async function checkChromeUpdateEndpoint() { const url = 'https://clients2.google.com/service/update2/crx?response=updatecheck&x=id%3Dghbmnnjooekpmoecnnnilnnbdlolhkhi%26uc'; try { const resp = await fetch(url, { mode: 'no-cors' }); console.log('REACHABLE: Chrome update server responded (type=' + resp.type + ')'); } catch (e) { console.error('BLOCKED: Chrome update server unreachable —', e.message); console.error('This is consistent with declarativeNetRequest rule ID 1 being active.'); }}checkChromeUpdateEndpoint();- 1Open any Chrome tab.
- 2Press F12 to open DevTools.
- 3Paste the script into the Console and press Enter.
- 4BLOCKED output confirms the rule is active; REACHABLE means it is not.