Modern Frontend CVEs

対象CVE: GHSA-xmf8-cvqr-rfgj

[Auth.js/NextAuth.js] getToken()におけるサービス拒否の脆弱性(GHSA-xmf8-cvqr-rfgj)について

Auth.jsおよびNextAuth.jsの`getToken()`ヘルパーにおいて、不正な`Authorization: Bearer`ヘッダーが原因で捕捉されない例外が発生し、サービス拒否に繋がる可能性のある脆弱性(GHSA-xmf8-cvqr-rfgj)が報告されました。本記事では、この脆弱性の詳細と対策について解説します。

はじめに

Auth.jsおよびNextAuth.jsを使用しているフロントエンドエンジニアの皆さん、こんにちは。今回は、Auth.jsの内部で使用されている`getToken()`ヘルパーに存在するサービス拒否(DoS)の脆弱性(GHSA-xmf8-cvqr-rfgj)について解説します。この脆弱性は、不正な入力が原因でサーバーサイドの処理がクラッシュする可能性があるため、特にAPIルートやミドルウェアで`getToken()`を直接利用している場合に注意が必要です。

脆弱性の概要と仕組み

この脆弱性は、`next-auth/jwt`や`@auth/core/jwt`からエクスポートされている`getToken()`ヘルパーが、不正な形式の`Authorization: Bearer …`ヘッダーを読み取った際に、捕捉されない例外をスローすることが原因で発生します。

通常、`getToken()`はセッションクッキーが存在しない場合、Bearerトークンの値をURLデコードしようとします。ここで、パーセントエンコーディングが不正な形式であると、デコード処理が例外をスローします。この例外が`getToken()`の呼び出し元で適切に処理(`try/catch`でラップ)されていない場合、アプリケーション全体がクラッシュし、サービス拒否の状態に陥る可能性があります。

これは、CWE-20: Improper Input Validation(不適切な入力検証)に分類される問題です。

あなたが影響を受けるかどうかの確認

以下のすべての条件に当てはまる場合、あなたは影響を受けます。

1. `next-auth`バージョン`5.0.0-beta.25`以前、または同じ`getToken()`実装を公開する`@auth/core`を使用している。 2. アプリケーションで`getToken()`を直接呼び出している(例:Route Handler、ミドルウェア、サーバーサイドのRequest Handler)。 3. `getToken()`の呼び出しを独自の`try/catch`でラップしていない。

以下の場合は影響を受けません。

1. フレームワークの`auth()`ヘルパーのみを使用し、`getToken()`を直接呼び出していない場合。 2. すべての`getToken()`呼び出し箇所がすでに例外処理(`try/catch`)で保護されている場合。

Next.jsのApp Routerで`auth()`を使用している場合や、Pages Routerで`getServerSession()`を使用している場合など、直接`getToken()`を呼び出していない場合は通常影響を受けません。しかし、もしカスタムでJWTを扱うために`getToken()`を直接呼び出している場合は注意が必要です。

具体的な影響

サービス拒否(Denial of Service, DoS): 認証されていないリクエストであっても、不正な`Authorization: Bearer`ヘッダーを送信するだけで、`getToken()`を呼び出しているハンドラーで未処理の例外が発生し、アプリケーションがクラッシュする可能性があります。これは、単一の不正なリクエストがサービス停止を引き起こす可能性があることを意味します。

この脆弱性は、トークンやセッション、その他のデータの漏洩には繋がりません。また、認証をバイパスすることもありません。影響はリクエスト単位であり、可用性に限定されます。

対策

最も推奨される対策は、パッチが適用されたバージョンへのアップグレードです。

Auth.jsまたはNextAuth.jsのパッチ適用版がリリースされ次第、速やかにアップグレードしてください。(執筆時点ではまだリリースされていませんが、アドバイザリが更新される予定です。)

修正版では、不正なBearer値は無効なトークンとして扱われ、`null`が返されるようになります。アップグレード後、コード変更は不要です。

コードレベルでの対応: `getToken()`の呼び出しを`try/catch`ブロックでラップし、エラーが発生した場合は「トークンなし」として扱うようにします。

```ts let token = null; try { token = await getToken({ req, secret }); } catch (e) { // エラーが発生した場合もトークンがないものとして扱う console.error("Failed to get token:", e); // 必要に応じてログを出力 token = null; } ```

エッジレベルでの対応: プロキシやミドルウェアなどで、`Authorization`ヘッダーのBearer部分が有効なパーセントエンコーディングでない場合に、そのヘッダーを削除または正規化する、あるいはリクエストを拒否する処理を追加します。

まとめ

Auth.js/NextAuth.jsの`getToken()`を使用している場合、不正なBearerヘッダーによるサービス拒否の脆弱性に注意が必要です。特にAPIルートやミドルウェアで`getToken()`を直接利用し、`try/catch`で囲んでいない場合は、早急な対応が求められます。

まずはご自身のアプリケーションが影響を受けるか確認し、パッチ適用版へのアップグレード、またはワークアラウンドの実装を検討してください。最新のライブラリに保ち、適切なエラーハンドリングを行うことが、堅牢なアプリケーション開発には不可欠です。

← ブログ一覧に戻る