GHSA-2r4p-jpmg-48f4
CRITICALGHSA-2r4p-jpmg-48f4 is a critical-severity (CVSS 9.1) Improper Authentication vulnerability in open-webui. O3 Security confirms whether GHSA-2r4p-jpmg-48f4 is actually reachable in your code before you act, and blocks exploitation at runtime until you patch.
Open WebUI has an LDAP Empty Password Authentication Bypass
Real-World Exposure
open-webuiReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.
Description
LDAP Empty Password Authentication Bypass
Affected Component
LDAP authentication endpoint:
backend/open_webui/routers/auths.py(lines 468-477, user bind with empty password)backend/open_webui/models/auths.py(lines 58-60,LdapFormmodel)
Affected Versions
Current main branch (commit 6fdd19bf1) and likely all versions with LDAP authentication support.
Description
The LDAP authentication endpoint does not validate that the submitted password is non-empty before performing a Simple Bind against the LDAP server. Per RFC 4513 Section 5.1.2, a Simple Bind with a valid DN and an empty password constitutes an "unauthenticated simple authentication" — many LDAP servers (including OpenLDAP in default configuration and some Active Directory setups) return success (resultCode 0) for this operation.
The LdapForm Pydantic model accepts password: str with no minimum length constraint, so an empty string passes validation. The subsequent Connection.bind() call succeeds on vulnerable LDAP servers, and the application issues a full session token for the target user.
# models/auths.py:58-60 — no min_length on password
class LdapForm(BaseModel):
user: str
password: str
# auths.py:469-477 — empty password reaches LDAP bind
connection_user = Connection(
server,
user_dn,
form_data.password, # can be ""
auto_bind='NONE',
authentication='SIMPLE',
)
if not await asyncio.to_thread(connection_user.bind):
raise HTTPException(400, 'Authentication failed.')
# If bind succeeds (which it does with empty password on many servers),
# execution continues and a full session token is issued
CVSS 3.1 Breakdown
| Metric | Value | Rationale |
|---|---|---|
| Attack Vector | Network (N) | Exploited remotely via the LDAP login endpoint |
| Attack Complexity | Low (L) | Single request with an empty password field |
| Privileges Required | None (N) | No prior authentication needed |
| User Interaction | None (N) | No victim interaction required |
| Scope | Unchanged (U) | Impact within the application's authentication boundary |
| Confidentiality | High (H) | Full access to victim's account data — chats, files, API keys, settings |
| Integrity | High (H) | Can modify victim's data, settings, send messages as victim |
| Availability | None (N) | No direct denial of service |
Attack Scenario
- LDAP authentication is enabled on the Open WebUI instance.
- The underlying LDAP server accepts unauthenticated simple binds (OpenLDAP default, some AD configs).
- Attacker sends:
POST /api/v1/auths/ldap {"user": "admin_username", "password": ""} - The app DN bind succeeds normally (line 366), finds the target user via LDAP search.
- The user bind (line 469-477) sends a Simple Bind with the target's DN and an empty password.
- The LDAP server returns success for the unauthenticated bind.
authenticate_user_by_email(line 507) issues a full session token for the target user.- Attacker has complete access to the victim's account.
Impact
- Complete authentication bypass — any LDAP user account can be taken over without knowing the password
- Includes admin accounts if they authenticate via LDAP
- No rate limiting on the LDAP endpoint (unlike the password signin endpoint)
- Zero interaction required from the victim
Preconditions
- LDAP must be enabled (
ENABLE_LDAP=True, disabled by default) - The LDAP server must accept unauthenticated simple binds with empty passwords (OpenLDAP default behavior, configurable on AD)
- Attacker must know a valid LDAP username
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐍PyPI | open-webui | all versions | 0.9.0 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for open-webui. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.
Fix
Update open-webui to 0.9.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-2r4p-jpmg-48f4 is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 pinpoints whether GHSA-2r4p-jpmg-48f4 is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.
Tailored to GHSA-2r4p-jpmg-48f4. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Frequently Asked Questions
Is GHSA-2r4p-jpmg-48f4 in your dependencies?
O3 detects GHSA-2r4p-jpmg-48f4 across PyPI dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.