Is VPN VeePN - Free VPN for Firefox safe?

Medium risk

VPN VeePN enumerates all installed browser extensions and sends their names, IDs, and versions to an AWS endpoint on install and update.

On installation or update, the extension calls chrome.management.getAll() and sends each discovered extension's name, ID, version, and install type to an AWS Lambda endpoint operated by VeePN. Every analytics event also includes the user's IP address, country, region, OS and browser version, screen dimensions, timezone, and a persistent device UUID. Additionally, the extension can detect and disable other installed extensions that hold the proxy permission.

VeePNv4.0.2Firefox Add-ons
45Risk

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

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Extension Can Disable Other Proxy-Control Add-ons

Clicking the extension's proxy-conflict fix option lists enabled add-ons, identifies ones requesting proxy access, and disables each match via the extension-management permission.

This can turn off another VPN or proxy add-on.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You choose the extension's proxy-conflict fix from the popup.

The popup has controls for fixing a blocked proxy connection.

The extension did this

The extension finds enabled add-ons with proxy access and disables each match.

The code excludes its own add-on ID before applying the disable operation.

02EvidenceFIELD TABLE
Installed add-on fields used by the disable path
FieldValueWhy it matters
Installed add-on type
extensionShows whether an installed item is a browser add-on that can be considered for the proxy-conflict flow.
Proxy access flag
permissions includes proxyShows whether another add-on has the kind of access needed to control browser proxy settings.
Enabled state
enabled: trueShows whether the other add-on is currently active and therefore eligible to be turned off by this flow.
Add-on identifier
bihmplhobchoageeokmgbdihknkjbknd (illustrative)Gives the extension a specific installed add-on to disable rather than only showing a general warning.
03EvidenceCODE COMPARE
The code that does this

Background code that finds and disables proxy-capable add-ons

What it actually does
Readable filter and disable methodsassets/background.ts-DFouEIUW.js
static async getActiveExtensionsWithProxyPermition() {
  return (await r.management.getAll()).filter(n => n.type === "extension" && n.id !== r.runtime.id).filter(n => {
    const i = n.enabled,
      o = n.permissions?.includes("proxy");
    return i && o
  })
}
async getProxyControlStatus() {
  const e = await r.tabs.query({
      active: !0,
      currentWindow: !0
    }).then(i => i.at(0)?.url),
    s = ["chrome://extensions", "about:addons", "edge://extensions", "opera://extensions"].some(i => e?.includes(i));
  return {
    success: !0,
    data: {
      blocked: !(await this.proxyService.getControlProxyStatus()).status,
      "extensions-tab": s
    }
  }
}
async openExtensionsTab() {
  await Promise.resolve(this);
  const s = {
    chrome: "chrome://extensions",
    firefox: "about:addons",
    edge: "edge://extensions",
    opera: "opera://extensions"
  } ["firefox"];
  return await r.tabs.create({
    url: s
  }), {
    success: !0,
    data: {
      success: !0
    }
  }
}
async disableProxyControlExtensions() {
  await Promise.resolve(this);
  const e = await Z.getActiveExtensionsWithProxyPermition();
  return await Promise.all(e.map(t => r.management.setEnabled(t.id, !1))), {
    success: !0,
    data: {
      success: !0
    }
  }
}
Readable message registrationassets/background.ts-DFouEIUW.js
"get-proxy-control-status": this.getProxyControlStatus.bind(this),
"open-extensions-tab": this.openExtensionsTab.bind(this),
"disable-proxy-control-extensions": this.disableProxyControlExtensions.bind(this)
04EvidenceCODE COMPARE
The code that does this

Popup controls that send the disable message

What it actually does
Readable popup callbacksassets/popup.html-dYpdzSuq.js
r = function() {
  sendMessageApp("send-analytic-event", {
    types: ["google-analytics", "amplitude", "aws-kinesis"],
    name: "extension_connection_blocked_another_extension_fix_for_me"
  }).catch(() => {}), sendMessageApp("disable-proxy-control-extensions").then(() => {
    e(), i(null)
  }).catch(() => {})
}
a = function() {
  sendMessageApp("send-analytic-event", {
    types: ["google-analytics", "amplitude", "aws-kinesis"],
    name: "extension_connection_blocked_another_extension_fix_myself"
  }).catch(() => {}), getProxyControlStatus().then(d => {
    d["extensions-tab"] ? i("turn-off") : i("instruction")
  }).catch(() => {})
}
o = function() {
  sendMessageApp("open-extensions-tab").catch(() => {})
}
l = function() {
  getProxyControlStatus().then(d => {
    d.blocked ? i("help") : (e(), i(null))
  }).catch(() => {})
}
c = function() {
  sendMessageApp("disable-proxy-control-extensions").then(() => {
    e(), i(null)
  }).catch(() => {})
}
05EvidenceCODE COMPARE
The code that does this

Manifest permission that allows installed-add-on management

What it actually does
"permissions": [
  "storage",
  "proxy",
  "tabs",
  "cookies",
  "notifications",
  "webRequest",
  "webRequestAuthProvider",
  "privacy",
  "management"
]

Data recipients

l7hs5ym3xsnfrchbfwycmd2rou0aqhzl.lambda-url.us-west-2.on.aws1.1.1.1veepn.com
Updated 17 September 2026amo-2590333