FlawOpen

flawopen.com/XSS em JavaScript/dangerouslySetInnerHTML

dangerouslySetInnerHTML do React é seguro?

Página de referência
Resposta curta

Pense no JSX comum como uma impressora de etiquetas: texto continua sendo texto. dangerouslySetInnerHTML troca isso por uma prensa que interpreta a string como HTML. Se ela contiver conteúdo controlado por um invasor, o navegador poderá tratá-lo como marcação ativa. Use esse ponto apenas com HTML deliberadamente confiável ou sanitizado para o contexto HTML exato.

Por que o JSX comum não precisa disso

RISCO — entrada de HTML bruto
function Comment({ html }) {
  return <p dangerouslySetInnerHTML=
    {{ __html: html }} />;
}
SEGURO — interpolação JSX comum
function Comment({ text }) {
  return <p>{text}</p>;
}

Quando dangerouslySetInnerHTML é apropriado?

Use-o somente quando o produto precisar preservar um formato restrito de rich text que não possa ser representado como filhos React comuns. Um CMS, editor ou renderizador Markdown não é confiável automaticamente: conteúdo armazenado e saída do renderizador ainda podem conter marcação não confiável. Defina os elementos e atributos permitidos, sanitize com uma biblioteca mantida como DOMPurify e envie o resultado sanitizado diretamente para esse ponto.

Como usar com segurança

Sanitize na fronteira de renderização

Sanitize imediatamente antes de atribuir o valor a dangerouslySetInnerHTML, usando uma biblioteca mantida como DOMPurify. Não use expressões regulares como sanitizador HTML. Evite alterar a string depois da sanitização; uma transformação posterior pode invalidar as garantias do sanitizador. Mantenha a biblioteca e o ambiente de análise atualizados.

Restrinja a marcação permitida

Uma lista de bloqueio de tags conhecidas é incompleta: o risco também pode vir de atributos, campos com URLs, namespaces e comportamento do parser. Escolha uma pequena lista de elementos e atributos necessários ao recurso e configure o sanitizador para essa política. Revise links e outros atributos de URL separadamente, conforme os destinos permitidos pelo produto.

Como verificar seu código

grep -rn "dangerouslySetInnerHTML" --include="*.jsx" --include="*.tsx" .
Para cada ocorrência, rastreie o valor desde a origem e por todas as transformações. Trate entrada do usuário, conteúdo importado e rich text armazenado como não confiáveis; confirme que a política do sanitizador corresponde ao contexto de saída e que nenhuma etapa posterior altera o resultado sanitizado.

Perguntas frequentes

A renderização de Markdown é segura automaticamente?

Depende do renderizador e de sua configuração. Verifique se ele aceita HTML bruto e se sanitiza a saída; não presuma que a conversão de Markdown, por si só, torne o HTML seguro.

Isso também se aplica ao v-html do Vue?

Sim. O v-html também entrega HTML ao navegador sem a interpolação de texto comum do framework. Trate o valor como um ponto de entrada HTML e sanitize conteúdo não confiável conforme uma política adequada.

Referências

Veja também Cross-Site Scripting (XSS, CWE-79): como funciona e como evitar em todas as linguagens — flawopen.com DOMPurify basta para proteger innerHTML? Markdown é seguro contra XSS? Svelte é seguro contra XSS por padrão? Upload de SVG pode causar XSS? Risco de XSS no Vue v-html WKWebView: HTML não confiável é seguro?