| title | experimental_taintObjectReference |
|---|---|
| version | experimental |
この API は実験的なものであり、まだ安定版の React では利用できません。
React パッケージを最新の実験バージョンにアップグレードすることで試すことができます。
react@experimentalreact-dom@experimentaleslint-plugin-react-hooks@experimental
React の実験バージョンにはバグが含まれている可能性があります。本番環境では使用しないでください。
この API は React Server Components 内でのみ利用できます。
taintObjectReference を使うと、user オブジェクトのような特定のオブジェクトインスタンスが Client Component に渡されるのを防げます。
experimental_taintObjectReference(message, object);キー、ハッシュ、トークンなどが渡されるのを防ぎたい場合は、taintUniqueValue を参照してください。
taintObjectReference をオブジェクトと共に呼び出すことで、そのオブジェクトをクライアントにそのまま渡してはならないものとして React に登録します。
import {experimental_taintObjectReference} from 'react';
experimental_taintObjectReference(
'Do not pass ALL environment variables to the client.',
process.env
);-
message: オブジェクトが Client Component に渡されてしまった場合に表示したいメッセージです。このメッセージは、そのオブジェクトが Client Component に渡されたときに投げられるエラーの一部として表示されます。 -
object: taint するオブジェクトです。関数やクラスインスタンスをtaintObjectReferenceにobjectとして渡すことができます。関数やクラスは Client Component に渡されることがすでにブロックされていますが、React のデフォルトのエラーメッセージはmessageで定義したものに置き換えられます。Typed Array の特定のインスタンスをtaintObjectReferenceにobjectとして渡した場合、その Typed Array の他のコピーは taint されません。
experimental_taintObjectReference は undefined を返します。
- taint されたオブジェクトを再作成またはクローンすると、機密データを含む可能性がある新しい taint されていないオブジェクトが作成されます。例えば、taint された
userオブジェクトがある場合、const userInfo = {name: user.name, ssn: user.ssn}や{...user}は taint されていない新しいオブジェクトを作成します。taintObjectReferenceが保護するのは、オブジェクトが変更されずに Client Component へそのまま渡されてしまうような単純なミスだけです。
セキュリティを taint だけに頼らないでください。オブジェクトを taint しても、派生しうるあらゆる値の漏えいを防げるわけではありません。例えば、taint されたオブジェクトをクローンすると、taint されていない新しいオブジェクトが作成されます。taint されたオブジェクトのデータを使うと(例えば {secret: taintedObj.secret})、taint されていない新しい値やオブジェクトが作成されます。taint は保護層の 1 つです。セキュアなアプリには、複数の保護層、適切に設計された API、分離パターンが必要です。
Client Component は、機密データを持つオブジェクトを決して受け取るべきではありません。理想的には、データ取得関数は現在のユーザに見せるべきではないデータを公開しないようにするべきです。しかしリファクタリング中にミスが起きることもあります。後続の処理でそのようなミスが起きた場合に備えて、データ API 内で user オブジェクトを "taint" できます。
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;
}これにより、誰かがこのオブジェクトを Client Component に渡そうとすると、指定したエラーメッセージを含むエラーが投げられます。
機密データにアクセスできる Server Components 環境を実行している場合、オブジェクトをそのまま渡さないように注意する必要があります。
// 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 オブジェクトが Client Component に渡されるのを防ぐために、user オブジェクトを "taint" できます。
// 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 オブジェクトを Client Component に渡そうとすると、指定したエラーメッセージを含むエラーが投げられます。