experimental_taintUniqueValue
taintUniqueValue
permite impedir que valores exclusivos sejam passados para Componentes de Cliente, como senhas, chaves ou tokens.
taintUniqueValue(errMessage, lifetime, value)
Para impedir a passagem de 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 de Cliente. Esta mensagem será exibida como parte do Erro que será lançado sevalue
for passado para um Componente de Cliente. -
lifetime
: Qualquer objeto que indique por quanto tempovalue
deve ser contaminado.value
será bloqueado de ser enviado para qualquer Componente de Cliente enquanto este objeto ainda existir. Por exemplo, passarglobalThis
bloqueia o valor durante o 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 exclusiva de caracteres ou bytes com alta entropia, como um token criptográfico, chave privada, hash ou uma senha longa.value
será bloqueado de ser enviado para qualquer Componente de Cliente.
Retorna
experimental_taintUniqueValue
retorna undefined
.
Ressalvas
- Derivar novos valores de valores contaminados pode comprometer a proteção contra contaminação. Novos valores criados por uppercase de 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ê explicitamente chame
taintUniqueValue
nesses valores recém-criados. - Não use
taintUniqueValue
para proteger valores de baixa entropia, como códigos PIN ou números de telefone. Se algum valor em uma solicitação for controlado por um invasor, ele poderá inferir qual valor está contaminado enumerando todos os valores possíveis do segredo.
Uso
Impedir que um token seja passado para Componentes de Cliente
Para garantir que informações confidenciais, como senhas, tokens de sessão ou outros valores exclusivos, não sejam passados inadvertidamente para Componentes de Cliente, a função taintUniqueValue
oferece uma camada de proteção. Quando um valor é contaminado, qualquer tentativa de passá-lo para um Componente de Cliente resultará em um erro.
O argumento lifetime
define a duração em que o valor permanece contaminado. Para valores que devem permanecer contaminados indefinidamente, objetos como globalThis
ou process
podem servir como argumento lifetime
. Esses objetos têm um tempo de vida que abrange toda a duração da execução do seu aplicativo.
import {experimental_taintUniqueValue} from 'react';
experimental_taintUniqueValue(
'Não passe uma senha de usuário para o cliente.',
globalThis,
process.env.SECRET_KEY
);
Se o tempo de vida do valor contaminado estiver ligado 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 encapsulador.
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 um token de sessão do usuário para o cliente.',
user,
user.session.token
);
return user;
}
Neste exemplo, o objeto user
serve como argumento lifetime
. Se este objeto for armazenado em um cache global ou for acessível por outra requisição, o token da sessão permanecerá contaminado.
Deep Dive
Se você estiver executando um ambiente de Componentes de Servidor que tenha acesso a chaves privadas ou senhas, como senhas de banco de dados, você deve ter cuidado para não passá-las para um Componente de 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]);
...
}
Este exemplo vazaria o token secreto da API para o cliente. Se este token da API puder ser usado para acessar dados que este usuário em particular não deveria ter acesso, isso poderia levar a uma violação de dados.
Idealmente, segredos como este 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 sobre isso. Para se proteger contra a ocorrência desses erros 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 esta senha para um Componente de Cliente, ou enviar a senha para um Componente de Cliente com uma Função de Servidor, um erro será lançado com a mensagem que você definiu quando chamou taintUniqueValue
.