Is EasyPubMedicine safe?

Medium risk

EP is medium risk. EasyPubMedicine has a sidebar-controlled clipboard listener. Once started, the background script picks a sandbox textarea, runs Chrome's paste command each second, reads paste-event text, strips control chars, returns it via the port.…

EasyPubMedv0.1.24Chrome Web Store
49Risk
Who publishes it

EasyPubMed - no other listings under this identity, 2 shared hostnames

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

Shared hosts - 2 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.

libgen.gs
Also called by 3 other listings, including Libgen search
libweb.anglia.ac.uk
Also called by 3 other listings, including MyBib

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

Publishers can request a review.

Findings

Sidebar clipboard listener polls text every second

EasyPubMedicine has a sidebar-controlled clipboard listener.

Once started, the background script picks a sandbox textarea, runs Chrome's paste command each second, reads paste-event text, strips control chars, returns it via the port.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-200
Source
Dynamic sandbox
What actually happens
You did this

You use the sidebar path that starts clipboard listening.

The extension did this

The extension checks for clipboard text every second and returns changed text through its own port.

The confirmed source path is gated behind the sidebar-controlled listener rather than running on every page load.

When this fires

Every 1 second

After the listener starts, the background script repeats the paste check once per second until disabled.

Clipboard data handled by the listener
  • Clipboard text
    PMID 30293440 abstract note copied for translation

    Text you copied can be read by the extension while this listener is active.

  • Sanitized text
    Trial design summary copied from a PubMed page

    Line breaks and a control character are removed before the text is sent through the extension port.

The code that does this

Background clipboard polling path

Readable version

Readable background method

js/background.js
async watchClipboard() {  let e = this;  function t() {    document.getElementById("sandbox").select(), document.execCommand("paste")  }  window.ep.watchClipboardIntervalId && clearInterval(window.ep.watchClipboardIntervalId), Et("#sandbox").length || Et("body").append("<textarea id='sandbox'></textarea>"), window.ep.watchClipboardIntervalId = setInterval(t, 1e3);  let n = !0;  this.pasteListener = function(t) {    t.preventDefault();    let r = t.clipboardData.getData("text");    if (n) return n = !1, void(window.ep.clipboard = r);    window.ep.clipboard != r && (window.ep.clipboard = r, e.responseMessage({      clipboard: r.replace(/[\r\n\x02]/g, "")    }, {      msg: "clipboardResponse",      ori: !1    }))  }, document.addEventListener("paste", this.pasteListener)}

Sidebar screenshot feature captures the active tab

EasyPubMedicine's screenshot feature attaches Chrome's debugger API to the tab for a full-page PNG.

The script builds a bounding box, requests Page.captureScreenshot with captureBeyondViewport, posts the PNG into the UI.

None was sent out.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-200
Source
Dynamic sandbox
What actually happens
You did this

You click the extension's screenshot button on a PubMed page.

The extension did this

The extension attaches the debugger interface to the active tab and captures a PNG image.

The capture request asks Chrome to include page content beyond the current viewport.

Page data included in the screenshot path
  • Active tab image
    PubMed article header for PMID 30293440

    The screenshot can include the page content visible to you at the time of capture.

  • Off-screen page area
    Article title, authors, citation metadata, and header layout

    The capture request can include page content outside the current viewport when Chrome supports it.

  • Image data
    data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA

    The captured page area is represented as a base64 PNG before it is shown in the extension UI.

The code that does this

Debugger screenshot capture path

Readable version

Readable background capture method

js/background.js
async screenshotActiveTabBoundingBox(e) {  let t = this,    n = t.msgId,    r = {      active: !0,      lastFocusedWindow: !0    },    i = await chrome.tabs.query(r),    a = i[0].id;  St.log("tab", a);  let s = !1;  chrome.tabs.query(r, (function(r) {    let i = r[0].id;    chrome.debugger.attach({      tabId: i    }, "1.3", (function() {      chrome.debugger.sendCommand({        tabId: i      }, "Page.captureScreenshot", {        format: "png",        fromSurface: !0,        captureBeyondViewport: !0,        quality: 100,        clip: e      }, (function(e) {        St.log(chrome.runtime.lastError), St.log("background-screenshotBoundingBox", e), e ? (t.responseMessage(e, n), s = !0, chrome.debugger.detach({          tabId: i        }, void 0)) : t.responseMessage({}, n, {          success: !1        })      }))    }))  })), setTimeout(() => {    s || t.responseMessage({}, n, {      success: !1    })  }, 2e3)}

Readable content-script request and display path

js/content-script.js
async function pt(t, e = 0, i = {  preProcess: void 0,  postProcess: void 0}, r) {  null === i || void 0 === i || i.preProcess();  let s = document.body.style.overflow;  document.body.style.overflow = "hidden";  let {    x: a,    y: o,    height: l,    width: u  } = t.getBoundingClientRect(), c = {    x: a + scrollX - e,    y: o + scrollY - e,    height: l + 2 * e,    width: u + 2 * e,    scale: 1  }, p = await ht(c);  if (!p) return document.body.style.overflow = s, null === i || void 0 === i || i.postProcess(), void Object(n["a"])("Some iframes might hinder the ability to capture a screenshot. Would you like to remove them and take a screenshot?", [{    text: "Continue to capture the screenshot",    events: {      click: () => {        let n = document.querySelectorAll("iframe");        for (let t of n) console.log(chrome.runtime.id), mt(t) || t.remove();        pt(t, e, i, r)      }    },    style: "yes"  }, {    text: "Cancel",    style: "no"  }], "warning", 0);  document.body.style.overflow = s, null === i || void 0 === i || i.postProcess();  let {    screenshotPort: h  } = await dt();  h.postMessage({    msg: "addImage",    data: {      image: p,      base64ImageWithHeader: "data:image/png;base64," + p,      config: r    }  }, "*")}async function ht(t) {  window.epScreenshotPort && !window.epScreenshotPort.isDisconnect || (ct = window.epScreenshotPort = h("epScreenshotPort"));  try {    let {      data: e    } = await ct.sendWithPromise("screenshotActiveTabBoundingBox", t, 500);    return e.data  } catch (e) {    return !1  }}
Updated 30 September 2026nkpdpmomjhifdobiopmgfjjffacldfje