Jul 7, 2026·5 min read·9 visits
Better Auth failed to evict cached sessions from secondary storage (e.g., Redis) when deleting users via admin, anonymous, or SCIM endpoints. Deleted users could continue accessing the system with active cookies for up to 7 days.
A critical session persistence vulnerability exists within the Better Auth framework when configured to use external secondary storage (such as Redis or Cloudflare KV) with default database options. Due to four incomplete user-deletion code paths, active user sessions are not evicted from secondary storage caches during deletion events. As a result, deleted users retain full system access via their pre-existing session cookies until the Session Time-To-Live (TTL) expires.
The Better Auth ecosystem utilizes an abstraction layer to manage user registration, authentication, and session handling. To optimize session verification latency, developers frequently deploy a double-tier storage strategy. In this architecture, relational databases host long-term user records, while memory-efficient 'secondaryStorage' systems (such as Redis or Cloudflare KV) handle active session tokens.
By default, the session.storeSessionInDatabase configuration parameter is set to false. When configured in this manner, session data resides exclusively in secondary memory-based storage. In database-centric configurations, relational foreign-key cascading deletes automatically eliminate active session rows when a parent user row is deleted. However, when sessions reside exclusively in cache tiers, session eviction must be explicitly handled by application-level logic.
This vulnerability stems from a logical discrepancy in four separate user-deletion handlers. While core self-deletion routes safely trigger the required two-stage cleanup sequence, the Admin, Anonymous, and SCIM plugin endpoints execute the database-level user deletion without purging the active session cached inside the secondary storage system. This allows unauthorized API access via orphaned sessions.
The underlying cause is categorized under CWE-613 (Insufficient Session Expiration) and CWE-459 (Incomplete Cleanup). The Better Auth database adapter interface exposes two key operations: internalAdapter.deleteUser(userId) and internalAdapter.deleteSessions(userId). In standard deployment topologies using external Key-Value stores, these endpoints must be chained sequentially during deletion routines.
An investigation of the codebase reveals that four operational endpoints failed to orchestrate this chain. Specifically, the framework invoked the database layer to drop the user record but completely bypassed session revocation inside the cache. Because the external session store lacks transactional integrity with the main database, the session token remains active inside the Redis cache.
When a request containing a stale cookie reaches the authentication middleware, getSessionFromCtx queries the secondary storage via internalAdapter.findSession(token). Because the cached session is not deleted, the validation checks succeed. The framework reconstructs a valid user session context without referencing the primary database, permitting unauthorized read/write access until the cache item reaches its natural expiration (TTL), which defaults to 7 days.
An analysis of the vulnerable code paths demonstrates the implementation gap. In the Admin plugin (packages/better-auth/src/plugins/admin/routes.ts), the removeUser API route executed user deletion directly without clearing active cache entries.
// VULNERABLE IMPLEMENTATION (routes.ts)
const removeUser = createAuthRoute("/admin/remove-user", {
method: "POST",
// ... validation schema
}, async (ctx) => {
const { userId } = ctx.body;
// Missing session eviction step
await ctx.context.internalAdapter.deleteUser(userId);
return ctx.json({ success: true });
});The patched version integrates explicit, blocking session revocation prior to deleting user relational rows. This prevents orphaned session records from residing in secondary memory structures.
// PATCHED IMPLEMENTATION (routes.ts)
const removeUser = createAuthRoute("/admin/remove-user", {
method: "POST",
// ... validation schema
}, async (ctx) => {
const { userId } = ctx.body;
// Explicitly evict cached sessions first to guarantee cleanup
await ctx.context.internalAdapter.deleteSessions(userId);
await ctx.context.internalAdapter.deleteUser(userId);
return ctx.json({ success: true });
});This same programmatic deficiency was present across three other handlers. In @better-auth/scim (routes.ts), the SCIM deprovisioning endpoint DELETE /scim/v2/Users/:userId deleted user profiles but left their enterprise sessions intact. Additionally, within the Anonymous plugin, both the /delete-anonymous-user route and the post-link account hook failed to evict temporary sessions, leaving unauthenticated persistent endpoints exposed.
Exploiting this flaw does not require active technical bypasses or complex payload payloads. Instead, it relies on timing and state discrepancies during standard account deprovisioning sequences. The primary threat scenario involves insider threat actors, compromised accounts, or deprovisioned employees.
To demonstrate this flow, consider an enterprise setting using SCIM synchronization. An identity provider detects a terminated employee and issues an automated SCIM deletion request. The application processes the delete operation successfully, removing the database record. However, because the employee's browser has an active session cookie, the employee can continue to query internal API endpoints. The underlying cached session remains untouched, authorizing access to confidential resources until the session TTL expires.
The security implications of this session persistence vulnerability are significant, especially within enterprise environments. A CVSS v3.1 base score of 3.8 (Low) is assigned primarily due to the privileges required to trigger deletion flows (e.g., an Administrator or Identity Provider). However, the actual impact on confidentiality and integrity can be high depending on the application context.
If a malicious insider is terminated, or if an administrator deletes a compromised user account to contain an ongoing incident, the containment will fail. The attacker will maintain access to operational APIs and database records. The vulnerability also directly undermines compliance standards (such as SOC 2 or ISO 27001) that mandate immediate, absolute termination of logical access upon employee deprovisioning.
The primary resolution is to upgrade all dependencies to the patched version. The maintainers resolved these session lifecycle bugs in the official v1.6.11 release. Security teams should perform immediate package updates across affected microservices.
In scenarios where immediate upgrades are blocked by regression testing pipelines, developers can apply targeted database configuration changes. Setting session.storeSessionInDatabase to true acts as a highly effective workaround. This transfers session states to the primary database, where cascading foreign-key rules enforce session destruction at the schema layer.
Alternatively, custom middleware or wrappers around user-deletion tasks can explicitly invoke session revocation via auth.api.revokeUserSessions prior to calling deletion methods. For the Anonymous plugin, implementing manual token clearing inside the onLinkAccount lifecycle hook prevents leftover credentials from persisting.
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
better-auth Better Auth | >= 0.3.4, < 1.6.11 | 1.6.11 |
@better-auth/scim Better Auth | >= 1.6.0, < 1.6.11 | 1.6.11 |
| Attribute | Detail |
|---|---|
| Vulnerability ID | GHSA-2vg6-77g8-24mp |
| CWE ID | CWE-613, CWE-459, CWE-672 |
| Attack Vector | Network |
| CVSS v3.1 Score | 3.8 (Low) |
| Exploit Status | Conceptual / Logic Defect |
| Remediation Status | Patched in v1.6.11 |
The application does not invalidate the session cache inside secondary storage when the corresponding user account is deleted.
An authentication bypass in the SiYuan personal knowledge management system before version 3.7.0 exposes a dynamic icon rendering endpoint. This endpoint processes client-supplied Go template directives. By submitting a crafted request, an unauthenticated remote attacker can leverage registered database template functions to execute arbitrary read-only SQL queries and exfiltrate workspace contents.
CVE-2026-54069 is a critical authentication bypass vulnerability in the SiYuan Note personal knowledge management system. The flaw is located in the HTTP server's middleware handling API authorization, which unconditionally trusts requests carrying a 'chrome-extension://' scheme in the Origin HTTP header, granting administrative access without validating API tokens.
CVE-2026-54089 is a critical authentication bypass vulnerability in File Browser affecting instances configured with proxy-based authentication. An unauthenticated remote attacker with direct network access can impersonate arbitrary users or register new accounts by spoofing configured HTTP headers.
The malicious Cargo package 'exploration' was uploaded to the crates.io registry. During compilation or package import, the crate executes code designed to establish an outbound TCP/HTTP connection, download an external second-stage binary, and execute the binary locally on the host machine. This creates an unauthenticated remote code execution vector impacting developer environments and continuous integration pipelines.
CVE-2026-54088 is a critical command injection vulnerability in File Browser prior to version 2.63.6. When Hook Authentication is enabled, the application interpolates unsanitized credentials into a shell command, allowing unauthenticated remote code execution.
An authenticated remote code execution vulnerability exists in NotrinosERP (versions up to and including 1.0.0) within the Human Resource Management (HRM) module. Users with employee management permissions can upload arbitrary file types, including PHP scripts, which are written directly to a web-accessible directory. This allows for arbitrary code execution in the context of the web-server user.