The Better Auth team has shipped a coordinated security release addressing 12 advisories across authentication bypass, account takeover, session revocation, authorization checks, and billing. Better Auth 1.7.16 and 1.8.0-beta.5 are available on npm now. One advisory, in @better-auth/expo, is rated critical (CVSS 9.1).
Vercel created new rules to address these vulnerabilities and deployed them to the Vercel WAF to automatically protect all projects hosted on Vercel at no cost. No configuration changes or redeploys are required. However, do not rely on the WAF for full protection. Immediate upgrades to a patched version are required, and some applications also require additional key rotation, cleanup, and configuration steps.
Copy link to headingRequired action
Upgrade better-auth and every @better-auth/* package you use to 1.7.16, or to 1.8.0-beta.5 on the beta line. Read the advisories for the plugins you use, since some fixes add a configuration step, such as listing trusted origins. If your server registers the expo() plugin, rotate your application secret after upgrading (see Impact on Vercel deployments).
Copy link to headingImpact
The release addresses the following advisories. Each advisory lists the affected versions and the conditions that decide whether you are affected.
Copy link to headingCritical
Copy link to headingExpo
- Authorization proxy can sign values it did not issue
- Fixed in: 1.7.16, 1.8.0-beta.5
- After upgrading: Rotate the application secret if the vulnerable Expo endpoint was reachable. If SSO sign-in stops working, add the identity provider's origin to
trustedOrigins.
Copy link to headingHigh
Copy link to headingPhone number
- Phone numbers can be claimed before they are verified
- Fixed in: 1.7.16, 1.8.0-beta.5
- After upgrading to 1.7.16: Remove previously saved phone numbers whose verification was never completed. Those users will need to add their numbers again. Version 1.8.0-beta.5 also checks account ownership before verifying a pending number, including numbers stored before the upgrade.
Copy link to headingElectron
- Desktop sign-in can return the server secret and skip two-factor
- Fixed in: 1.7.16, 1.8.0-beta.5
- After upgrading: If an affected version of the Electron server plugin has been running, assume the authentication secret and all configured social provider client secrets were exposed. Rotate all of them; the upgrade cannot reverse an earlier disclosure.
Copy link to headingMedium
Copy link to headingCore
- Email-change links stay valid after the address changes hands
- Fixed in: 1.7.16, 1.8.0-beta.5
- OAuth sign-in can treat an unverified provider email as verified
- Fixed in: 1.7.16, 1.8.0-beta.5
- MySQL serial IDs can return another request's record (
@better-auth/kysely-adapterand@better-auth/drizzle-adapter)- Fixed in: 1.7.16, 1.8.0-beta.5
- Revoked sessions can stay valid with secondary storage or the cookie cache
- Fixed in: 1.7.16, 1.8.0-beta.5
Copy link to headingEmail OTP
- Email OTP attempt limit can be raced and codes are loosely bound to addresses
- Fixed in: 1.7.16, 1.8.0-beta.5
- After upgrading: Users with pending email changes must request fresh codes; codes issued before the upgrade no longer work.
Copy link to headingAdmin
- Admin roles with
user:updatecan change another user's phone number- Fixed in: 1.7.16, 1.8.0-beta.5
- Configuration: For custom access controls, include
set-phonein the permission statements and assignuser:set-phoneonly to roles authorized to change users' phone numbers. The default admin role already includes this permission.
Copy link to headingOrganization
- Organization admins can invite an owner with a padded role name
- Fixed in: 1.7.16, 1.8.0-beta.5
- After upgrading: Audit existing invitations and memberships for role strings affected by whitespace trimming, and review owners invited by those members. Do not automatically trim stored roles: this can activate unintended owner privileges.
Copy link to headingStripe
- Billing actions can target another customer's Stripe account
- Fixed in: 1.7.16, 1.8.0-beta.5
- After upgrading: Find Stripe customer IDs associated with multiple users and verify those associations against the customer's
metadata.userIdin Stripe. Check organization records too if organization billing is enabled. The patch does not repair previously stored associations.
Copy link to headingLow
Copy link to headingPasskey
- Passkey verification does not enforce origin or user verification
- Fixed in: 1.7.16, 1.8.0-beta.5
- Configuration: Set an explicit
originif you configurerpIDand that domain is covered by a wildcard inbaseURL.allowedHosts.
Copy link to headingImpact on Vercel deployments
Vercel deployed WAF rules that block the exploitable request patterns for the advisories that can be identified at the request layer, including the critical @better-auth/expo issue. Logic-level issues, such as session revocation with secondary storage, cannot be blocked by a WAF and are fixed only by upgrading.
WAF rules reduce exposure but do not replace patching. The WAF blocks new exploit attempts but cannot invalidate signatures forged before the rules were deployed, so applications using the expo() plugin should upgrade and rotate their application secret.
Copy link to headingResolution
Patching is required for complete mitigation, and some applications also require additional key rotation, cleanup, and configuration steps.
Upgrade every Better Auth package together. Packages released separately, such as @better-auth/expo, @better-auth/electron, @better-auth/passkey, @better-auth/stripe, and @better-auth/kysely-adapter, ship with the same version numbers as better-auth.
For applications on the 1.7.x line:
npm install better-auth@1.7.16
For applications on the 1.8.0 beta line:
npm install better-auth@1.8.0-beta.5
If Expo sign-in through an SSO identity provider fails after upgrading, add the identity provider's origin to trustedOrigins.
If you can't upgrade immediately and you don't use Expo social sign-in, remove the expo() server plugin. Otherwise, block requests to /expo-authorization-proxy (under your auth base path) whose authorizationURL carries a state value that is not exactly 32 characters from A-Z, a-z, 0-9, -, and _. This workaround blocks the signing problem only.
Copy link to headingAffected versions
| Package | Affected | Upgrade to |
|---|---|---|
better-auth 1.7.x and earlier | <1.7.16 | 1.7.16 |
better-auth 1.8.0-beta.x | >=1.8.0-beta.0, <1.8.0-beta.5 | 1.8.0-beta.5 |
@better-auth/expo | >=1.4.0-beta.6, <1.7.16 or >=1.8.0-beta.0, <1.8.0-beta.5 | 1.7.16 or 1.8.0-beta.5 |
Other @better-auth/* packages | See each advisory | 1.7.16 or 1.8.0-beta.5 |
Copy link to headingFixed in
Better Auth: 1.7.16, 1.8.0-beta.5
All @better-auth/* packages: same versions