experimental_taintUniqueValue
taintUniqueValue vous permet d’empêcher que certaines valeurs uniques soient passées à un Composant Client, telles que des mots de passe, clés ou jetons.
taintUniqueValue(errMessage, lifetime, value)Pour empêcher le passage d’un objet contenant des données sensibles, utilisez taintObjectReference.
Référence
taintUniqueValue(message, lifetime, value)
Appelez taintUniqueValue avec un mot de passe, jeton, clé ou hash pour indiquer à React qu’il ne doit pas permettre le passage de cette valeur vers le côté client :
import { experimental_taintUniqueValue } from 'react';
experimental_taintUniqueValue(
'Ne passez pas de clés secrètes au client.',
process,
process.env.SECRET_KEY
);Voir plus d’exemples ci-dessous.
Paramètres
-
message: le message que vous souhaitez afficher sivalueest passée à un Composant Client. Ce message fera partie de l’erreur qui sera levée sivalueest passée à un Composant Client. -
lifetime: tout objet indiquant pour combien de tempsvaluedevrait être « ternie ». React bloquera le passage devalueaux Composants Clients tant que cet objet existera. PasserglobalThispour cet argument bloquerait par exemple le passage de cette valeur pour toute la durée de vie de l’appli.lifetimeest le plus souvent un objet dont l’une des propriétés contientvalue. -
value: une chaîne de caractères, un bigint ou un TypedArray (tableau typé).valuedoit être une séquence unique de caractères ou d’octets dotée d’une forte entropie, telle qu’un jeton cryptographique, une clé privée, un hash ou un long mot de passe.valuene pourra alors plus être passée à un Composant Client.
Valeur renvoyée
experimental_taintUniqueValue renvoie undefined.
Limitations
- La dérivation de valeurs à partir des valeurs ternies peut nuire à la protection par ternissement. Les nouvelles valeurs créées par exemple en changeant la casse de valeurs ternies, en concaténant des chaînes ternies vers une chaîne de caractères plus longue, en convertissant des valeurs ternies en Base 64, en extrayant des portions de chaînes ternies, ou toute autre transformation du même genre, ne constituent plus des valeurs ternies à moins que vous n’appeliez explicitement
taintUniqueValuesur les nouvelles valeurs ainsi produites. - N’utilisez pas
taintUniqueValuepour protéger des valeurs à basse entropie, telles que des codes PIN ou des numéros de téléphones. Si une valeur de requête est contrôlée par vos attaquants, ils peuvent alors déterminer la valeur ternie en énumérant toutes les valeurs possibles du secret.
Utilisation
Empêcher le passage d’un jeton à un Composant Client
Pour vous assurer que des données sensibles telles que des mots de passe, jetons de sessions et autres valeurs uniques ne soient pas passées par inadvertance à des Composants Clients, la fonction taintUniqueValue vous offre une couche de protection. Lorsqu’une valeur est ternie, toute tentative de la passer à un Composant Client lèvera une erreur.
L’argument lifetime définit la durée du ternissement pour cette valeur. Si vous souhaitez un ternissement définitif, utilisez pour l’argument lifetime des objets tels que globalThis ou process. Ces objets ont une durée de vie qui couvre toute l’exécution de votre appli.
import { experimental_taintUniqueValue } from 'react';
experimental_taintUniqueValue(
'Ne passez pas une clé privée au client.',
globalThis,
process.env.SECRET_KEY
);Si la durée de vie de la valeur ternie est liée à un objet, définissez lifetime à l’objet qui encapsule cette valeur. Ça garantit que la valeur ternie restera protégée pendant toute la durée de vie de l’objet qui la contient.
import { experimental_taintUniqueValue } from 'react';
export async function getUser(id) {
const user = await db`SELECT * FROM users WHERE id = ${id}`;
experimental_taintUniqueValue(
'Ne passez par un jeton de session utilisateur au client.',
user,
user.session.token
);
return user;
}Dans cet exemple, l’objet user sert comme argument lifetime. Si cet objet est stocké dans un cache global ou se retrouve accessible par une autre requête, le jeton de session restera terni.
En détail
Si votre environnement de Composants Serveur a accès à des données sensibles telles que des clés privées ou des mots de passe, vous devez être attentif·ve à ne pas les passer à un Composant Client.
export async function Dashboard(props) {
// NE FAITES PAS ÇA
return <Overview password={process.env.API_PASSWORD} />;
}"use client";
import {useEffect} from '...'
export async function Overview({ password }) {
useEffect(() => {
const headers = { Authorization: password };
fetch(url, { headers }).then(...);
}, [password]);
...
}Cet exemple ferait fuiter un jeton d’API secret vers le côté client. Si ce jeton d’API peut être utilisé pour accéder à des données auxquelles cet utilisateur spécifique ne devrait pas avoir accès, il constituerait une faille de sécurité.
Dans l’idéal, ce type de secrets est isolé dans un unique fichier utilitaire qui ne doit pouvoir être importé que par des utilitaires de confiance côté serveur. Ce type de fichier peut même être étiqueté avec server-only pour garantir qu’il ne sera pas importé côté client.
import "server-only";
export function fetchAPI(url) {
const headers = { Authorization: process.env.API_PASSWORD };
return fetch(url, { headers });
}Lors d’une refonte, des erreurs peuvent survenir car l’ensemble de votre équipe ne sera peut-être pas attentive à ce point de sécurité. Pour vous éviter des erreurs en aval vous pouvez « ternir » le mot de passe effectif :
import "server-only";
import { experimental_taintUniqueValue } from 'react';
experimental_taintUniqueValue(
'Ne passez pas le jeton d’API au client. ' +
'Effectuez plutôt les chargements côté serveur.'
process,
process.env.API_PASSWORD
);À présent, dès que quiconque essaierait de passer ce mot de passe à un Composant Client, ou enverrait le mot de passe à un Composant Client via une Server Action, une erreur serait levée avec le message défini lors de l’appel à taintUniqueValue.