Vendure vulnerable to timing attack that enables user enumeration in NativeAuthenticationStrategy
Description
Vendure is an open-source headless commerce platform. Prior to version 3.5.3, the NativeAuthenticationStrategy.authenticate() method is vulnerable to a timing attack that allows attackers to enumerate valid usernames (email addresses). In packages/core/src/config/auth/native-authentication-strategy.ts, the authenticate method returns immediately if a user is not found. The significant timing difference (~200-400ms for bcrypt vs ~1-5ms for DB miss) allows attackers to reliably distinguish between existing and non-existing accounts. Version 3.5.3 fixes the issue.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
@vendure/corenpm | < 3.5.3 | 3.5.3 |
Affected products
1Patches
17f0c5556ecddMerge commit from fork
1 file changed · +11 −0
packages/core/src/config/auth/native-authentication-strategy.ts+11 −0 modified@@ -17,6 +17,14 @@ export interface NativeAuthenticationData { export const NATIVE_AUTH_STRATEGY_NAME = 'native'; +/** + * A pre-computed bcrypt hash used for dummy password checks to prevent timing attacks. + * When a user is not found, we still perform a hash comparison against this dummy value + * to ensure consistent response times regardless of whether the user exists. + * This mitigates user enumeration via timing analysis. + */ +const DUMMY_PASSWORD_HASH = '$2b$12$SFfIOqrqph9N4yvWLtbqteiV5C6GEN/YOumGLryDDbHeMLtSQo4/6'; + /** * @description * This strategy implements a username/password credential-based authentication, with the credentials @@ -53,6 +61,9 @@ export class NativeAuthenticationStrategy implements AuthenticationStrategy<Nati async authenticate(ctx: RequestContext, data: NativeAuthenticationData): Promise<User | false> { const user = await this.userService.getUserByEmailAddress(ctx, data.username); if (!user) { + // Perform a dummy password check to prevent timing attacks that could + // be used to determine whether a user account exists. + await this.passwordCipher.check(data.password, DUMMY_PASSWORD_HASH); return false; } const passwordMatch = await this.verifyUserPassword(ctx, user.id, data.password);
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-6f65-4fv2-wwchghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-25050ghsaADVISORY
- github.com/vendurehq/vendure/commit/7f0c5556ecddb44a5d5208677a45fdd5923b0cc9ghsaWEB
- github.com/vendurehq/vendure/releases/tag/v3.5.3ghsax_refsource_MISCWEB
- github.com/vendurehq/vendure/security/advisories/GHSA-6f65-4fv2-wwchghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.