experimental_taintObjectReference

開発中

このAPIは実験的なものであり、まだReactの安定版では利用できません。

最新の試験版にReactパッケージをアップグレードすることで試すことができます。

  • react@experimental
  • react-dom@experimental
  • eslint-plugin-react-hooks@experimental

Reactの試験版にはバグが含まれている可能性があります。本番環境では使用しないでください。

このAPIは、Reactサーバーコンポーネント内でのみ使用できます。

taintObjectReference を使用すると、user オブジェクトのようなクライアントコンポーネントに特定のオブジェクトインスタンスが渡されるのを防ぐことができます。

experimental_taintObjectReference(message, object);

キー、ハッシュ、またはトークンの渡りを防ぐには、taintUniqueValue を参照してください。


リファレンス

taintObjectReference(message, object)

taintObjectReference をオブジェクトと共に呼び出して、それをReactに登録します。これは、クライアントにそのまま渡されるべきではないものとして扱われます。

import {experimental_taintObjectReference} from 'react';

experimental_taintObjectReference(
'Do not pass ALL environment variables to the client.',
process.env
);

以下のさらに多くの例を参照してください。

パラメーター

  • message: オブジェクトがクライアントコンポーネントに渡された場合に表示するメッセージ。このメッセージは、オブジェクトがクライアントコンポーネントに渡された場合にスローされるエラーの一部として表示されます。

  • object: 汚染されるオブジェクト。関数とクラスインスタンスは、object として taintObjectReference に渡すことができます。関数とクラスは既にクライアントコンポーネントへの渡しがブロックされていますが、Reactのデフォルトのエラーメッセージは、message で定義したものに置き換えられます。特定のTypedArrayインスタンスがobjectとしてtaintObjectReferenceに渡された場合、TypedArrayの他のコピーは汚染されません。

戻り値

experimental_taintObjectReferenceundefined を返します。

注意事項

  • 汚染されたオブジェクトを再作成または複製すると、機密データを含む可能性のある新しい非汚染オブジェクトが作成されます。たとえば、汚染されたuserオブジェクトがある場合、const userInfo = {name: user.name, ssn: user.ssn}または{...user}によって、汚染されていない新しいオブジェクトが作成されます。taintObjectReferenceは、オブジェクトがクライアントコンポーネントに変更されずに渡された場合の単純なミスからしか保護しません。

落とし穴

セキュリティのために汚染だけに依存しないでください。オブジェクトを汚染しても、考えられるすべての派生値の漏洩を防ぐわけではありません。たとえば、汚染されたオブジェクトのクローンは、新しい非汚染オブジェクトを作成します。汚染されたオブジェクトのデータを使用する場合(例:{secret: taintedObj.secret})、汚染されていない新しい値またはオブジェクトが作成されます。汚染は保護の層の1つです。安全なアプリケーションには、複数の保護層、適切に設計されたAPI、および分離パターンが必要です。


使用方法

ユーザーデータが意図せずクライアントに到達するのを防ぐ

クライアントコンポーネントは、機密データを含むオブジェクトを受け入れるべきではありません。理想的には、データ取得関数は、現在のユーザーがアクセスすべきではないデータを公開すべきではありません。リファクタリング中にミスが発生することがあります。このようなミスが将来発生するのを防ぐために、データAPIでユーザーオブジェクトを「汚染」することができます。

import {experimental_taintObjectReference} from 'react';

export async function getUser(id) {
const user = await db`SELECT * FROM users WHERE id = ${id}`;
experimental_taintObjectReference(
'Do not pass the entire user object to the client. ' +
'Instead, pick off the specific properties you need for this use case.',
user,
);
return user;
}

これで、このオブジェクトをクライアントコンポーネントに渡そうとすると、渡されたエラーメッセージと共にエラーがスローされます。

詳細解説

データ取得における漏洩の防止

機密データにアクセスできるサーバーコンポーネント環境を実行している場合は、オブジェクトをそのまま渡さないように注意する必要があります。

// api.js
export async function getUser(id) {
const user = await db`SELECT * FROM users WHERE id = ${id}`;
return user;
}
import { getUser } from 'api.js';
import { InfoCard } from 'components.js';

export async function Profile(props) {
const user = await getUser(props.userId);
// DO NOT DO THIS
return <InfoCard user={user} />;
}
// components.js
"use client";

export async function InfoCard({ user }) {
return <div>{user.name}</div>;
}

理想的には、getUserは、現在のユーザーがアクセスすべきではないデータを公開すべきではありません。将来、userオブジェクトをクライアントコンポーネントに渡すのを防ぐために、ユーザーオブジェクトを「汚染」することができます。

// api.js
import {experimental_taintObjectReference} from 'react';

export async function getUser(id) {
const user = await db`SELECT * FROM users WHERE id = ${id}`;
experimental_taintObjectReference(
'Do not pass the entire user object to the client. ' +
'Instead, pick off the specific properties you need for this use case.',
user,
);
return user;
}

これで、userオブジェクトをクライアントコンポーネントに渡そうとすると、渡されたエラーメッセージと共にエラーがスローされます。