ClaudeNext.js2023/10/23 14:00

How to Think About Security in Next.js

要点だけを先に読めるように短く再構成したセクションです。

元記事

Quick Digest

要約

要点だけを先に読めるように短く再構成したセクションです。

claudejamodel: claude-sonnet-4-20250514

Next.jsにおけるセキュリティの考え方

Key Points

  • React Server Componentsの新しいセキュリティパラダイム
  • 3つのデータハンドリングモデルの選択指針
  • Taint APIによる機密データ漏洩防止機能

Summary

Next.jsのApp RouterとReact Server Components(RSC)における新しいセキュリティパラダイムについて解説。サーバーとクライアント間のデータ処理において、偶発的なデータ漏洩リスクを最小化するためのベストプラクティスを提供。

Key Points

  • 3つのデータハンドリングモデル

    • HTTP APIs:既存の大規模プロジェクト向け(Zero Trustアプローチ)
    • Data Access Layer:新規プロジェクト推奨(一元化されたデータアクセス制御)
    • Component Level Data Access:プロトタイピング用(小規模チーム向け)
  • セキュリティ保護機能

    • server-onlyモジュールによるサーバー専用コードの保護
    • 実験的なTaint APIによる機密データの漏洩防止
    • 環境変数のサーバー側デフォルト保護
  • 監査時の注意点

    • Client Componentのpropsインターフェースの最小化
    • DTOパターンによる安全なデータ転送
    • パラメータ化クエリによるSQLインジェクション対策

Full Translation

翻訳

原文の流れを保ったまま読める翻訳セクションです。

claudejamodel: claude-sonnet-4-20250514

Next.jsにおけるセキュリティの考え方

Next.jsにおけるセキュリティの考え方

2023年10月23日(月)投稿者:Sebastian Markbåge @ sebmarkbage

App RouterのReact Server Components(RSC)は、従来の手法に関連する冗長性と潜在的なリスクの多くを排除する新しいパラダイムです。この新しさゆえに、開発者とセキュリティチームは、既存のセキュリティプロトコルをこのモデルに合わせることが困難な場合があります。この文書は、注意すべき領域、組み込まれた保護機能を強調し、アプリケーションの監査ガイドを含むことを目的としています。特に偶発的なデータ露出のリスクに焦点を当てています。

データ処理モデルの選択

React Server Componentsはサーバーとクライアントの境界を曖昧にします。データ処理は、情報がどこで処理され、その後利用可能になるかを理解する上で最も重要です。最初に行う必要があるのは、プロジェクトに適したデータ処理アプローチを選択することです。

  • HTTP APIs(既存の大規模プロジェクト/組織に推奨)
  • Data Access Layer(新規プロジェクトに推奨)
  • Component Level Data Access(プロトタイピングと学習に推奨)

1つのアプローチに固執し、あまり混在させないことをお勧めします。これにより、コードベースで作業する開発者とセキュリティ監査者の両方にとって、何を期待すべきかが明確になります。例外は疑わしいものとして目立ちます。

HTTP APIs

既存のプロジェクトでServer Componentsを採用する場合、推奨されるアプローチは、Server Componentsを実行時にSSRやクライアント内と同様に、デフォルトで安全でない/信頼できないものとして扱うことです。内部ネットワークや信頼ゾーンの仮定はなく、エンジニアはZero Trustの概念を適用できます。

代わりに、Server Componentsからクライアントで実行されるかのように、fetch()を使用してRESTやGraphQLなどのカスタムAPIエンドポイントのみを呼び出します。すべてのCookieを渡します。

データベースに接続する既存のgetStaticProps/getServerSidePropsがある場合、モデルを統合し、これらをAPIエンドポイントに移動して、1つの方法で物事を行うことをお勧めします。内部ネットワークからのフェッチが安全であると仮定するアクセス制御に注意してください。

このアプローチにより、セキュリティに特化した既存のバックエンドチームが既存のセキュリティプラクティスを適用できる既存の組織構造を維持できます。これらのチームがJavaScript以外の言語を使用している場合、このアプローチでうまく機能します。

Data Access Layer

新規プロジェクトに推奨されるアプローチは、JavaScriptコードベース内に別個のData Access Layerを作成し、すべてのデータアクセスをそこに統合することです。このアプローチにより、一貫したデータアクセスが保証され、認可バグが発生する可能性が減少します。単一のライブラリに統合するため、保守も容易になります。

現在のユーザーを受け入れ、データを返す前にユーザーがこのデータを見ることができるかどうかをチェックする内部JavaScriptライブラリを構築します。原則として、Server Component関数本体は、リクエストを発行している現在のユーザーがアクセスを許可されているデータのみを見るべきです。

// data/auth.tsx
import { cache } from 'react';
import { cookies } from 'next/headers';

export const getCurrentUser = cache(async () => {
  const token = cookies().get('AUTH_TOKEN');
  const decodedToken = await decryptAndValidate(token);
  return new User(decodedToken.id);
});
// data/user-dto.tsx
import 'server-only';
import { getCurrentUser } from './auth';

export async function getProfileDTO(slug: string) {
  const [rows] = await sql`SELECT * FROM user WHERE slug = ${slug}`;
  const userData = rows[0];
  const currentUser = await getCurrentUser();
  
  return {
    username: canSeeUsername(currentUser) ? userData.username : null,
    phonenumber: canSeePhoneNumber(currentUser, userData.team) ? userData.phonenumber : null,
  };
}

これらのメソッドは、そのままクライアントに転送しても安全なオブジェクトを公開する必要があります。これらをData Transfer Objects(DTO)と呼び、クライアントが消費する準備ができていることを明確にします。

Component Level Data Access

別のアプローチは、データベースクエリを直接Server Componentsに配置することです。このアプローチは、迅速な反復とプロトタイピングにのみ適しています。

このアプローチでは、「use client」ファイルを慎重に監査する必要があります。監査とPRレビューの際は、すべてのエクスポートされた関数と、型シグネチャがUserのような過度に広範なオブジェクトを受け入れるか、tokencreditCardのようなプロパティを含むかどうかを確認してください。

Server Only

サーバーでのみ実行されるべきコードは、次のようにマークできます:

import 'server-only';

これにより、Client Componentがこのモジュールをインポートしようとするとビルドエラーが発生します。

Next.js 14の実験的機能

次期Next.js 14リリースでは、next.config.jsでtaintフラグを有効にすることで、実験的なReact Taint APIを試すことができます:

// next.config.js
module.exports = {
  experimental: {
    taint: true,
  },
};
// app/data.ts
import { experimental_taintObjectReference } from 'react';

export async function getUserData(id) {
  const data = ...;
  experimental_taintObjectReference('Do not pass user data to the client', data);
  return data;
}

トークンなどの一意の文字列の場合、taintUniqueValueを使用して生の値もブロックできます。

環境変数

デフォルトでは、環境変数はサーバーでのみ利用可能です。慣例により、Next.jsはNEXT_PUBLIC_で始まる環境変数もクライアントに公開します。これにより、クライアントで利用可能であるべき特定の明示的な設定を公開できます。

SSR vs RSC

初期ロードでは、Next.jsはHTMLを生成するためにServer ComponentsとClient Componentsの両方をサーバーで実行します。Server Components(RSC)は、2つのモジュール間で情報が誤って露出することを避けるため、Client Componentsとは別のモジュールシステムで実行されます。

Server-side Rendering(SSR)を通じてレンダリングされるClient Componentsは、ブラウザクライアントと同じセキュリティポリシーとして考慮されるべきです。特権データやプライベートAPIにアクセスすべきではありません。