Is My IP Hider VPN safe?

High risk

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.…

ProxyListPro.comv12.1.1Chrome Web Store
75Risk
Who publishes it

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.

Publisher
ProxyListPro.com

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.

my-safe-net.com
Also called by 1 other listing: My IP Hider VPN

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

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.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You sign in through the extension popup.

The extension did this

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.

02EvidenceNETWORK CAPTURE
Captured request
POSThttps://my-safe-net.com/misc/proxylistpro/action
Headers
Content-typeapplication/x-www-form-urlencoded
03EvidenceFIELD TABLE
Fields involved in the geo lookup and local cache
FieldValueWhy it matters
Geo operation
op=geoThis tells the service that the extension is requesting a location lookup rather than another account action.
Country code
USThis records the country associated with your network location.
Country name
United StatesThis records a human-readable country associated with your network location.
City
New YorkThis can narrow the location estimate from country level to a city-level label.
Server value
us-newyork-01.my-safe-net.comThis links the lookup result to a service-side server value used by the extension.
Cache time
1720795678This lets the extension decide when to request a fresh location record again.
04EvidenceSTORAGE DUMP
What's stored on your device

The extension keeps the last returned location record on the device so it can reuse it until the cache expires.

Locationchrome.storage.local key v1_user_geo_info
Contents (JSON)
{
  "city": "New York",
  "code": "US",
  "server": "us-newyork-01.my-safe-net.com",
  "country": "United States",
  "cacheTime": 1720795678
}
05EvidenceCODE COMPARE
The code that does this

Login success leads to a geo lookup and local storage write

What it actually does
Popup login button emits the background authentication messagedeobfuscated/data/popup/popup.js
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()
      }
    });
  })
})
Background authentication handler requests and stores geo informationdeobfuscated/index.js
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}
        });
      }
    )
  }
})
Geo request operationdeobfuscated/lib/ServerAPI.js
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)
  });
}
Shared POST helper used by the geo requestdeobfuscated/lib/ServerAPI.js
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
        });          
    });    
}
06EvidenceTHIRD PARTY LIST
External service reached by this flow
  • 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

webRequestAuthProvider
Updated 30 September 2026keodbianoliadkoelloecbhllnpiocoi