Is VPN safe?
VPN sends the full URL and HTTP referrer of every page visited to api.sandvpn.com along with a persistent user identifier.
On every browser navigation, the extension captures the visited URL, the page's HTTP referrer, and a persistent random userId stored in sync storage, then transmits them to api.sandvpn.com/smartProxy. During sign-in the extension forwards the raw Google OAuth access_token to api.sandvpn.com/google before exchanging it for a service token. All browser traffic is routed through HTTP (not HTTPS) proxy servers whose credentials are fetched from api.sandvpn.com and stored in plaintext in sync storage.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Google OAuth token sent to SandVPN backend
Clicking Google sign-in starts an OAuth flow for openid, email, and profile.
After Google returns an access token, the background script posts it to api.sandvpn.com/google, which returns a SandVPN token for later API calls.
What actually happens
You click the Google sign-in button in the VPN extension.
The popup sends a googleOauth message to the background script.
The extension extracts the Google OAuth access token and posts it to SandVPN's backend.
The request goes to https://api.sandvpn.com/google immediately after the OAuth redirect is handled.
Captured request
- Content-Type
- application/json
- Access-Control-Allow-Origin
- *
Data sent in the sign-in request
- Google OAuth access tokenaccess_token=<redacted>
This token represents the Google sign-in access granted to the extension for the requested profile scopes.
- Requested Google profile accessopenid email profile
This lets the sign-in flow identify your Google account profile and email address to the service.
The code that does this
Popup click, OAuth redirect parsing, and backend POST
Popup Google sign-in click handler
main.jsonClick: function() { p(!0), browser.runtime.sendMessage({ action: "googleOauth" })}Background POST helper
background.jsfunction f(e) { return p.apply(this, arguments)}function p() { return (p = l(c().mark((function e(t) { return c().wrap((function(e) { for (;;) switch (e.prev = e.next) { case 0: return e.abrupt("return", fetch("https://api.sandvpn.com/google", { method: "POST", headers: { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" }, body: JSON.stringify(t) }).then((function(e) { if (!e.ok) { if (500 === e.status) throw new Error("Server Error"); return e.text().then((function(e) { throw e })) } return e.json() }))); case 1: case "end": return e.stop() } }), e) })))).apply(this, arguments)}Redirect parser and Google OAuth launcher
background.jsfunction x(e) { return k.apply(this, arguments)}function k() { return (k = l(c().mark((function e(t) { var r, n, o, a, s, u, l; return c().wrap((function(e) { for (;;) switch (e.prev = e.next) { case 0: if (r = t.match(/access_token=(.*?)&/i)[1], n = browser.extension.getViews({ type: "popup" }), !r) { e.next = 27; break } return e.prev = 3, o = { access_token: r }, e.next = 7, f(o); case 7: return a = e.sent, e.next = 10, w(a.token); case 10: if (null == (s = e.sent) || !s.premium) { e.next = 16; break } return e.next = 14, v(a.token); case 14: u = e.sent, browser.storage.sync.set({ proxyInfos: u }); case 16: l = i(i(i({}, a), s), {}, { isAuth: !0 }), browser.storage.sync.set({ userInfo: l }), n.length || m({ path: "user" }), e.next = 26; break; case 23: e.prev = 23, e.t0 = e.catch(3), console.log(e.t0); case 26: case 27: case 28: case "end": return e.stop() } }), e, null, [ [3, 23] ]) })))).apply(this, arguments)}function L() { return (e = browser.identity.getRedirectURL(), t = "https://accounts.google.com/o/oauth2/auth", t += "?client_id=".concat("368215438305-s6n3g9q6roovov01p03b5kgm8f248cpr.apps.googleusercontent.com"), t += "&prompt=select_account", t += "&response_type=token", t += "&redirect_uri=".concat(encodeURIComponent(e)), t += "&scope=".concat(encodeURIComponent(["openid", "email", "profile"].join(" "))), browser.identity.launchWebAuthFlow({ interactive: !0, url: t })).then(x); var e, t}External services involved in this sign-in path
- accounts.google.com
Google OAuth consent and redirect endpoint for the openid, email, and profile scopes.
- api.sandvpn.com
SandVPN backend that receives the Google OAuth access token and returns a SandVPN service token.
What it can do
Permissions this extension asks for, as declared in version 9.7.2. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.
Read and change your data on every site you visit
<all_urls>
Sign you in with your Google account
identity
See every page you navigate to, as you navigate to it
webNavigation
Read and change cookies, including the ones that keep you signed in
cookies
Clear your browsing history, cache and cookies
browsingData
Show you desktop notifications
notifications
See the address and title of every tab you have open
tabs
Change your browser's privacy and security settings
privacy
Route all of your browsing through a server of its choosing
proxy
See, disable and uninstall your other extensions, including your security ones
management
Store data in your browser
storage
Watch every request your browser makes
webRequest
Watch, block and rewrite every request your browser makes
webRequestBlocking
Act on the current tab, but only after you click the extension
activeTab
Add items to the right-click menu
contextMenus
Write to your clipboard
clipboardWrite
Schedule its own background tasks
alarms
Where it sends data
Destinations our analysis observed VPN 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.sandvpn.com
VPN sends data to api.sandvpn.com. One other extension we have analyzed sends data here.