Better Authに脆弱性12件、1.7.16へ更新を【2026年11月】
ログイン機能を自前で作るとき、TypeScript の認証フレームワーク「Better Auth」を使っている人も多いのではないでしょうか。
2026年11月3日、Better Auth は「v1.7.16」と「v1.8.0-beta.5」を公開し、12件の脆弱性を修正しました。 公式ブログでは、深刻度が Critical(緊急)1件・High(重要)2件・Medium 8件・Low 1件 と示されています。

緊急の1件は Expo 向けのプラグイン(@better-auth/expo) の問題で、条件がそろうと メールアドレスを知っているだけで他人としてサインインできる 内容です。ログインという守りの要を担うライブラリだけに、使っている機能を確かめて、早めに上げておきたいリリース と言えます。
この記事はこんな人向けです
- Better Auth で Web アプリやモバイル・デスクトップアプリのログインを作っている
- Expo・Electron・電話番号・Stripe などのプラグインを使っていて、自分が対象か知りたい
- 1.7.16 へのアップデートの手順と、更新後に必要な設定の変更を確かめたい
Better Authのセキュリティリリースとは?一言でまとめると
「プラグインごとの穴をまとめて塞いだ、12件のセキュリティ修正」 です。
| 項目 | 内容 |
|---|---|
| 公開日 | 2026年11月3日(npm での公開は日本時間11月4日の早朝) |
| 修正版 | 1.7.16(安定版)/1.8.0-beta.5(ベータ版) |
| 修正した問題 | 12件(GitHub Security Advisories) |
| 深刻度 | Critical 1件・High 2件・Medium 8件・Low 1件 |
| CVE 番号 | 各アドバイザリーには 記載なし(2026年11月4日時点) |
| 悪用の報告 | 公式ブログ・各アドバイザリーに 記載なし |
| やること | better-auth と @better-auth/* をすべて同じ修正版へ |
公式ブログは、Vercel にデプロイしたアプリには WAF(Web アプリケーションファイアウォール)による保護を適用済み としています。ただし同時に、Vercel でも最新版への更新を勧めています。

そもそもBetter Authとは:プラグインで機能を足す認証フレームワーク
Better Auth は、公式ドキュメントで 「TypeScript 向けの、フレームワークを問わない認証・認可のフレームワーク」 と説明されています。npm install better-auth で入れて使い、2段階認証・パスキー・マルチテナント・マルチセッション などを プラグインの仕組みで足せる と紹介されています。
今回のアドバイザリーにも、電話番号・2段階認証・パスキー・組織・Stripe・管理者 といったプラグインの名前が並んでいます。Expo や Electron のアプリ向けには、@better-auth/expo・@better-auth/electron のような別配布のパッケージがあります。
今回の12件も、ほとんどが 特定のプラグインや設定を使っているときだけ 当てはまります。逆に言えば、どのプラグインを使っているかで、急ぎ度が変わる ということです。
Node.js のバージョン選びや更新の考え方は、こちらで整理しています。

発表の概要:12件の一覧
公式ブログとアドバイザリーをもとに、12件を深刻度順にまとめます。CVSS は各アドバイザリーに載っている v3.1 の値 です。
| 深刻度 | 対象 | 内容 | CVSS |
|---|---|---|---|
| Critical | Expo | 認可プロキシが、自分で発行していない値に署名してしまう | 9.1 |
| High | 電話番号 | 確認前の電話番号を、他人が自分のアカウントに登録できる | 8.1 |
| High | Electron | デスクトップのサインインでサーバーの秘密鍵が返り、2段階認証も飛ばせる | 8.1 |
| Medium | 本体 | メール変更のリンクが、アドレスの持ち主が変わった後も有効 | 6.4 |
| Medium | 本体 | OAuth で、未確認のメールアドレスを確認済みとして扱う | 5.9 |
| Medium | Kysely アダプター | MySQL の連番 ID で、別のリクエストのレコードが返る | 6.8 |
| Medium | 本体 | 取り消したセッションが、条件によって使い続けられる | 4.2 |
| Medium | メール OTP | 試行回数の上限を同時アクセスで超えられる | 4.8 |
| Medium | 管理者 | user:update を持つロールが、他人の電話番号を変えられる | 6.8 |
| Medium | 組織 | 空白を付けたロール名で、owner を招待できる | 4.9 |
| Medium | Stripe | 別の顧客の Stripe アカウントに請求操作ができる | 5.9 |
| Low | パスキー | オリジンと本人確認(PIN・生体認証)を強制していない | 3.1 |

12件すべてが 1.7.16 と 1.8.0-beta.5 で修正済み です。各アドバイザリーには、影響するバージョンと「どんな設定なら対象か」が書かれています。
深刻度が高い3件で何が起きるのか
① Expoプラグイン:メールアドレスだけで他人としてサインイン(Critical)
サーバーで expo() プラグインを登録しているアプリが対象 です(@better-auth/expo 1.4.0-beta.6 以降)。
アドバイザリーによると、認証されていない攻撃者が、ユーザーのメールアドレスを知っているだけで、そのユーザーとしてサインインしメールアドレスまで変えられます。 ユーザー側の操作は必要ありません。セッションのクッキーキャッシュを有効にしていると、ユーザー ID だけで成りすませる とされています。
ほかにも、任意の外部サイトへのリダイレクト(フィッシングに使われうる)と、myapp://* のような ワイルドカードの trustedOrigins が想定外の URL に一致する 問題も含まれます。
更新後の注意点として、エンドポイントに外から届く状態だったなら、アプリのシークレットを入れ替える よう求めています。修正前に発行された署名は、シークレットを変えるまで有効なままだからです。
② 電話番号プラグイン:確認前の番号を他人が先に登録(High)
電話番号プラグインを使うアプリが対象 です(0.4.12-beta.7 以降)。
攻撃者が 被害者の電話番号を、自分のアカウントに未確認のまま保存 できました。その後、被害者が自分の電話に届いた OTP(ワンタイムパスワード)でサインインすると、攻撃者のアカウントに入ってしまい、そこに入力したデータが攻撃者に見られるおそれ があります。
アドバイザリーは、OTP を盗んだり、被害者自身のアカウントに入ったりするものではない とも書いています。1.7.16 に上げた後は、更新前に保存された未確認の電話番号を消す 作業が必要です。
③ Electronプラグイン:サーバーの秘密鍵が返り、2段階認証も回避(High)
サーバーで electron() プラグインを登録しているアプリが対象 です(@better-auth/electron 1.5.0-beta.12 以降)。
サインインできる利用者なら誰でも、サーバーの認証シークレットと、ソーシャルログインのクライアントシークレットを受け取れました。 認証シークレットがあれば、メールアドレスを知っている別のユーザーのセッションを作れます。
さらに twoFactor() も使い、plugins の並びで electron() が twoFactor() より前にある と、パスワードを知っている攻撃者が 2段階認証なしでセッションを得られました。
この件は 更新するだけでは済みません。 脆弱なバージョンで動いていたなら、認証シークレットとすべてのソーシャルプロバイダーのクライアントシークレットを、漏れたものとして入れ替える よう求められています。
残り9件:使っている機能しだいで対象になる
Medium と Low の9件は、特定の設定や組み合わせのときだけ 当てはまるものがほとんどです。
| 対象 | こんな使い方なら要注意 |
|---|---|
| メール変更(本体) | メール変更を有効 にし、手放されたアドレスを別の人が登録できる |
| OAuth(本体) | email_verified を 文字列で返すプロバイダー(例: Amazon Cognito)、genericOAuth()、Zoom の一部オプション |
| Kysely / Drizzle アダプター | MySQL・MariaDB で generateId を “serial” にしている |
| セッション(本体) | secondaryStorage や cookieCache を使っている |
| メール OTP | emailOTP() を使っている(メール変更・MySQL の照合順序で追加の問題) |
| 管理者 | admin と電話番号を併用し、完全な管理者以外に user:update を与えている |
| 組織 | owner 以外のロールが招待を作れる(既定では admin が作れる) |
| Stripe | stripe() を使っている(請求への影響は subscription.enabled のとき) |
| パスキー | userVerification を “required” にしている、または rpID が他のサブドメインを含む |
中でも気をつけたいのは MySQL の連番 ID の件 です。同時アクセスがあると、サインインした人が別のユーザーのセッションを受け取ることがあります(攻撃者が相手を選ぶことはできません)。
Stripe の件 では、他の顧客の Stripe の顧客 ID を知っているサインイン済みの利用者 が、その顧客の請求ポータルを開けました。請求書の閲覧や サブスクリプションの解約 までできたとされています。
影響を受けるバージョンと条件
各アドバイザリーの「影響するバージョン」は、どれも 安定版は 1.7.16 より前、ベータ版は 1.8.0-beta.0〜beta.4 で終わっています。始まりは問題ごとに違います。
| 問題 | 影響が始まるバージョン |
|---|---|
| Expo(Critical) | @better-auth/expo 1.4.0-beta.6 から |
| 電話番号(High) | better-auth 0.4.12-beta.7 から |
| Electron(High) | @better-auth/electron 1.5.0-beta.12 から |
| OAuth のメール確認 | 0.4.9 から |
| セッションの取り消し | 0.8.1-beta.5 から(cookieCache との組み合わせは 1.6.25 から) |
| メール OTP | 1.3.7 から |
| メール変更 | 1.4.0 から |
| 組織 | 1.5.5 から |
| Kysely / Drizzle アダプター | 1.5.0-beta.9 から |
| 管理者 | 1.7.16 より前のすべて |
| Stripe | @better-auth/stripe 1.2.0-beta.18 から |
| パスキー | @better-auth/passkey 1.4.0-beta.16 から(本体の組み込み版 1.2.0-beta.18〜1.3.x は 1.4.0 で修正済み) |
公式ブログが示している修正版は、1.7.16(1.7 系)と 1.8.0-beta.5(ベータ)の2つだけ です。
バージョンの確認と更新方法
① いまのバージョンを確認する
プロジェクトのフォルダで、次のコマンドを実行します。npm の公式ドキュメントによると、npm ls は 入れ子の依存も含めて、インストールされているバージョンを表示 します。
npm ls better-auth
npm ls @better-auth/expo @better-auth/electron @better-auth/passkey @better-auth/stripe
1.7.16 より前(ベータを使っているなら 1.8.0-beta.5 より前)なら更新の対象です。
② 本体とプラグインをまとめて更新する
公式ブログは、better-auth と @better-auth/* のパッケージをすべて同じ修正版に上げる よう案内しています。npm なら、使っているパッケージを並べて指定します。
npm install better-auth@1.7.16 @better-auth/expo@1.7.16
@better-auth/expo の部分は、プロジェクトに入っているパッケージ(electron・passkey・stripe・kysely-adapter など)に置き換えます。ベータ版を使っている場合は 1.8.0-beta.5 です。クライアントとサーバーを分けている構成では、両方のプロジェクトで更新 します。

③ 更新後にやること
一部の修正は、更新に加えて作業や設定の変更が必要 です。使っているものだけ確認してください。
- Expo: エンドポイントに外から届いていたなら アプリのシークレットを入れ替え。SSO 経由のサインインが失敗したら、その IdP のオリジンを trustedOrigins に追加
- Electron: 脆弱なバージョンで動いていたなら 認証シークレットとソーシャルのクライアントシークレットを入れ替え
- 電話番号: 更新前に保存された 未確認の電話番号を消す(サインアップ・サインインで phoneNumber を送ると拒否されるようになる)
- 管理者: 独自のアクセス制御を使っているなら、statements に set-phone を追加
- Stripe: 顧客 ID は update-user では設定できなくなるので データベースアダプター経由で書く。同じ顧客 ID が複数のユーザーに付いていないか を確かめる
- 組織: 既存の招待・メンバーに 空白入りのロール がないか点検する
- メール OTP: 更新前に送った メール変更のコードは送り直し
- パスキー: rpID と baseURL.allowedHosts のワイルドカードを使っているなら origin を明示。userVerification の “required” は 認証時にも効く ようになる
1.8.0-beta.5 には、API キーのセッションを一部の操作で拒否する など、ベータ版だけの破壊的変更もあります。ベータ版を使っている場合は、リリースノートも確認しておきましょう。
すぐ更新できないときの回避策
各アドバイザリーには、更新までのつなぎとして次の回避策が載っています。どれも一時しのぎで、更新の代わりにはなりません。
| 対象 | 公式の回避策 |
|---|---|
| Expo | Expo のソーシャルサインインを使わないなら expo() を外す |
| Electron | electron() を外す(デスクトップのサインインは止まる) |
| 電話番号 | 未確認の電話番号を消し、サインアップで phoneNumber を受け付けない |
| Kysely / Drizzle | MySQL で generateId: “serial” をやめる |
| セッション | 取り消しをすぐ効かせたいなら cookieCache を切る |
| メール変更 | ユーザーによるメール変更を止める |
| 管理者 | 不要なロールから user:update を外す |
| 組織 | owner 以外のロールから 招待の権限を外す |
パスキーの件は、更新以外の回避策は確認されていない とアドバイザリーに書かれています。
IT Picks的な所感
今回の12件は、「プラグインを足すほど便利になる」作りの裏側で、プラグインごとの確認が甘かった部分をまとめて直したリリース だと受け止めています。本体だけでなく、Expo・Electron・Stripe・パスキーと 別配布のパッケージにも修正が及んでいる のが特徴です。
特に Electron の件は、更新しても漏れたシークレットは戻らない ため、入れ替えの手間がかかります。ログインまわりは 「バージョンを上げて終わり」になりにくい ので、使っているプラグインの一覧を手元に持っておくと対応が早くなると思います。
公式ブログが フロンティア AI モデルを使ったセキュリティレビュー に触れている点も目を引きます。オープンソースの脆弱性が見つかるペースは今後も上がりそうで、pgAdmin 4 の15件の修正や WordPress 7.1.4 のセキュリティリリースと同じく、すぐ更新できる体制づくり が大事になってきます。
まとめ
Better Auth のセキュリティリリースのポイントをまとめます。
- 修正版:1.7.16(安定版)/1.8.0-beta.5(ベータ版)
- 公開日:2026年11月3日
- 修正した問題:12件(Critical 1・High 2・Medium 8・Low 1)
- 緊急:Expo プラグイン(メールアドレスだけで他人としてサインイン、CVSS 9.1)
- 重要:電話番号プラグイン、Electron プラグイン(各 CVSS 8.1)
- 悪用の報告:公式ブログ・各アドバイザリーに 記載なし
- 更新:better-auth と @better-auth/* をすべて同じ修正版へ
- 更新後:Expo・Electron は シークレットの入れ替え、電話番号は 未確認の番号の削除 など
まずは npm ls better-auth で、いま入っているバージョンと使っているプラグインを確かめてみてください。
