Is Mendeley Web Importer safe?

Medium risk

Mendeley Web Importer sends analytics with your IP address and device fingerprint to New Relic, Adobe Analytics, and Mendeley.

When you use the extension to import academic articles, it collects telemetry that includes your public IP address (fetched from api.ipify.org), screen resolution, browser language, timezone, and the URL of the page you are viewing. These details are transmitted to three third-party analytics endpoints: Elsevier's Adobe Analytics (elsevier.sc.omtrdc.net), New Relic (insights-collector.newrelic.com), and Mendeley's own backend (brxt.mendeley.com). The IP is cached for 60 minutes and included in events fired on common actions such as opening the extension, scraping article metadata, and downloading PDFs.

Mendeleyv3.2.78Firefox Add-ons
50Risk
Who publishes it

Mendeley - no other listings under this identity, 7 shared hostnames

What this publisher told the store about itself, and the other listings that told it the same thing.

Shared hosts - 7 hostnames

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.

brxt.mendeley.com
Also called by 1 other listing
elsevier.sc.omtrdc.net
Also called by 1 other listing: Mendeley Web Importer
howcanishareit.com
Also called by 1 other listing: Mendeley Web Importer
portal.prodpad.com
Also called by 1 other listing: Nuxeo Dev Tools
reader.elsevier.com
Also called by 1 other listing: Mendeley Web Importer
relx.com
Also called by 1 other listing: Mendeley Web Importer
service.elsevier.com
Also called by 2 other listings, including Scopus Document Download Manager

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

Publishers can request a review.

Findings

Mendeley sends device analytics to New Relic and Adobe

MediumunwantedCWE-359Dynamic sandbox

Mendeley Web Importer builds analytics events when you open or use it, including browser, screen, language, time zone, tab URL, account, and IP when available.

What actually happens

You did this

You open Mendeley Web Importer or use one of its import, login, PDF, or download features.

The extension did this

The extension builds an analytics event with device, browser, session, account, institution, IP, and tab context when those values are available.

Fields assembled before analytics transmission

  • Action name
    EXTENSION_LAUNCHED

    This tells the analytics service which extension action happened.

  • Browser and operating system
    Firefox 128 on Linux

    This identifies your browser family, version, and operating-system family for the event.

  • Language and time zone
    en-US, UTC offset -240

    This adds locale and time-zone context that can narrow where and how you use the browser.

  • Screen size
    1920x1080

    This records your display dimensions as part of the event context.

  • Cookie support
    true

    This records whether your browser reports cookies as enabled.

  • Extension version and ID
    3.2.78, webapps@mendeley.com

    This ties the event to the installed extension build and browser extension identifier.

  • Session ID
    7d4a5c68-1c5e-4ac6-9f07-4f6b8fd3e318

    This lets events from the same browser session be grouped together.

  • Tab URL and hostname
    https://pubmed.ncbi.nlm.nih.gov/37200000/

    This can reveal the page associated with the extension action.

  • Account and institution
    userId 1234567, institution Example University

    When you are signed in, this can associate the event with your Mendeley account and institution.

  • IP address
    198.51.100.24 (illustrative)

    This can identify the network used when the analytics event is sent.

Captured request

POSThttps://insights-collector.newrelic.com/v1/accounts/67651/events

The verification evidence records the POST target and header; no request body or response body was recorded for this claim.

Headers
Content-Type
application/json
X-Insert-Key
<redacted>

The code that does this

The analytics builder and senders in background.js

Readable version

New Relic queue and POST sender

deobfuscated/background.js
const newRelicUrl = N.newrelic_insights_url;const newRelicInsertKey = N.newrelic_insights_apikey;const normalizeFields = event => Object.fromEntries(  Object.entries(event)    .filter(([, value]) => value !== undefined)    .map(([key, value]) => typeof value === "boolean" ? [key, String(value)] : [key, value]));const queuedEvents = new Set;function Bs(actionName, fields = {}) {  queuedEvents.add({    appName: "brxt-extension",    eventType: "PageAction",    actionName,    ...normalizeFields(fields)  });  if (Us === null) Us = setTimeout(js, 1000);}let Us = null;async function js() {  Us = null;  fetch(newRelicUrl, {    method: "POST",    headers: {      "Content-Type": "application/json",      "X-Insert-Key": newRelicInsertKey    },    body: JSON.stringify([...queuedEvents])  });  queuedEvents.clear();}

Event context builder

deobfuscated/background.js
const analyticsClients = [e, n, t];const Ys = (...args) => {  try {    (function(actionName, eventData = {}, context = {}) {      const parsedUa = Is().parse(window.navigator.userAgent);      const event = {        ...eventData,        ...context,        extensionVersion: f.client_version,        extensionBuildTarget: f.target_platform,        userAgent: navigator.userAgent,        userAgentName: parsedUa.browser.name,        userAgentVersion: parsedUa.browser.version,        userAgentOsName: parsedUa.os.name,        userAgentOsVersion: parsedUa.os.version,        userAgentOsVersionName: parsedUa.os.versionName,        language: navigator.language,        cookiesEnabled: navigator.cookieEnabled,        timestamp: Date.now(),        timezone: (new Date).getTimezoneOffset(),        extensionId: o().runtime.id,        height: window.screen.height,        width: window.screen.width,        sessionId: F()      };      analyticsClients.forEach(client => client.logEvent(actionName, event));    })(...args);  } catch (error) {    console.error(error);  }};

