Sep 11, 2026·5 min read·24 visits
An authenticated attacker can crash the shared Open WebUI background scheduler by sending non-numeric values in calendar event metadata, resulting in instance-wide suppression of all calendar alerts.
Open WebUI is a self-hosted AI platform. Versions 0.9.0 through 0.11.0 contain a denial-of-service vulnerability where an authenticated user can inject non-numeric values into calendar event alert metadata. The shared scheduler process fails to validate the type, leading to an unhandled TypeError that halts the execution of instance-wide alerts, suppressing notifications for all users.
Open WebUI, a self-hosted, feature-rich interface for artificial intelligence platforms, implements a calendar management system inside its backend architecture. This system allows users with calendar-editing privileges to create, schedule, and configure events, including setting reminder notifications via the alert_minutes metadata parameter.\n\nThe core vulnerability resides in the backend scheduling mechanism, which uses a single, shared, background polling thread to aggregate upcoming events across all users. This multi-tenant design processes events sequentially in a unified loop without isolation boundaries or localized error-handling routines.\n\nAn authenticated user can abuse this shared context by submitting an event with non-numeric metadata. Because the platform fails to validate the data type on input, the value is written directly to the database. When the shared background scheduler subsequently retrieves the entry, it encounters an unexpected data type, leading to an application-level crash.
The root cause of this vulnerability lies in a combination of CWE-1287 (Improper Validation of Specified Type of Input) and CWE-754 (Improper Check for Unusual or Exceptional Conditions). The data schema for the calendar component stores user-defined event metadata in a schema-less, free-form JSON dictionary called meta.\n\nWhen writing or updating an event, the backend accepts the incoming payload without confirming that fields like alert_minutes contain numeric data types. The scheduler retrieves active events periodically and processes them within a single query result set. In this loop, the application performs a direct numerical comparison using Python's comparison operators.\n\nIf the value of alert_minutes is a string or a complex JSON object, the comparison operation (e.g., < 0) triggers an unhandled TypeError exception. Because the polling loop operates in a single thread without per-event exception wrapper blocks, any exception raised by a single event terminates the entire scheduler run, halting alert delivery for all other users on the instance.
To understand the defect, examine the vulnerable implementation within backend/open_webui/models/calendar.py where events are pulled and processed:\n\npython\n# Vulnerable scheduler code path\nasync def get_upcoming_events(...):\n events = []\n for event, tz in rows:\n model = CalendarEventModel.model_validate(event)\n # Determine per-event alert window\n alert_minutes = None\n if model.meta and 'alert_minutes' in model.meta:\n alert_minutes = model.meta['alert_minutes']\n\n if alert_minutes is not None:\n if alert_minutes < 0: # <-- TypeError raised here\n\n\nWhen an attacker supplies \"crash_the_scheduler\" as the value of alert_minutes, the condition alert_minutes is not None evaluates to true. The interpreter then executes \"crash_the_scheduler\" < 0, which raises a TypeError and crashes the routine.\n\nTo remediate this issue, the patch introduced explicit type checking on the retrieved metadata before executing any comparative arithmetic:\n\npython\n# Patched scheduler code path\nasync def get_upcoming_events(...):\n events = []\n for event, tz in rows:\n model = CalendarEventModel.model_validate(event)\n # Safe dictionary access with fallback to empty dict\n alert_minutes = (model.meta or {}).get('alert_minutes')\n # Strict type-checking restricts value to numeric types\n if not isinstance(alert_minutes, (int, float)):\n alert_minutes = None\n\n if alert_minutes is not None:\n if alert_minutes < 0:\n\n\nThe patched version uses isinstance(alert_minutes, (int, float)) to verify the type before performing the numerical comparison. Any non-numeric input is safely coerced to None, successfully isolating the scheduler from malformed metadata entries.
An attacker must have valid credentials to an account on the target Open WebUI instance with permissions to create or modify calendar events. The attack vector does not require administrator privileges, as any standard user with calendar access can trigger the vulnerability.\n\nThe attacker sends a structured HTTP POST or PUT request to the calendar endpoint, specifying a payload where meta.alert_minutes contains a non-numeric string or object. The database interface commits this entry without performing type enforcement.\n\nOnce the database is updated, the attacker waits for the periodic background scheduler to run. When the execution thread queries the newly created event, it encounters the malformed metadata. The resulting TypeError aborts the scheduler loop, effectively suppressing all notifications across the instance as long as the malicious event remains within the lookahead window.
The impact of this vulnerability is a localized, application-level Denial of Service (DoS) affecting the notification functionality of Open WebUI. It does not lead to remote code execution, database corruption, or unauthorized data exposure.\n\nHowever, in a multi-tenant corporate or educational deployment, the absolute suppression of calendar alerts can disrupt operational workflows. Users rely on these alerts to join scheduled calls, execute tasks, or manage shared resources.\n\nThe severity is rated as Medium with a CVSS v3.1 score of 4.3. The attack requires basic authenticated access (PR:L) and low complexity (AC:L), but the impact is restricted to availability (A:L) without impacting confidentiality or integrity.
The primary remediation is upgrading the Open WebUI installation to version 0.11.1 or higher, which contains the defensive patch. Administrators can pull the updated Docker image from the official repository.\n\nIf immediate patching is not feasible, administrators can apply defensive measures at the database or reverse proxy level. Running a periodic database script to sanitize or delete calendar entries with non-numeric alert_minutes parameters will prevent the scheduler from encountering the crash condition.\n\nDevelopers should note that relying on read-path coercion is a defensive-in-depth measure, but the API write-path should also be hardened. Restricting the input schema on the write-path prevents malformed JSON elements from persisting to the datastore in the first place.\n\nHere is a sequence diagram illustrating the attack flow:\n\nmermaid\ngraph LR\n A[\"Attacker\"] -- \"POST /api/v1/calendar (non-numeric alert_minutes)\" --> B[\"Open WebUI API\"]\n B -- \"Saves event directly to Database without verification\" --> C[(\"Database\")]\n D[\"Shared Scheduler Process\"] -- \"Fetches upcoming events\" --> C\n C -- \"Returns events including attacker payload\" --> D\n D -- \"Performs comparison 'string < 0'\" --> E[\"Unhandled TypeError Exception\"]\n E -- \"Crashes Background Job\" --> F[\"Instance-Wide Suppression of Alerts\"]\n
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L| Product | Affected Versions | Fixed Version |
|---|---|---|
Open WebUI Open WebUI | >= 0.9.0, < 0.11.1 | 0.11.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-1287, CWE-754 |
| Attack Vector | Network (AV:N) |
| CVSS Score | 4.3 (Medium) |
| EPSS Score | 0.00268 (18.83% percentile) |
| Impact | Denial of Service (Instance-wide alert suppression) |
| Exploit Status | PoC concept, no public exploits |
| KEV Status | Not listed in CISA KEV |
The application receives input that is expected to be of a specific type (e.g., an integer), but fails to validate that the received input actually matches that specified type before performing type-sensitive operations.
Vikunja versions 2.3.0 through 2.6.0 contain an insufficient session expiration vulnerability (CWE-613) within the WebSocket authentication handler. Although Vikunja enforces server-side session tracking and revocation for REST API routes, the WebSocket handshake handler validates cryptographic JWT signatures without querying the database session state. Consequently, revoked JWT tokens can establish new real-time WebSocket connections, and existing connections persist after session revocation.
A cross-tenant boundary breach vulnerability in Vikunja allows an authenticated user to trigger global task position recalculations across all tenant instances by creating a saved filter with an empty filter string payload.
An access revocation flaw in Vikunja allows removed collaborators to retain outbound webhooks and link shares created prior to revocation, enabling persistent exfiltration of sensitive task data.
Vikunja v2.6.0 contains a permission inheritance regression in pkg/models/project_access.go where explicit down-restrictions on sub-projects are overridden by higher parent project permissions due to MAX aggregation across project tree nodes.
An authorization bypass vulnerability in Vikunja's link share deletion handlers allows project members with Write privileges to delete Admin-tier link shares. The handler passes an unpopulated struct to the authorization check, causing the permission evaluation to fall back to default Write permissions instead of requiring Admin privileges.
Vikunja versions 2.2.0 through 2.6.0 contain a Cross-Origin Resource Sharing (CORS) misconfiguration flaw in `code.vikunja.io/api`. Default configurations permit wildcard origins for localhost (`http://127.0.0.1:*` and `http://localhost:*`) with credentialed requests (`Access-Control-Allow-Credentials: true`). Because configuring a public service URL appends to this default list rather than overriding it, production environments inadvertently trust all local origins. A local page or application on a user's machine can execute a credentialed cross-origin request to the token refresh endpoint, extract the returned JWT access token, and achieve complete account takeover.