Better Auth: Stale sessions persist after user deletion across admin, anonymous, and SCIM flows
Am I affected?
Users are affected if all of the following are true:
- They configure
secondaryStorageonbetterAuth(...)(Redis, KV, or any external session cache). session.storeSessionInDatabaseis left unset or set tofalse(the default).- Their application's deployment uses one or more of:
- The
adminplugin and callsauth.api.removeUser(...)orauthClient.admin.removeUser(...). - The
anonymousplugin and exposes/delete-anonymous-useror relies on the after-link hook to clean up the anonymous user. - The
@better-auth/scimplugin and exposesDELETE /scim/v2/Users/:userId.
- The
If storeSessionInDatabase is true, sessions are also written to the database, and the database delete cascades; users are not affected.
Fix:
- Upgrade to
better-auth@<patched-version>or later (and@better-auth/scim@<patched-version>if they use SCIM). - If they cannot upgrade, see workarounds below.
Summary
When secondaryStorage is configured and storeSessionInDatabase is false, three user-deletion endpoints in better-auth plus one in @better-auth/scim call internalAdapter.deleteUser(userId) without first calling internalAdapter.deleteSessions(userId). The deleted user's session payload (which carries a cached user object) remains in secondary storage, and internalAdapter.findSession(token) keeps returning it as a valid session until the session TTL elapses (default 7 days).
Details
The vulnerable call sites are:
adminplugin'sremoveUser(packages/better-auth/src/plugins/admin/routes.ts:1463).anonymousplugin's self-delete endpoint (packages/better-auth/src/plugins/anonymous/index.ts:222).anonymousplugin's after-link hook (packages/better-auth/src/plugins/anonymous/index.ts:325).@better-auth/scim'sDELETE /scim/v2/Users/:userId(packages/scim/src/routes.ts:1019).
Working callers that already do the right thing: the core /delete-user self-delete and /delete-user/callback (packages/better-auth/src/api/routes/update-user.ts:551).
The fix shape extends each vulnerable caller to invoke deleteSessions(userId) before deleteUser(userId). The architectural follow-up centralizes the cleanup inside deleteUser itself or introduces a single deleteUserAndSessions orchestrator so future callers cannot regress this contract.
Patches
Fixed in better-auth@<patched-version> and @better-auth/scim@<patched-version>. All four user-deletion call sites now invoke deleteSessions(userId) before deleteUser(userId) so sessions are evicted from secondary storage at the same time the user row is removed.
Workarounds
If users cannot upgrade immediately:
- Configuration-level: set
session.storeSessionInDatabase: true. Subsequent user-delete writes reach the session table and the database cascade removes rows. Increases write volume for high-throughput sessions but eliminates the gap. - Code-level (admin path): when calling
auth.api.removeUser, also callauth.api.revokeUserSessions({ body: { userId } }), which usesdeleteSessionsinternally. - Code-level (SCIM path): wrap their SCIM provider's deprovisioning hook to call
auth.api.revokeUserSessions(...)after the SCIM DELETE. - Code-level (anonymous path): in
onLinkAccount, explicitly callinternalAdapter.deleteSessions(anonymousUser.user.id)before allowing the new session to be issued.
Impact
- Stale session validity: a deleted user's existing session cookie continues to authenticate against
getSessionFromCtxuntil the session TTL elapses (default 7 days). Within that window, the deleted user retains their pre-existing read and write surface. - SCIM-driven deprovisioning gap: organizations using SCIM to revoke offboarded employees' access do not, in fact, revoke active sessions. The deleted account remains usable for up to 7 days after deprovisioning.
Credit
Reported by @iruizsalinas.
Resources
Software afectado
Haz clic en una tecnología para ver todas sus vulnerabilidades.
| Plataforma | Paquete | Versiones vulnerables | Corregida en |
|---|---|---|---|
| Paquete de npm | better-auth | >= 0.3.4, < 1.6.11 | 1.6.11 |
| Paquete de npm | @better-auth/scim | >= 1.6.0, < 1.6.11 | 1.6.11 |
Referencias
- Vector CVSS
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:L/I:L/A:N- Debilidad (CWE)
CWE-459, CWE-613, CWE-672- Plataforma
- npm
- Paquete
better-auth, @better-auth/scim- Publicada
- 07.07.2026
- Actualizado
- 11.10.2026 10:22
Fuentes y licencias
OSV / GitHub Advisory Database - GHSA-2vg6-77g8-24mp - CC BY 4.0
Historial de vulnerabilidades: better-auth
Todas las vulnerabilidades publicadas de este paquete (Paquete de npm), de la más reciente a la más antigua. Muestra si es un fallo aislado o un paquete que hay que vigilar.
- Entradas en total
- 22
- Primera → última
- 12.2024 07.2026
- Sin corrección
- 0
- Explotada en ataques
- 0
Distribución por gravedad
- Crítica 2
- Alta 14
- Media 3
- Baja 3
Divulgaciones por año
- 2024: 1
- 2025: 8
- 2026: 13
-
Better Auth: Stale sessions persist after user deletion across admin, anonymous, and SCIM flows esta entrada
Identifica las vulnerabilidades de tu aplicación
Con la integración de DockRay y el inventario de software activado, DockRay compara las versiones notificadas de los componentes con las vulnerabilidades conocidas y avisa de las coincidencias confirmadas. La cobertura depende de la tecnología compatible y de los avisos disponibles.