Is VPN safe?
VPN is medium risk. 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.
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.
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.
| Content-Type | application/json |
| Access-Control-Allow-Origin | * |
| Field | Value | Why it matters | |
|---|---|---|---|
Google OAuth access token | access_token=<redacted> | This token represents the Google sign-in access granted to the extension for the requested profile scopes. | |
Requested Google profile access | openid email profile | This lets the sign-in flow identify your Google account profile and email address to the service. |
Popup click, OAuth redirect parsing, and backend POST
onClick: function() {
p(!0), browser.runtime.sendMessage({
action: "googleOauth"
})
}function 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)
}function 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
}- 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.