コンテンツにスキップ

taint

この機能は現在実験的であり、変更される可能性があります。本番環境での使用は推奨されません。お試しいただき、GitHubでフィードバックをお寄せください。

使用方法

taint オプションは、オブジェクトや値のtaint(汚染)を可能にする実験的な React API のサポートを有効にします。この機能は、機密データがクライアントに誤って渡されるのを防ぐのに役立ちます。有効にすると、以下を使用できます。

知っておくと良いこと: このフラグをアクティブにすると、app ディレクトリの React experimental チャネルも有効になります。

next.config.ts
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  experimental: {
    taint: true,
  },
}
 
export default nextConfig

警告: taint API を、機密データをクライアントに公開しないための唯一のメカニズムとして依存しないでください。弊社の セキュリティ推奨事項 を参照してください。

taint API を使用すると、サーバーとクライアントの境界を通過することが許可されていないデータを宣言的かつ明示的にマークすることで、防御的になることができます。オブジェクトまたは値がサーバーとクライアントの境界を通過すると、React はエラーをスローします。

これは、次のような場合に役立ちます。

  • データの読み取りメソッドが制御不能な場合
  • 自身で定義されていない機密データ形状を扱う必要がある場合
  • サーバーコンポーネントのレンダリング中に機密データにアクセスされる場合

機密データが不要なコンテキストに返されないように、データと API をモデル化することが推奨されます。

注意点

  • taint はオブジェクト参照のみを追跡できます。オブジェクトをコピーすると、taint されていないバージョンが作成され、API が提供するすべての保証が失われます。コピーも taint する必要があります。
  • taint は、taint された値から派生したデータを追跡できません。派生値も taint する必要があります。
  • 値は、それらのライフタイム参照がスコープ内にある限り taint されます。詳細については、experimental_taintUniqueValue パラメータリファレンス を参照してください。

オブジェクト参照のtaint(汚染)

この場合、getUserDetails 関数は指定されたユーザーのデータを返します。ユーザーオブジェクト参照を taint して、サーバーとクライアントの境界を越えられないようにします。たとえば、UserCard が Client Component であると仮定します。

import { experimental_taintObjectReference } from 'react'
 
function getUserDetails(id: string): UserDetails {
  const user = await db.queryUserById(id)
 
  experimental_taintObjectReference(
    'Do not use the entire user info object. Instead, select only the fields you need.',
    user
  )
 
  return user
}

taint された userDetails オブジェクトから個々のフィールドにアクセスすることは依然として可能です。

export async function ContactPage({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params
  const userDetails = await getUserDetails(id)
 
  return (
    <UserCard
      firstName={userDetails.firstName}
      lastName={userDetails.lastName}
    />
  )
}

これで、オブジェクト全体を Client Component に渡すとエラーが発生します。

export async function ContactPage({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const userDetails = await getUserDetails(id)
 
  // Throws an error
  return <UserCard user={userDetails} />
}

ユニークな値のtaint(汚染)

この場合、config.getConfigDetails への呼び出しを await することで、サーバー構成にアクセスできます。しかし、システム構成には SERVICE_API_KEY が含まれており、これはクライアントに公開したくありません。

config.SERVICE_API_KEY の値を taint できます。

import { experimental_taintUniqueValue } from 'react'
 
function getSystemConfig(): SystemConfig {
  const config = await config.getConfigDetails()
 
  experimental_taintUniqueValue(
    'Do not pass configuration tokens to the client',
    config,
    config.SERVICE_API_KEY
  )
 
  return config
}

systemConfig オブジェクトの他のプロパティに引き続きアクセスできます。

export async function Dashboard() {
  const systemConfig = await getSystemConfig()
 
  return <ClientDashboard version={systemConfig.SERVICE_API_VERSION} />
}

しかし、SERVICE_API_KEYClientDashboard に渡すとエラーが発生します。

export async function Dashboard() {
  const systemConfig = await getSystemConfig()
  // Someone makes a mistake in a PR
  const version = systemConfig.SERVICE_API_KEY
 
  return <ClientDashboard version={version} />
}

systemConfig.SERVICE_API_KEY が新しい変数に再代入された場合でも、Client Component に渡すとエラーが発生することに注意してください。

一方、taint されたユニークな値から派生した値は、クライアントに公開されます。

export async function Dashboard() {
  const systemConfig = await getSystemConfig()
  // Someone makes a mistake in a PR
  const version = `version::${systemConfig.SERVICE_API_KEY}`
 
  return <ClientDashboard version={version} />
}

より良いアプローチは、getSystemConfig から返されるデータから SERVICE_API_KEY を削除することです。