Is My IP Hider VPN safe?
My IP Hider VPN is high risk. At sign-in, My IP Hider VPN checks if its cached location record is stale. If so, it POSTs to my-safe-net.com with the geo operation and saves country code, name, city, server, and cache time to local storage. DA confirmed this path.…
Who publishes itProxyListPro.com - no other listings under this identity, 1 shared hostname
ProxyListPro.com - no other listings under this identity, 1 shared hostname
What this publisher told the store about itself, and the other listings that told it the same thing.
Shared hosts - 1 hostname
Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Location lookup after VPN login
At sign-in, My IP Hider VPN checks if its cached location record is stale.
If so, it POSTs to my-safe-net.com with the geo operation and saves country code, name, city, server, and cache time to local storage.
DA confirmed this path.
You sign in through the extension popup.
The extension asks its service for location information when its cached record is older than ten minutes.
The response is used to display a country or city label and is also saved in local extension storage.
| Content-type | application/x-www-form-urlencoded |
| Field | Value | Why it matters | |
|---|---|---|---|
Geo operation | op=geo | This tells the service that the extension is requesting a location lookup rather than another account action. | |
Country code | US | This records the country associated with your network location. | |
Country name | United States | This records a human-readable country associated with your network location. | |
City | New York | This can narrow the location estimate from country level to a city-level label. | |
Server value | us-newyork-01.my-safe-net.com | This links the lookup result to a service-side server value used by the extension. | |
Cache time | 1720795678 | This lets the extension decide when to request a fresh location record again. |
The extension keeps the last returned location record on the device so it can reuse it until the cache expires.
chrome.storage.local key v1_user_geo_info{
"city": "New York",
"code": "US",
"server": "us-newyork-01.my-safe-net.com",
"country": "United States",
"cacheTime": 1720795678
}Login success leads to a geo lookup and local storage write
Popup.buttons.auth.login.click(function() {
Popup.HideMessage();
Popup.ShowAnimation(function() {
Popup.Emit({
message: 'AuthenticateBackground',
content: {
email: Popup.inputs.auth.email.val(),
pass: Popup.inputs.auth.password.val()
}
});
})
})Listen({
message: 'AuthenticateBackground',
callback: function (message) {
var GeoInformatoinSuccess = function() {
var userGeoInfo = Preferences.userGeoInfo;
Emit({
message: 'GeoInformatoinContentScript',
content: {'location': (userGeoInfo.city) ? userGeoInfo.country+', '+userGeoInfo.city : userGeoInfo.country}
});
var profile = Preferences.profile;
Emit({
message: 'AuthenticateContentScript',
content: {'valid': profile.valid, 'total': profile.total}
});
}
var AuthenticateSuccess = function() {
// if cached userGeoInfo did not expire then use cached one
var now = Math.floor((new Date().getTime()) / 1000);
if (now - Preferences.userGeoInfo.cacheTime < Preferences.USER_GEO_INFO_CACHE_EXPIRE) {
GeoInformatoinSuccess();
return;
}
// stored userGeoInfo expired, request new one from server
ServerAPI.GeoInformatoin(
function(code, country, city, server) {
Preferences.userGeoInfo.code = code;
Preferences.userGeoInfo.country = country;
Preferences.userGeoInfo.city = city;
Preferences.userGeoInfo.server = server;
Preferences.userGeoInfo.cacheTime = Math.floor((new Date().getTime()) / 1000);
Preferences.SavePreferences(function() {
GeoInformatoinSuccess();
})
},
function(code, message) {
var profile = Preferences.profile;
Emit({
message: 'GeoInformatoinContentScript',
content: {'location': message}
});
Emit({
message: 'AuthenticateContentScript',
content: {'valid': profile.valid, 'total': profile.total}
});
}
)
}
var now = Math.floor((new Date().getTime()) / 1000);
if (now - Preferences.profile.cacheTime < Preferences.PROFILE_CACHE_TIME) {
AuthenticateSuccess();
return;
}
RestoreProxy();
ServerAPI.Authenticate(
message.email,
message.pass,
function(valid, total, invoice) {
Preferences.profile.email = message.email;
Preferences.profile.pass = message.pass;
Preferences.profile.valid = valid;
Preferences.profile.total = total;
// if invoice is different from what we already reported
if (invoice != '' && Preferences.profile.invoice != invoice) {
chrome.tabs.create({'url': chrome.i18n.getMessage('url_thanks')+invoice});
Preferences.profile.invoice = invoice;
}
Preferences.profile.cacheTime = (valid < 0) ? 0 : Math.floor((new Date().getTime()) / 1000);
Preferences.SavePreferences(function() {
AuthenticateSuccess();
})
},
function(code, message) {
Emit({
message: 'AuthenticateContentScript',
content: {'code': code, 'message': message}
});
}
)
}
})GeoInformatoin: function(success, fail) {
if (this.debugMode) console.log('Identifying GEO information for user (SendMessage.GeoInformatoin)');
this.Request({
url: this.serviceUrl,
content: {
'op': 'geo'
},
onComplete: this.Callback(function(response) {
if (this.debugMode) console.log('Identifying GEO information for user result "' + response.text + '" (ServerAPI.Authenticate)');
response = response.text;
if (response.substring(0, 2) == 'OK') {
response = response.split(':');
success(response[1], response[2], response[3], response[4]);
} else {
response = this.ExtractMessage('GeoInformatoin', response);
fail(response.code, response.message);
}
}, this)
});
}Request: function(options) {
// decorator: compatibility with Firefox/Chrome
options.content.source = get('app_short_name');
var postData = new Array();
for (var key in options.content)
postData.push(encodeURIComponent(key)+'='+encodeURIComponent(options.content[key]));
var request = new Request(options.url, {
method: 'POST',
body: postData.join('&'),
headers: {'Content-type': 'application/x-www-form-urlencoded'},
requstIndex: ++this.requstIndex
});
var _this = this;
fetch(request)
.then(function(response) {
if (response.ok)
return response.text();
})
.then(function(responseText) {
if (_this.debugMode) console.log('Reply for request #'+request.requstIndex+', last request #'+_this.requstIndex);
if (request.requstIndex == _this.requstIndex)
try { var json = JSON.parse(responseText)} catch(err) { json = null };
options.onComplete({
text: responseText,
json: json,
statusText: responseText
});
});
}- my-safe-net.com
Receives the extension's geo lookup POST and returns country, city, and server fields for My IP Hider VPN.
What it can do
Permissions this extension asks for, as declared in version 12.1.1. 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
*://*/*
Route all of your browsing through a server of its choosing
proxy
Store data in your browser
storage
Watch every request your browser makes
webRequest
Block and redirect the requests your browser makes
declarativeNetRequest
See, disable and uninstall your other extensions, including your security ones
management
Run its own code inside the pages you visit
scripting