Skip to main content

CVE-2025-15603

CVE IDCVE-2025-15603
Vendor DispositionRejected, practically unexploitable
Published2026-03-09
Issuing CNAVulDB (from a huntr.com bounty report)
Claimed SeverityLow (CVSS 3.7, CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N) per VulDB; re-scored Medium (CVSS 4.0, 6.3) by some third-party trackers

Resolved: this CVE is now rejected

The issuing CNA has withdrawn the record, so the official CVE entry now carries the REJECTED state and NVD and downstream feeds inherit it. The public record now matches Open WebUI's vendor disposition below, confirming our assessment that this was not a genuine vulnerability. There is no advisory and no affected Open WebUI release.

Timeline

DateEvent
2026-03-09CVE-2025-15603 published by VulDB, derived from a huntr.com bounty report.
2026-05-04Open WebUI files a formal dispute with the CVE Program. The dispute goes unanswered.
2026-05-05Open WebUI publishes this disposition, rejecting the report as not a security issue.
2026-06-15Open WebUI files another dispute with the CVE Program; the Secretariat directs it to the issuing CNA (VulDB), which owns the record.
2026-06-17Open WebUI contacts VulDB directly.
2026-06-18VulDB withdraws the candidate. The official CVE record state becomes REJECTED.

Our disposition rejected this report on 2026-05-05. The issuing CNA followed later: on 2026-06-18 VulDB formally withdrew the candidate, so the official CVE record now carries the REJECTED state, which NVD and downstream feeds inherit. The public record now matches the position we had already taken, and there is no advisory or affected Open WebUI release. The CNA's published rejection reads:

** REJECT ** DO NOT USE THIS CANDIDATE NUMBER. ConsultIDs: none. Reason: This candidate was withdrawn by its CNA. Further investigation showed that it was not a security issue. Notes: The vendor explains: "The 't0p-s3cr3t' default was dead code on every supported startup path: start.sh, start_windows.bat and open-webui serve all set or auto-generate WEBUI_SECRET_KEY before the backend imports env.py. It was only ever reachable by invoking uvicorn directly, which is unsupported and unsafe (the app would then sign tokens/cookies with a public, hardcoded key)."

Disclosure Pathway

No report corresponding to this CVE was filed through the project's official reporting channel (GitHub Security Advisories) prior to publication.


What Was Claimed

This CVE traces to a single huntr.com bounty report that bundled more than one concern about how WEBUI_SECRET_KEY (the value used to sign JWT session tokens) is set. Because it was not one clean claim, public trackers describe it in different and sometimes contradictory ways. Two interpretations propagated:

  1. Weak random key generation in start_windows.bat. This is the framing NVD, VulDB and most third-party trackers carry, sometimes labeled a "JWT Key Handler" flaw. The Windows startup script derives a fallback WEBUI_SECRET_KEY from the %RANDOM% shell variable, a non-cryptographic generator, so the key is claimed to be predictable enough to forge tokens.
  2. A hardcoded t0p-s3cr3t default. This is the facet the CNA's rejection note addresses. If WEBUI_SECRET_KEY were ever left unset, older code could fall back to a public constant and sign tokens with it.

The classifications follow the confusion: VulDB assigned CWE-330 at CVSS 3.1 3.7 (Low), while other trackers re-cast it as CWE-310 at CVSS 4.0 6.3 (Medium) and even labeled it remote code execution, which it is not. Neither interpretation is exploitable in a supported deployment.


Why This Is Not a Vulnerability

Open WebUI has three supported startup mechanisms: start.sh (Linux or WSL, the recommended one), start_windows.bat (Windows) and open-webui serve. Each one sets or generates WEBUI_SECRET_KEY and persists it to .webui_secret_key before the backend imports env.py, so a stable key is always in place before any token is signed. The documented production guidance, for every mechanism, is to set WEBUI_SECRET_KEY explicitly.

The start_windows.bat random-key path (interpretation 1)

This path runs only on a first run where both conditions hold:

  1. The operator has not provided WEBUI_SECRET_KEY via environment variable.
  2. No .webui_secret_key file exists on the host yet.

In that state the script builds a key by appending %RANDOM% WEBUI_SECRET_KEY_LENGTH times (default 24) and writes it to .webui_secret_key. Every later run reads from that persisted file. So the %RANDOM% path is reached at most once per host, and is bypassed entirely on every subsequent run and in any deployment where the operator set the key.

%RANDOM% returns 0 to 32767 per call from a time-seeded, non-cryptographic generator, so the produced key is weaker than one from a CSPRNG. But this is a single convenience script (its own first line recommends start.sh with WSL instead), the key is generated once and then persisted, and practical token forgery would require recovering the seed (the exact second the script first ran on that host) plus network access to test forgeries. VulDB's own Low rating reflects that. For comparison, start.sh draws from /dev/random, while open-webui serve uses Python's random.randbytes auto-seeded from system entropy; the genuinely weak source is specific to the Windows script and only on first run.

The t0p-s3cr3t default (interpretation 2)

On every supported path the key is set or generated before env.py is imported, so the hardcoded default was never reached in a supported deployment. It could only be hit by invoking uvicorn directly, which is fundamentally unsupported and is neither a documented nor a supported way to start Open WebUI. That fallback has since been removed outright: env.py now defaults WEBUI_SECRET_KEY to an empty string and treats an unset key as a hard error when authentication is enabled, so there is no silent fallback to any constant.

Applicable Security Policy Rules

  • Rule 1: Configuration options and expected setup behavior are not vulnerabilities. A first-run entropy property of an optional convenience script is a configuration concern.
  • Rule 6: The cited path manifests only in a particular first-run state and is bypassed by every documented production configuration.

That a single report bundled several distinct claims is also why the public trackers cannot agree on what this CVE even is. Under the CVE Program's own counting rules a single CVE identifier is meant to cover a single vulnerability, so a report that combines several distinct claims should not have been assigned one CVE at all. That is the direct cause of the contradictory descriptions different trackers published for this identifier, which is exactly the confusion seen here.


Impact to Users

No action required for the vast majority of deployments. If you run Open WebUI via start_windows.bat without setting WEBUI_SECRET_KEY, the generated .webui_secret_key file is adequate for typical deployments. For high-security environments, set WEBUI_SECRET_KEY explicitly to a long random value, which is the documented production guidance regardless of startup mechanism.


References

This content is for informational purposes only and does not constitute a warranty, guarantee, or contractual commitment. Open WebUI is provided "as is." See your license for applicable terms.