Is Devolutions Password Manager safe?

Medium risk

Devolutions Workspace reads form fields on every page to autofill saved logins, and ships hardcoded credentials for its telemetry server.

As a password manager, Devolutions Workspace injects a content script into every http/https/file page and frame that enumerates forms and reads input field values (including hidden fields, truncated at 254 chars) to power autofill. A second script runs in the page's main world and intercepts navigator.credentials.create/get calls to relay WebAuthn challenges to the extension. The background script also embeds a fixed username and password used to POST analytics to Devolutions' OpenSearch telemetry server; because extension source is readable after install, those credentials are effectively public.

Devolutionsv2026.2.4.8Chrome Web Store
45Risk

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

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-522
SourceAI SANDBOX

OpenSearch Basic-auth credentials in the extension package

Devolutions Password Manager includes an OpenSearch Basic-auth username and password in its background script, used to build a daily analytics POST to telemetry2.devolutions.net:9200, so anyone inspecting the package can read both values.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You keep the extension installed while its background script is running.

The analytics sender runs on startup and then uses a 24-hour interval before sending again.

The extension did this

The extension builds an OpenSearch analytics request with Basic-auth credentials stored in its own code.

The packaged source includes the account name and password value used for the request.

02EvidenceTEMPORAL PATTERN
When this fires
Every 1 day

The analytics sender runs once when the background script initializes, then suppresses another send until a full day has elapsed.

03EvidenceNETWORK CAPTURE
Captured request
POSThttps://telemetry2.devolutions.net:9200/wbex_configuration_events/_doc
The request construction was confirmed in source; no dynamic response body was recorded for this claim.
Headers
Content-Typeapplication/json
AuthorizationBasic <redacted>
04EvidenceFIELD TABLE
Fields and constants used by the OpenSearch analytics request
FieldValueWhy it matters
Analytics host
telemetry2.devolutions.net:9200This is the remote service that receives the analytics request from the extension.
Basic-auth account
WBEX_2025.3This account name is packaged with the extension and is used to authenticate the OpenSearch write request.
Basic-auth password
password value redactedThe corresponding password is also packaged with the extension, making the credential readable from the installed code.
OpenSearch index
wbex_configuration_eventsThis names the destination collection where the extension writes the settings event.
Installation identifier
4f45d8a3-2c6d-4d3b-9f25-1f0c7f7a8b61This value lets the analytics event be tied back to the same extension installation over time.
Application and browser details
WBEX 2026.2.0.6 on Chrome/Linux, en-USThese fields describe the extension version, browser, operating system, architecture, and language included in the analytics event.
Never-list counters
neverAutofillCount: 2These counters summarize how many sites were added to local lists that prevent saving, autofill, or icons.
05EvidenceCODE COMPARE
The code that does this

The shipped constants and request builder

What it actually does
Readable OpenSearch constantsdeobfuscated/background/background.js
const FA = {
  url: "https://telemetry2.devolutions.net:9200",
  username: "WBEX_2025.3",
  password: "<redacted>",
  datasourceFeatureEventIndex: "wbex_configuration_events",
  featureEventIndex: "feature_events"
};
Readable daily senderdeobfuscated/background/background.js
static async send() {
  try {
    const e = await x.getLocalStorageModelKey(["settings", "analyticsInfos", "NeverAddSite", "NeverAutofill", "NeverDoAnything", "NeverShowIconsInFields"]);
    if (!e.settings || e.settings.disableAnalytics) return;
    const i = e.analyticsInfos?.lastSentAt ?? 0;
    if (Date.now() - i < this.TWENTY_FOUR_HOURS_MS) return;
    const n = {
        neverAddSiteCount: (e.NeverAddSite ?? []).length,
        neverAutofillCount: (e.NeverAutofill ?? []).length,
        neverDoAnythingCount: (e.NeverDoAnything ?? []).length,
        neverShowIconsInFieldsCount: (e.NeverShowIconsInFields ?? []).length
      },
      r = !!(await M.getManagedStorageItem())?.Settings,
      a = await this.getInstallID();
    await x.setLocalStorageModel({
      analyticsInfos: {
        ...e.analyticsInfos,
        applicationInstallUniqueId: a,
        lastSentAt: Date.now()
      }
    }), await this.sendToOpenSearch(e.settings, n, r, a);
  } catch (e) {
    le.debug(e);
  }
}
Readable OpenSearch POST builderdeobfuscated/background/background.js
static async sendToOpenSearch(e, i, n, s) {
  const {
    url: r,
    username: a,
    password: l,
    datasourceFeatureEventIndex: u
  } = FA, d = u, h = await this.getApplicationInfos(), c = {
    eventDate: new Date().toISOString(),
    eventId: As(),
    installId: s,
    application: h,
    settings: this.sanitizeSettings(e),
    neverList: i,
    hasManagedSettings: n
  };
  await fetch(`${r}/${d}/_doc`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Basic ${btoa(`${a}:${l}`)}`
    },
    body: JSON.stringify(c)
  });
}
06EvidenceTHIRD PARTY LIST
Remote host used by this claim
  • telemetry2.devolutions.net

    Devolutions telemetry host that receives OpenSearch analytics POST requests on port 9200.

Data recipients

telemetry2.devolutions.net
Updated 17 September 2026neimonjjffhehnojilepgfejkneaidmo