---
id: "GHSA-48c2-w96j-mv3m"
page: "https://infrastack.ai/live/GHSA-48c2-w96j-mv3m"
kind: "vulnerability"
aliases: ["GHSA-48c2-w96j-mv3m"]
title: "@better-auth/kysely-adapter: MySQL serial IDs can return another request's record"
severity: "medium"
cvss: 6.8
epss: null
exploited: false
status: "open"
category: "package"
products: [{"name": "@better-auth/kysely-adapter", "fixed": ["1.7.16"], "affected": ">= 1.5.0-beta.9, < 1.7.16", "ecosystem": "npm"}, {"name": "@better-auth/kysely-adapter", "fixed": ["1.8.0-beta.5"], "affected": ">= 1.8.0-beta.0, < 1.8.0-beta.5", "ecosystem": "npm"}, {"name": "@better-auth/drizzle-adapter", "fixed": ["1.7.16"], "affected": ">= 1.5.0-beta.9, < 1.7.16", "ecosystem": "npm"}, {"name": "@better-auth/drizzle-adapter", "fixed": ["1.8.0-beta.5"], "affected": ">= 1.8.0-beta.0, < 1.8.0-beta.5", "ecosystem": "npm"}, {"name": "better-auth", "fixed": ["1.7.16"], "affected": "< 1.7.16", "ecosystem": "npm"}, {"name": "better-auth", "fixed": ["1.8.0-beta.5"], "affected": ">= 1.8.0-beta.0, < 1.8.0-beta.5", "ecosystem": "npm"}]
ecosystems: ["npm"]
tags: ["better-auth", "cwe-362", "cwe-488", "drizzle", "kysely", "mariadb", "mysql", "node.js", "package"]
not_affected_if: ["default-id-generation", "postgresql", "sqlite"]
published_at: "2026-11-03T21:39:08+00:00"
first_seen_at: "2026-11-09T22:53:19+00:00"
updated_at: "2026-11-09T22:54:39+00:00"
sources: [{"source": "ghsa-repo", "url": "https://github.com/better-auth/better-auth/security/advisories/GHSA-48c2-w96j-mv3m", "first_seen_at": "2026-11-09T22:53:19+00:00"}]
exploit_sources: []
---

# @better-auth/kysely-adapter: MySQL serial IDs can return another request's record

Link for people: https://infrastack.ai/live/GHSA-48c2-w96j-mv3m (this .md is for agents)

On MySQL or MariaDB with generateId set to serial, the adapter read the new row's ID through a separate query that could run on a different pooled connection. A signed-in user can receive another user's session or sign-up record and act as that user.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- npm:@better-auth/kysely-adapter affected >= 1.5.0-beta.9, < 1.7.16 fixed 1.7.16
- npm:@better-auth/kysely-adapter affected >= 1.8.0-beta.0, < 1.8.0-beta.5 fixed 1.8.0-beta.5
- npm:@better-auth/drizzle-adapter affected >= 1.5.0-beta.9, < 1.7.16 fixed 1.7.16
- npm:@better-auth/drizzle-adapter affected >= 1.8.0-beta.0, < 1.8.0-beta.5 fixed 1.8.0-beta.5
- npm:better-auth affected < 1.7.16 fixed 1.7.16
- npm:better-auth affected >= 1.8.0-beta.0, < 1.8.0-beta.5 fixed 1.8.0-beta.5

## How to check

- Check the installed versions of `better-auth`, `@better-auth/kysely-adapter` and `@better-auth/drizzle-adapter` (for example `npm ls better-auth @better-auth/kysely-adapter @better-auth/drizzle-adapter`).
- Search your auth configuration for `generateId: "serial"` and confirm the database is MySQL or MariaDB.

## Fix

- `better-auth` `1.7.16` (or `1.8.0-beta.5` on the beta line)
- `@better-auth/kysely-adapter` `1.7.16` (or `1.8.0-beta.5` on the beta line)
- `@better-auth/drizzle-adapter` `1.7.16` (or `1.8.0-beta.5` on the beta line)
- If you cannot upgrade, stop using `generateId: "serial"` on MySQL; a single-connection pool does not prevent this.

## Timeline

- 2026-11-09T22:53:19+00:00 ghsa-repo https://github.com/better-auth/better-auth/security/advisories/GHSA-48c2-w96j-mv3m

## Documents

- [advisory] Maintainer's advisory: github.com https://github.com/better-auth/better-auth/security/advisories/GHSA-48c2-w96j-mv3m

## From the sources

## Am I affected?

You are affected if **all** of these are true:

- Your database is MySQL or MariaDB.
- You set `advanced.database.generateId: "serial"`.
- You use the default Kysely adapter or the Drizzle adapter with a connection pool.

You are not affected with other databases or other ID settings.

## Summary

After inserting a row, the adapter read the new ID back with a separate query. On a connection pool, that query could run on a different connection and return the ID of a row inserted by another request.

## Impact

Under ordinary concurrent load, a user who signs in can receive another user's session and act as that user. A sign-up can also return another user's record. Other requests fail with an error. The attacker cannot choose which account they receive.

## Patches

Upgrade `better-auth` and your adapter package (`@better-auth/kysely-adapter` or `@better-auth/drizzle-adapter`) to 1.7.16, or to 1.8.0-beta.5 on the beta line.

## Workarounds

If you cannot upgrade, stop using `generateId: "serial"` on MySQL. A single-connection pool does not prevent this.

## Technical details

The MySQL branch ran the insert on the pool and then read `LAST_INSERT_ID()` in a separate transaction. `LAST_INSERT_ID()` is scoped to a connection, so the second query could see another request's insert. The adapters now use the ID reported by the insert itself, and fail instead of guessing when no ID is reported.

---

_Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai_
