Is VMP™ Pass Password Manager safe?
VMP Pass is high risk. When you verify or set the vault master password, the extension builds a JSON request with your email and typed password, sent to passwordmanager.themebeaver.com:5443. Not reached live; test account was unregistered. Evidenced from source.…
Who publishes itVPN Master Pro - no other listings under this identity
VPN Master Pro - no other listings under this identity
What this publisher told the store about itself, and the other listings that told it the same thing.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Master password posted to Themebeaver API
When you verify or set the vault master password, the extension builds a JSON request with your email and typed password, sent to passwordmanager.themebeaver.com:5443.
Not reached live; test account was unregistered.
Evidenced from source.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-522
- Source
- Dynamic sandbox
You enter the vault master password during verification or setup.
The extension places that password in a JSON request to the Themebeaver API.
- Account emailuser@example.com (illustrative)
This ties the password check to your password-manager account.
- Vault master passwordcorrect-horse-battery-staple (illustrative)
This is the password you rely on to unlock or create the vault.
- Content-Type
- application/json
Verification and setup handlers build password JSON requests
Readable verify-password handler
assets/masterPass.jsd0 = B("master_password", "verify_password", async t => { if (t.preventDefault(), !E) { const r = new Error("Please enter your master password"); v("master_password", "validation", r, { hasPassword: !1, passwordLength: 0 }), n(r.message); return } d(!0), n(""); try { const s = await (await q(`${g}/api/verify-password`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: e, password: E }), context: { component: "MasterPass", action: "verifyPassword", userEmail: e } })).json(); if (s.success && s.verified) { try { const i = await (await fetch(`${g}/api/salt/${encodeURIComponent(S)}`)).json(); if (!i.success || !i.salt) throw new Error("Failed to retrieve encryption salt"); const x = await N.deriveEncryptionKey(E, i.salt); await N.storeEncryptionKey(x, S) } catch (o) { console.error("❌ Failed to generate encryption key:", o), n("Failed to setup encryption. Please try again."), d(!1); return } try { await Q(e) } catch (o) { console.error("⚠️ Failed to load settings, will use defaults:", o) } chrome.storage.local.get(["userSettings"], o => { if (console.log("🔍 [MasterPass-Verify] Checking userSettings:", o.userSettings ? "EXISTS" : "NOT FOUND"), o.userSettings) console.log("⏭️ [MasterPass-Verify] Settings already exist, skipping initialization"); else { console.log("🆕 [MasterPass-Verify] Initializing default settings..."); const i = { accessibility: !1, biometricLogin: !1, passwordSuggestions: !0, matchSubdomain: !1, autoSubmit: !1, vmpfillTool: !0, autofillPrompt: !0, savePasswordPrompt: !0, changePasswordPrompt: !0, httpWarningPrompt: !0, vmpfillDisabledPrompt: !0, clipboard: { enabled: !0, time: "30" }, security: { stayLoggedIn: !0, inactivityTimer: { value: "30", unit: "Minutes" } }, fieldIcons: "always", theme: "Light", promptLocation: { location: "Top Right", animation: "Slide In" } }; chrome.storage.local.set({ userSettings: i }, () => { chrome.runtime.lastError ? console.error("❌ [MasterPass-Verify] Error storing settings:", chrome.runtime.lastError) : console.log("✅ [MasterPass-Verify] Default settings initialized successfully") }) } }), chrome.storage.local.set({ vault_unlocked: !0, vault_unlock_time: new Date().getTime() }, async () => { const o = chrome.runtime.lastError; if (o) { console.error("Storage error:", o), n("Failed to unlock vault. Please try again."), d(!1); return } if (K(), await J("master_password", e, e == null ? void 0 : e.split("@")[0], "vault_unlock"), L) { window.close(); return } try { (await chrome.windows.getCurrent()).type === "popup" ? window.close() : F() } catch { F() } }) } else if (s.passwordNotSet || s.error === "Password not set for this user") p("set"), H(""); else { const o = new Error("Invalid master password"); v("master_password", "authentication_failed", o, { passwordNotSet: s.passwordNotSet, apiError: s.error, verified: s.verified }), n(o.message) } } catch (r) { const s = new Error("An error occurred. Please try again."); v("master_password", "network_error", r, { originalMessage: r.message, userEmail: e }), n(s.message) } finally { d(!1) }})Readable update-password handler
assets/masterPass.jsh0 = async () => { U(!1), _("masterpass_warning_confirmed", { user_email: e, timestamp: new Date().toISOString() }), C("masterpass_warning_confirmed", { user_email: e, timestamp: new Date().toISOString() }), d(!0), n(""); try { const r = await (await q(`${g}/api/update-password`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: e, password: w }), context: { component: "MasterPass", action: "setPassword", userEmail: e } })).json(); if (r.success) { try { const o = await (await fetch(`${g}/api/salt/${encodeURIComponent(S)}`)).json(); if (!o.success || !o.salt) throw new Error("Failed to retrieve encryption salt"); const i = await N.deriveEncryptionKey(w, o.salt); await N.storeEncryptionKey(i, S) } catch (s) { console.error("❌ Failed to generate encryption key:", s), n("Failed to setup encryption. Please try again."), d(!1); return } chrome.storage.local.get(["userSettings"], s => { if (console.log("🔍 [MasterPass] Checking userSettings:", s.userSettings ? "EXISTS" : "NOT FOUND"), s.userSettings) console.log("⏭️ [MasterPass] Settings already exist, skipping initialization"); else { console.log("🆕 [MasterPass] Initializing default settings..."); const o = { accessibility: !1, biometricLogin: !1, passwordSuggestions: !0, matchSubdomain: !1, autoSubmit: !1, vmpfillTool: !0, autofillPrompt: !0, savePasswordPrompt: !0, changePasswordPrompt: !0, httpWarningPrompt: !0, vmpfillDisabledPrompt: !0, clipboard: { enabled: !0, time: "30" }, security: { stayLoggedIn: !0, inactivityTimer: { value: "30", unit: "Minutes" } }, fieldIcons: "always", theme: "Light", promptLocation: { location: "Top Right", animation: "Slide In" } }; chrome.storage.local.set({ userSettings: o }, () => { chrome.runtime.lastError ? console.error("❌ [MasterPass] Error storing settings:", chrome.runtime.lastError) : console.log("✅ [MasterPass] Default settings initialized successfully") }) } }), chrome.storage.local.set({ vault_unlocked: !0, vault_unlock_time: new Date().getTime() }, async () => { const s = chrome.runtime.lastError; if (s) { console.error("Storage error:", s), n("Failed to save vault state. Please try again."), d(!1); return } _("masterpass_password_created", { user_email: e, timestamp: new Date().toISOString() }), await C("masterpass_password_created", { user_email: e, timestamp: new Date().toISOString() }), await K(), await J("master_password", e, e == null ? void 0 : e.split("@")[0], "new_account_setup"); try { (await chrome.windows.getCurrent()).type === "popup" ? window.close() : F() } catch { F() } }) } else { const s = new Error("Failed to set password: " + (r.error || "Unknown error")); v("master_password", "set_password_failed", s, { apiSuccess: !1, apiError: r.error }), n(s.message) } } catch (t) { const r = new Error("An error occurred. Please try again."); v("master_password", "network_error", t, { originalMessage: t.message, userEmail: e }), n(r.message) } finally { d(!1) }}Readable API base URL
assets/main.js_API_PROD = "https://passwordmanager.themebeaver.com:5443",API_BASE_URL = _API_PROD- passwordmanager.themebeaver.com
Receives the verify-password and update-password API requests for the Themebeaver password-manager service.
User email transmitted to developer server on every vault page load
Visiting the VMP Pass web vault at vmppass.com, the content script sends your email to passwordmanager.themebeaver.com:5443 via POST /api/ext/auth/create-ticket.
DA captured four such requests across two navigations, on every page load.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You navigate to vmppass.com while logged in to the extension.
No explicit action beyond page navigation is required.
The extension sends your email address to passwordmanager.themebeaver.com:5443 via a POST to /api/ext/auth/create-ticket.
This happens on every page load at vmppass.com, and again when the extension vault is unlocked while you are on that site.
Returns {success: true, ticket: "eyJ..."}, a short-lived token written to vmppass.com localStorage.
- Content-Type
- application/json
{ "email": "user@example.com"}Ticket creation trigger, background.js
// background.js lines 1861-1879 — triggered on every VAULT_PAGE_LOADED messagechrome.storage.local.get( ['oauth_token', 'vault_unlocked', 'encryption_key_base64', 'last_user_email'], async (authData) => { if (!authData.oauth_token || !authData.last_user_email) { sendResponse({ success: true }); return; } const email = authData.last_user_email; // POST email to developer server on every page load const ticketRes = await fetch(`${API_BASE_URL}/api/ext/auth/create-ticket`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email }) }); });- Email addressjane.smith@company.com
Your account email address, as stored in the extension, is sent to the developer's server on every page load at vmppass.com.
- passwordmanager.themebeaver.com
Developer backend operated by Themebeaver; receives user email address on every vmppass.com page load to issue short-lived auto-login tickets.
Autofill events transmit your email and visited URL to developer analytics
When you fill in or save credentials on a site, the extension sends your email, the page URL, title, and domain to an analytics server at passwordmanager.themebeaver.com, in the background, without notice.
A canary email confirmed this.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You use the autofill dropdown or autosave popup to fill or save a password on a login page.
This covers autofill_credential_selected, autofill_fill_success, autosave_popup_shown, autosave_save_clicked, and autosave_save_success events.
The extension sends your account email, the full URL of that page, and the page title to the developer's analytics server.
The POST goes to https://passwordmanager.themebeaver.com:5443/api/extension-analytics/events and includes your email address as a top-level field.
Dynamic analysis confirmed canary email a planted marker email appeared in POST bodies for captured during dynamic analysis, and 62 across a 3-minute session.
- Content-Type
- application/json
{ "event_name": "autofill_fill_success", "user_email": "alice@example.com", "user_id": "u_68a3f1c2b9", "client_id": "8b2c4f1a-3d5e-4a7b-9c0d-1e2f3a4b5c6d", "session_id": "s_7f9d2a1b4c", "event_params": { "page_path": "/login", "page_title": "Sign In — Acme Corp", "page_location": "https://app.acmecorp.com/login", "domain": "app.acmecorp.com", "is_https": true }, "context": { "app_version": "2.8.0", "browser": "Chrome", "browser_version": "124.0.6367.62", "os": "macOS", "os_version": "14.4.1", "country": "United States", "city": "San Francisco", "region": "California", "timezone": "America/Los_Angeles", "language": "en-US", "screen_width": 1920, "screen_height": 1080 }}- Account email addressalice@example.com
Your registered email for this password manager is sent to the developer's server each time you autofill or save credentials.
- Full page URLhttps://app.acmecorp.com/login
The complete URL of the site where you used autofill reveals which services and accounts you have credentials for.
- Page titleSign In — Acme Corp
The browser tab title of the page where autofill was triggered.
- Domainapp.acmecorp.com
The hostname of the site where autofill was used, indicating which service you were logging into.
- Client and session ID8b2c4f1a-3d5e-4a7b-9c0d-1e2f3a4b5c6d
Persistent identifiers that let the developer track autofill behavior across browser sessions.
Content script assembles payload with user email and page URL
Background.js forwards payload to developer server (background.js:1277-1299)
background.jsif (message.action === 'SEND_CUSTOM_ANALYTICS') { const CUSTOM_ANALYTICS_URL = `${self.VMP_API_BASE_URL}/api/extension-analytics/events`; (async () => { try { const response = await fetch(CUSTOM_ANALYTICS_URL, { method: 'POST', body: JSON.stringify(message.payload), headers: { 'Content-Type': 'application/json' } }); const result = await response.json(); sendResponse(result); } catch (error) { sendResponse({ success: false, error: error.message }); } })(); return true;}- passwordmanager.themebeaver.com
Developer-operated analytics backend. Receives user email, full page URL, page title, domain, and behavioral event data on every autofill or autosave action.
+2 more findings not shown