Is Just-One-Page-PDF: An awesome web page to PDF tool safe?

Medium risk

Just-One-Page-PDF: An awesome web page to PDF tool is medium risk. Starting a page-to-PDF capture uses the manage-extensions permission. The worker scans the page for extension iframes, matches IDs against enabled installed extensions, disables matches during capture, stores IDs, and later…

suziwen1v2.0.4Chrome Web Store
45Risk
Who publishes it

suziwen1 - 4 other listings from the same operator, none carrying a finding

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

Publisher
suziwen1

Same store account

4 other listings published from this account, 903k+ users between them, none of them carrying a finding.

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.

colorink.top
Also called by 2 other listings: %E7%88%B1%E5%93%94%E5%93%94-bilibili-b%E7%AB%99%E5%8A%A9%E6%89%8B, 小飞书--飞书 PDF 导出工具
geminilabs.io
Also called by 2 other listings, including Humantic AI

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

Publishers can request a review.

Findings

Disables Other Extensions During PDF Capture

MediumunwantedCWE-829Dynamic sandbox

Starting a page-to-PDF capture uses the manage-extensions permission.

What actually happens

You did this

You start a page-to-PDF capture.

The extension did this

The extension scans the page for extension iframes, turns matching enabled extensions off during capture, stores their IDs locally, and later tries to turn them back on.

Concrete values used by the extension-management path

  • Permission to manage extensions
    manifest permissions includes "management"

    This permission lets the extension turn other installed extensions on or off.

  • Extension iframe URL
    chrome-extension://cjpalhdlnbpafiamejdnhcphjbkeiagm/frame.html (illustrative)

    This is how the page scan identifies that another browser extension has injected a frame into the page.

  • Matched extension ID
    cjpalhdlnbpafiamejdnhcphjbkeiagm (illustrative)

    The ID is compared with enabled installed extensions before the extension is turned off.

  • Local restore list
    chrome.storage.local disableExtensionIds

    This local value records which extensions were turned off so the extension can try to restore them after capture.

  • Disable and restore values
    setEnabled(id, false) then setEnabled(id, true)

    The first value turns the matched extension off; the later value attempts to turn it back on.

Where the capture flow invokes extension disable and restore

  1. before capture

    You did

    The page-capture script sends a create request.

    The extension did

    The service worker enters the PDF creation path and scans for extension iframes before capture.

  2. during setup

    You did

    The scan returns IDs that match enabled installed extensions.

    The extension did

    Each matching extension is turned off and the IDs are saved locally.

  3. after capture

    You did

    The capture path finishes or reaches a later frame-ready path.

    The extension did

    The saved IDs are read back and the extension attempts to turn those extensions on again.

The code that does this

Shipped code that scans, disables, stores, and restores extension IDs

Readable version

Readable scanner function

js/background.js
_w = function(e) {  const t = [],    n = (r, i = 1, o) => {      if (i > 10) return "function" == typeof r.remove && e && r.remove(), void(o && "function" == typeof o.remove && o.remove());      i++;      let a = !1;      r.querySelectorAll("*").forEach((function(r) {        if (!a)          if ("IFRAME" === r.tagName)(function(n) {            if (n.src.startsWith("chrome-extension://")) {              let r = n.src;              if (r = r.substring(19), r = r.split("/")[0], r && t.push(r), e) return n.remove(), !0            }          })(r) && o && "function" == typeof o.remove && (o.remove(), a = !0);          else if (r.shadowRoot) n(r.shadowRoot, i);        else try {          const e = chrome.dom.openOrClosedShadowRoot(r);          e && n(e, i, r)        } catch (e) {}      }))    };  return n(document), t}

Readable disable function

js/background.js
Sw = async function(e) {  if (!pb.checkCanExecuteScript(e)) return [];  const t = e.id,    n = await chrome.scripting.executeScript({      target: {        tabId: t,        allFrames: !0      },      injectImmediately: !0,      func: _w    }),    r = [],    i = (await chrome.management.getAll()).filter((e => "extension" === e.type && (e.id !== chrome.runtime.id && !!e.enabled))).map((e => e.id));  if (n && n.forEach((e => {      e.result?.forEach((e => {        e != chrome.runtime.id && i.indexOf(e) >= 0 && r.push(e)      }))    })), r.length > 0) {    const e = Array.from(new Set(r));    for (let t = 0; t < e.length; t++) {      const n = e[t];      try {        await chrome.management.setEnabled(n, !1)      } catch (e) {}    }    const n = (await chrome.storage.local.get("disableExtensionIds")).disableExtensionIds || [],      i = Array.from(new Set(e.concat(n)));    return await chrome.storage.local.set({      disableExtensionIds: i    }), await chrome.scripting.executeScript({      target: {        tabId: t,        allFrames: !0      },      func: _w,      args: [!0]    }), e  }  return []}

Readable restore function

js/background.js
kw = async function(e, t) {  const n = (await chrome.storage.local.get("disableExtensionIds")).disableExtensionIds || [];  t = Array.from(new Set(n.concat(t)));  for (let e = 0; e < t.length; e++) {    const n = t[e];    try {      await chrome.management.setEnabled(n, !0)    } catch (e) {}  }  await chrome.storage.local.set({    disableExtensionIds: []  })}

The code that does this

Manifest permission that enables the behavior

Readable version
"permissions": [  "activeTab",  "contextMenus",  "scripting",  "debugger",  "downloads",  "storage",  "management",  "tabs",  "notifications",  "history"]
Updated 2 November 2026fgbhbfdgdlojklkbhdoilkdlomoilbpl