Vendure GraphQL Admin API Authentication Timing Attack / User Enumeration (CVE-2026-25050)
by Christbowel · 2026-07-05
- Severity
- Medium
- CVE
- CVE-2026-25050
- Category
- web
- Affected product
- Vendure (NativeAuthenticationStrategy.authenticate(), Admin GraphQL API)
- Affected versions
- Not specified in source (affects versions using the vulnerable NativeAuthenticationStrategy logic)
- Disclosed
- 2026-07-05
- Patch status
- unpatched
Tags
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-02 |
| Author / Researcher | Christbowel |
| CVE / Advisory | CVE-2026-25050 |
| Category | web |
| Severity | Medium |
| CVSS Score | Not specified in source |
| Status | PoC |
| Tags | vendure, graphql, timing-attack, user-enumeration, authentication, python, cwe-208, brute-force-enabler |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | Vendure (NativeAuthenticationStrategy.authenticate(), Admin GraphQL API) |
| Versions Affected | Not specified in source (affects versions using the vulnerable NativeAuthenticationStrategy logic) |
| Language / Platform | Python 3 PoC against a Node.js/GraphQL target |
| Authentication Required | No |
| Network Access Required | Yes |
Summary
Vendure’s NativeAuthenticationStrategy.authenticate() method looks up a user by email and returns immediately (in roughly 1-5ms) when no matching account exists, but performs a costly bcrypt password verification (roughly 200-400ms) when the account does exist. This asymmetry lets an unauthenticated attacker distinguish valid from invalid usernames purely by measuring response latency on the Admin GraphQL API’s login mutation, without needing correct credentials. The included exploit.py automates this by sending repeated authentication attempts per candidate username against a wordlist, averaging response times to classify each as existing or non-existing, and supports shuffling, randomized delays, resuming, and JSON export of results.
Vulnerability Details
Root Cause
Non-constant-time authentication logic: the code path returns early when getUserByEmailAddress() finds no user, but calls verifyUserPassword() (bcrypt hashing) only when a user is found, creating a measurable timing side channel keyed on account existence.
Attack Vector
- Attacker collects or generates a candidate list of usernames/email addresses.
- Attacker sends multiple authentication requests per candidate to the Vendure Admin API’s
/admin-api?languageCode=enendpoint, recording response latency. - Requests that consistently take ~200-400ms (bcrypt verification) are classified as existing accounts; requests returning in ~1-5ms are classified as non-existent.
- Confirmed valid usernames are exported for targeted credential-stuffing, brute-force, or phishing campaigns.
Impact
Enables reliable enumeration of valid Vendure admin/user accounts without any authentication, which materially improves the success rate and efficiency of follow-on brute-force and phishing attacks.
Environment / Lab Setup
Target: Vendure instance exposing the Admin GraphQL API (/admin-api)
Attacker: Python 3, network access to the target
Proof of Concept
PoC Script
See
exploit.pyin this folder.
| |
The script iterates the supplied wordlist, issues multiple timed authentication attempts per entry against the vulnerable endpoint, computes average response times, classifies each username as existing or non-existing based on the timing gap, and can resume interrupted scans or export results to JSON.
Detection & Indicators of Compromise
Signs of compromise:
- Elevated volume of failed login mutations on the Admin GraphQL API from a single IP or narrow IP range
- Requests spaced with unusual randomized delays consistent with evasion (
--delaystyle throttling) - Log entries showing systematic sweeps through a username/email wordlist
Remediation
| Action | Detail |
|---|---|
| Primary fix | No vendor patch confirmed as of 2026-07-05 — monitor for advisory; apply constant-time authentication logic (always perform a dummy hash verification when the user does not exist) |
| Interim mitigation | Rate-limit and add jitter/delay to the Admin API login mutation regardless of account existence; monitor for enumeration-pattern traffic |
References
Notes
Mirrored from https://github.com/Christbowel/CVE-2026-25050 on 2026-07-05.
| |