Just to update this quick, WhatRuns has stopped collecting AI chats and has since disabled the functionality so it cannot be remotely enabled, they are still however sending off full URLs of every page the user visits, they also send off only the hostname of the site the user is visiting in a different request to get the data for the functionality.
I've rechecked Poper Blocker (v8.7.1), Stylish (v3.4.15) and Similarweb and they're all still exfiltrating AI chats currently.
To deobfuscate the requests from "Poper blocker", copy & paste the request outgoing contents into this function (working on v8.7.1):
function decodePoper(s) {
const rot47 = x => x.replace(/[!-~]/g, c => String.fromCharCode(33 + (c.charCodeAt(0) - 33 + 47) % 94));
const deep = v => {
if (typeof v === 'string') {
let t = v;
try { const u = decodeURIComponent(t); if (u !== t) t = u; } catch {}
if (/^[\[{]/.test(t)) { try { return deep(JSON.parse(t)); } catch {} }
return t;
}
if (Array.isArray(v)) return v.map(deep);
if (v && typeof v === 'object') return Object.fromEntries(Object.entries(v).map(([k,x]) => [k, deep(x)]));
return v;
};
let out;
try { out = deep(JSON.parse(rot47(s))); } catch { out = deep(rot47(s)); }
return out;
}
I don't want to manually reinstall the poperblocker extension to update the version on the sandbox last time it had a 24 hour delay before it started collecting the chats.
Stylish has been reconfirmed today to still be exfiltrating AI chats.
Here's the deobfuscation script, copy & paste the request outgoing contents into this function (confirmed working on v3.4.15):
async function decodeStylish(blob) {
const key = await crypto.subtle.importKey("jwk",
{alg:"A256CBC",ext:true,
k:"MaQ2KBEEiYcOcSCfszxMBVrKsXK3hxGmxZ8Zjq50KZg",
key_ops:["decrypt"],kty:"oct"},
"AES-CBC",false,["decrypt"]);
const raw = Uint8Array.from(atob(blob), c => c.charCodeAt(0));
const dec = await crypto.subtle.decrypt({name:"AES-CBC",iv:raw.slice(0,16)}, key, raw.slice(16));
const rows = new TextDecoder().decode(dec).split("\n");
let b64 = "";
for (let col = 0; col < rows[0].length; col++)
for (const row of rows) { const ch = row[col]; if (ch && ch !== " ") b64 += ch; }
const obj = JSON.parse(atob(b64));
const once = atob(obj.e.replace(/-/g,"+").replace(/_/g,"/"));
const qs = atob(once.replace(/-/g,"+").replace(/_/g,"/"));
return Object.fromEntries(new URLSearchParams(qs));
}