Is image downloader manager safe?

Critical risk

Image Downloader Manager is critical risk. The extension ships a modified JSZip: its deprecated generate() method now POSTs to sm.imagedownloadmanager.com and returns the JSON reply, instead of zipping. Runs whenever 'prepare-zip' calls JSZip().generate(url, body).…

97Risk

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

Publishers can request a review.

Findings

Bundled JSZip library repurposed as an undisclosed HTTP POST wrapper

The extension ships a modified JSZip: its deprecated generate() method now POSTs to sm.imagedownloadmanager.com and returns the JSON reply, instead of zipping.

Runs whenever 'prepare-zip' calls JSZip().generate(url, body).

Severity
Critical unwanted
Type
Unexpected
CWE
CWE-506
Source
Dynamic sandbox
What actually happens
You did this

You interact with the extension's download functionality, triggering a 'prepare-zip' message to the service worker.

The extension did this

Instead of building a zip file, the extension sends an HTTP POST to the developer's server and returns the server's JSON response to the caller.

The call to JSZip.prototype.generate() routes through a replacement function that performs fetch(url, {method:'POST', body}), no zip is ever created.

The code that does this

JSZip.prototype.generate, upstream vs. shipped

Readable version

Upstream JSZip 3.10.1 generate() (for reference)

(upstream reference)
// JSZip 3.x removed generate() entirely.// Calling it throws: "This method has been removed in JSZip 3.0,// please check the upgrade guide."// It accepts no URL or body arguments.
Destination for undisclosed POST requests
    • sm.imagedownloadmanager.com

    Developer-operated server that receives the POST payload from the overridden generate() call and returns a JSON response

Reproduce it yourself

Loads the shipped JSZip from the extension directory and confirms that generate() performs a fetch instead of creating a zip archive.

Requires
  • Node.js 18+
jszip-trojan-poc.js · js
#!/usr/bin/env node// Reproducer for the trojanized JSZip generate() override// Run from the extension's deobfuscated directory://   node jszip-trojan-poc.jsconst path = require('path');// Capture fetch calls before loading the libraryconst calls = [];globalThis.fetch = (url, opts) => {  calls.push({ url, method: opts?.method ?? 'GET', bodyType: typeof opts?.body });  return Promise.resolve({ json: () => Promise.resolve({ intercepted: true }) });};// Simulate the module environment JSZip expectsglobalThis.window = globalThis;const src = require('fs').readFileSync(  path.join(__dirname, 'libs/jszip.js'), 'utf8');// JSZip registers itself on a global when loaded via script tageval(src);const zip = new JSZip();zip.generate('https://sm.imagedownloadmanager.com/c', JSON.stringify({test: 1}))  .then(() => {    if (calls.length === 1 && calls[0].method === 'POST') {      console.log('CONFIRMED: generate() issued a POST fetch instead of building a zip.');      console.log('Captured call:', JSON.stringify(calls[0], null, 2));      process.exit(0);    } else {      console.error('UNEXPECTED: calls=', JSON.stringify(calls));      process.exit(1);    }  })  .catch(err => {    console.error('Error:', err.message);    process.exit(1);  });
How to run it
  1. 1Copy this file into the extension's deobfuscated/ directory.
  2. 2Run `node jszip-trojan-poc.js`.
  3. 3Expect output: 'CONFIRMED: generate() issued a POST fetch...'

Daily server-controlled filter determines which sites the extension targets

On install and every 24 hours, the extension downloads a 262,144-byte Bloom filter from sm.imagedownloadmanager.com/supportedMedia, deciding which sites run its media logic.

Updates happen silently, so targets can change anytime.

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

On every browser startup and every 24 hours thereafter, the extension contacts the developer's server.

The extension did this

The server returns a binary payload that without notifying the user replaces the stored Bloom filter, changing which websites the extension runs its media-interception logic on.

No user prompt or notification accompanies this update. The extension's content script reads the updated filter on the next page load.

Captured request
GEThttps://sm.imagedownloadmanager.com/supportedMedia

HTTP 200, 262,144 bytes, Content-Type: application/octet-stream (Bloom filter bit-array). Observed during dynamic analysis: three requests captured within an 11-second window.

Headers
key
imd-ext-key-prod
version
4.2.0
The code that does this

Bloom filter fetch and per-page targeting gate

Readable version

Startup and alarm wiring (service-worker.js lines 5-34)

service-worker.js
// On browser startup — fetch filter immediatelychrome.runtime.onStartup.addListener(() => {  loadCurrentSupportedMedias();});// On install — set up the daily alarmchrome.runtime.onInstalled.addListener(() => {  // ... prefs defaults ...  chrome.alarms.create('dailyTicktack', { periodInMinutes: 24 * 60 });});// Alarm fires every 24 h — re-fetch the filterchrome.alarms.onAlarm.addListener((alarm) => {  if (alarm.name === 'dailyTicktack') {    loadCurrentSupportedMedias();  }});
What's stored on your device

A 262,144-byte Bloom filter from the developer's server, read each page load. The server can silently retarget it on the next refresh.

Location
chrome.storage.local key 'supportedMedia'
Contents
[0, 0, 0, 12, 128, 0, 4, 0, 2, 64, ... (262,144 total bytes)]
Server providing the targeting filter
    • sm.imagedownloadmanager.com

    Developer-operated CDN/API that serves the Bloom filter controlling which websites the extension targets and receives the extension's version and manifest key on every request

What it can do

Permissions this extension asks for, as declared in version 4.2.0. 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 site you visit

    <all_urls>

  • Start, monitor and manage your downloads

    downloads

  • Store data in your browser

    storage

  • Schedule its own background tasks

    alarms

Updated 21 September 2026lkfpbdoaiidkjnfoechefnifgmoipkap