The vulnerability lies in the fact that SillyTavern did not invalidate existing user sessions after a password change or recovery. This allowed an attacker with a stolen session cookie to maintain access to the user's account even after the user had changed their password. The root cause was the stateless nature of the sessions, which were stored entirely in client-side cookies without a server-side mechanism for revocation.
The fix, introduced in version 1.18.0, implements a session versioning system. A new function, getAccountVersion, generates a version tag based on the user's handle, password hash, and salt. This version tag is stored in the session cookie upon login, password change, and password recovery.
A middleware, setUserDataMiddleware, is now executed on every authenticated request. This middleware compares the version tag in the session cookie with the current version tag of the user account. If they do not match, it means the user's credentials have changed (e.g., a password update), and the session is invalidated, forcing a re-login.
The vulnerable functions are the ones that handle password changes but failed to invalidate sessions. The analysis of the patch identified two such functions:
- The anonymous function handling the
POST /api/users/change-password route in src/endpoints/users-private.js.
- The anonymous function handling the
POST /api/users/recover-step2 route in src/endpoints/users-public.js.
These functions were modified in the patch to update the session with the new account version, thus ensuring that any other sessions with an older version become invalid. The setUserDataMiddleware is the enforcement point for this new security measure.