React

Sanitizzare l'input contro XSS: cosa serve

L'input non si sanifica in ingresso: si codifica in uscita e solo l'HTML generato dagli utenti passa da un sanitizer come DOMPurify.

In sintesi

  • L'input si codifica in uscita; solo l'HTML generato dagli utenti va sanificato.
  • React sfugge il testo in JSX, non il markup passato a dangerouslySetInnerHTML.
  • La sanificazione va ripetuta sul server: il client si può modificare.

L'input non si sanifica in ingresso: si codifica in uscita, e solo l'HTML generato dagli utenti passa da un sanitizer come DOMPurify.

Il testo non è il pericolo

React, distribuito con licenza MIT, sfugge già i valori: {commento} finisce nel DOM come testo, non come markup. Il buco si apre con dangerouslySetInnerHTML, dove la stringa arriva al DOM così com'è.

Codificare o sanificare

function Commento({ testo }) {
  return {testo}; // React escapes the string, no script runs
}

function CommentoRicco({ html }) {
  return ;
}

La prima versione è sicura per costruzione: il testo resta testo. La seconda accetta markup, quindi deve passare da DOMPurify, disponibile con licenza Apache-2.0 o MPL-2.0, prima di toccare il DOM.

Le regole che reggono

  • Codifica in uscita: il testo diventa entità quando entra nel DOM, non quando arriva dal form.
  • Sanifica solo l'HTML: un editor ricco ha bisogno di un parser che rimuova tag, attributi e URL con schema javascript:.
  • Niente concatenazione: comporre HTML con + salta ogni difesa, anche quando i pezzi sembrano innocui.

Installazione

npm i dompurify

Il pacchetto non chiede configurazione: DOMPurify.sanitize usa una lista di tag ammessi, e la si restringe con ALLOWED_TAGS quando il contenuto deve restare semplice.

Tre componenti dove l'input dell'utente conta: interfaces-textarea, link-preview e input. Per sfogliare per categoria parti da 111.985 componenti.

La limitazione

La sanificazione nel browser non basta se l'HTML viene salvato e servito ad altri: un client modificato può inviare markup non filtrato. La stessa funzione va eseguita sul server, dove DOMPurify richiede jsdom come DOM.

Dove continuare

Il modello dei campi è in form controllati e non; il flusso progressivo è in form progressivo con Next.js; la differenza fra azioni server e API è in Server Actions vs API.

Domande frequenti

Basta React per evitare XSS?

Per il testo sì: JSX sfugge i valori. Per l'HTML no: dangerouslySetInnerHTML lo inserisce così com'è e serve un sanitizer.

Posso sanificare con una regex?

No. Una regex non conosce la grammatica HTML e lascia passare varianti come attributi spezzati o entità annidate. Serve un parser.

Dove va applicata la sanificazione?

In uscita, nel punto in cui l'HTML entra nel DOM. Va ripetuta sul server, perché il client può essere modificato.

DOMPurify funziona anche in Node?

Sì, con jsdom a fornire il DOM. Nel browser usa quello nativo. La licenza è Apache-2.0 o MPL-2.0.

Un nome o un'email vanno sanificati?

No. Vanno validati e codificati in uscita: non sono HTML e non devono diventarlo.