experimental_taintUniqueValue
taintUniqueValue
permite que você impeça que valores únicos, como senhas, chaves ou tokens, sejam passados para Componentes do Cliente.
taintUniqueValue(errMessage, lifetime, value)
Para evitar passar um objeto contendo dados sensíveis, consulte taintObjectReference
.
Referência
taintUniqueValue(message, lifetime, value)
Chame taintUniqueValue
com uma senha, token, chave ou hash para registrá-lo com o React como algo que não deve ser permitido passar para o Cliente como está:
import {experimental_taintUniqueValue} from 'react';
experimental_taintUniqueValue(
'Não passe chaves secretas para o cliente.',
process,
process.env.SECRET_KEY
);
Parâmetros
-
message
: A mensagem que você deseja exibir sevalue
for passado para um Componente do Cliente. Esta mensagem será exibida como parte do erro que será lançado sevalue
for passado para um Componente do Cliente. -
lifetime
: Qualquer objeto que indique por quanto tempovalue
deve ser contaminado.value
será bloqueado de ser enviado a qualquer Componente do Cliente enquanto este objeto ainda existir. Por exemplo, passarglobalThis
bloqueia o valor pelo tempo de vida de um aplicativo.lifetime
é tipicamente um objeto cujas propriedades contêmvalue
. -
value
: Uma string, bigint ou TypedArray.value
deve ser uma sequência única de caracteres ou bytes com alta entropia, como um token criptográfico, chave privada, hash ou uma longa senha.value
será bloqueado de ser enviado a qualquer Componente do Cliente.
Retornos
experimental_taintUniqueValue
retorna undefined
.
Ressalvas
- Derivar novos valores de valores contaminados pode comprometer a proteção contra contaminação. Novos valores criados por uppercasing valores contaminados, concatenando valores de string contaminados em uma string maior, convertendo valores contaminados para base64, substringando valores contaminados e outras transformações semelhantes não são contaminados a menos que você chame explicitamente
taintUniqueValue
sobre esses novos valores criados. - Não use
taintUniqueValue
para proteger valores de baixa entropia, como códigos PIN ou números de telefone. Se qualquer valor em uma solicitação é controlado por um atacante, eles podem inferir qual valor está contaminado enumerando todos os possíveis valores do segredo.
Uso
Impedir que um token seja passado para Componentes do Cliente
Para garantir que informações sensíveis, como senhas, tokens de sessão ou outros valores únicos, não sejam inadvertidamente passadas para Componentes do Cliente, a função taintUniqueValue
fornece uma camada de proteção. Quando um valor é contaminado, qualquer tentativa de passá-lo para um Componente do Cliente resultará em um erro.
O argumento lifetime
define a duração pela qual o valor permanece contaminado. Para valores que devem permanecer contaminados indefinidamente, objetos como globalThis
ou process
podem servir como o argumento lifetime
. Esses objetos têm uma vida útil que abrange toda a duração da execução do seu aplicativo.
import {experimental_taintUniqueValue} from 'react';
experimental_taintUniqueValue(
'Não passe a senha de um usuário para o cliente.',
globalThis,
process.env.SECRET_KEY
);
Se a vida útil do valor contaminado estiver ligada a um objeto, o lifetime
deve ser o objeto que encapsula o valor. Isso garante que o valor contaminado permaneça protegido durante a vida útil do objeto encapsulante.
import {experimental_taintUniqueValue} from 'react';
export async function getUser(id) {
const user = await db`SELECT * FROM users WHERE id = ${id}`;
experimental_taintUniqueValue(
'Não passe o token de sessão de um usuário para o cliente.',
user,
user.session.token
);
return user;
}
Neste exemplo, o objeto user
serve como o argumento lifetime
. Se esse objeto for armazenado em um cache global ou for acessível por outra solicitação, o token de sessão permanece contaminado.
Deep Dive
Se você está executando um ambiente de Componentes do Servidor que tem acesso a chaves privadas ou senhas, como senhas de banco de dados, você deve ter cuidado para não passá-las para um Componente do Cliente.
export async function Dashboard(props) {
// NÃO FAÇA ISSO
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]);
...
}
Esse exemplo vazaria o token secreto da API para o cliente. Se esse token da API puder ser usado para acessar dados que este usuário específico não deveria ter acesso, isso pode levar a uma violação de dados.
Idealmente, segredos como esse são abstraídos em um único arquivo auxiliar que só pode ser importado por utilitários de dados confiáveis no servidor. O auxiliar pode até ser marcado com server-only
para garantir que este arquivo não seja importado no cliente.
import "server-only";
export function fetchAPI(url) {
const headers = { Authorization: process.env.API_PASSWORD };
return fetch(url, { headers });
}
Às vezes, erros acontecem durante a refatoração e nem todos os seus colegas podem saber disso. Para proteger contra esses erros que podem ocorrer no futuro, podemos “contaminar” a senha real:
import "server-only";
import {experimental_taintUniqueValue} from 'react';
experimental_taintUniqueValue(
'Não passe a senha do token da API para o cliente. ' +
'Em vez disso, faça todas as buscas no servidor.'
process,
process.env.API_PASSWORD
);
Agora, sempre que alguém tentar passar essa senha para um Componente do Cliente, ou enviar a senha para um Componente do Cliente com uma Ação do Servidor, um erro será lançado com a mensagem que você definiu ao chamar taintUniqueValue
.