Tab, account, institution, IP, and session context

deobfuscated/background.js
const $c = tab => {  if (tab && tab.url) {    return {      tabUrl: tab.url,      tabHostname: new URL(tab.url).hostname,      tabIncognito: tab.incognito    };  }};const Wc = state => {  const timeSinceLaunched = Date.now() - state.launched;  const timeSinceLoaded = state.loaded ? Date.now() - state.loaded : void 0;  const oneHour = 36e5;  const userInfo = rl.possiblyStale({ refreshIfOlderThan: oneHour });  const userProfileUuid = userInfo == null ? void 0 : userInfo.mendeleyId;  const analyticsInfo = userInfo == null ? void 0 : userInfo.analyticsInfo;  const userId = analyticsInfo == null ? void 0 : analyticsInfo.userId;  const institutionId = analyticsInfo == null ? void 0 : analyticsInfo.accountId;  const institutionName = analyticsInfo == null ? void 0 : analyticsInfo.accountName;  const accessType = analyticsInfo == null ? void 0 : analyticsInfo.accessType;  const ipAddress = Rs.possiblyStale({ refreshIfOlderThan: oneHour });  const sessionId = F();  return {    ...$c(state.tab),    accessType,    institutionId,    institutionName,    ipAddress,    timeSinceLaunched,    timeSinceLoaded,    userId,    userProfileUuid,    sessionId  };};

Popup launch trigger

deobfuscated/background.js
const tl = async tab => {  const state = Yc(tab);  state.launched || (state.launched = Date.now());  Xs(tab);  Ys("EXTENSION_LAUNCHED", void 0, Wc(state));};o().browserAction.onClicked.addListener(tl);

Adobe Analytics XML sender

deobfuscated/background.js
function As(actionName, fields) {  const adobePageFields = vs[actionName];  if (!adobePageFields) return;  if (actionName === "ADD_REF_TO_LIBRARY") {    adobePageFields.events = fields.addReferenceSuccess ? "event79" : "event26";  }  const body = function(event) {    const {      accessType, cookiesEnabled, errorMessage, events, height, institutionId,      institutionName, ipAddress, language, linkName, linkType, page, pageName,      pageType, products, timestamp, timezone, userAgent, userId, width    } = event;    const xmlFields = {      connectionType: "LAN",      cookiesEnabled,      evar7: institutionName,      evar16: institutionId,      evar29: userId,      evar33: accessType,      evar43: errorMessage,      events,      ipAddress,      language,      linkName,      linkType,      page,      pageName,      products,      resolution: width && height ? `${width}x${height}` : "",      timestamp,      timezone,      userAgent    };    return `<?xml version="1.0" encoding="UTF-8"?>\n<request>${      "\n" + Object.entries(xmlFields)        .map(([key, value]) => value ? `  <${key}>${value}</${key}>\n` : "")        .join("")    }</request>\n`;  }({ ...fields, ...adobePageFields });  fetch("https://elsevier.sc.omtrdc.net/b/ss//6", {    method: "POST",    headers: { "Content-Type": "text/xml" },    body  }).catch();}

Network destinations used by this analytics path

    • insights-collector.newrelic.com

    Receives batched JSON PageAction analytics events through the New Relic Insights endpoint.

    • elsevier.sc.omtrdc.net

    Receives Adobe Analytics XML requests built from the same event fields.

    • api.ipify.org

    Supplies the public IP address that Wc can add to later analytics event context.

What it can do

Permissions this extension asks for, as declared in version 3.2.78. 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

    <all_urls>

  • Read and change cookies, including the ones that keep you signed in

    cookies

  • Start, monitor and manage your downloads

    downloads

  • Show you desktop notifications

    notifications

  • Store data in your browser

    storage

  • Watch every request your browser makes

    webRequest

Where it sends data

Destinations our analysis observed Mendeley Web Importer contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.

  • api.ipify.orgwidely used

    Mendeley Web Importer sends data to api.ipify.org. A widely used service: 58 other extensions we have analyzed send data here.

  • elsevier.sc.omtrdc.net

    Mendeley Web Importer sends data to elsevier.sc.omtrdc.net. One other extension we have analyzed sends data here.

  • insights-collector.newrelic.com

    Mendeley Web Importer sends data to insights-collector.newrelic.com. One other extension we have analyzed sends data here.

  • brxt.mendeley.com

    Mendeley Web Importer sends data to brxt.mendeley.com. No other extension we have analyzed sends data here.

Updated 2 November 2026amo-2614372