Un’entità HTML è un modo di scrivere un carattere perché il browser lo mostri come testo invece di interpretarlo come markup. Scrivi un < grezzo nel tuo contenuto e il browser inizia a leggere un tag; scrivi invece < e renderizza un < letterale sulla pagina. È tutto qui il senso della codifica delle entità HTML.
Cinque caratteri hanno un significato speciale in HTML e sono quelli a cui fai escape più spesso: <, >, &, " e '. Ne fai l’escape per due motivi. Il primo è la visualizzazione: vuoi mostrare codice o markup come testo. Il secondo, e più importante, è la sicurezza: fare l’escape dell’input non attendibile è la base per fermare il cross-site scripting (XSS).
Esistono tre modi intercambiabili di scrivere qualsiasi entità, con nome (<), decimale (<) ed esadecimale (<), e si risolvono tutti nello stesso carattere. La domanda più insidiosa è quando fare escape e con cosa, perché la risposta giusta dipende da dove finisce il valore: testo HTML, un attributo, uno script o un URL. Sotto trovi le notazioni, l’insieme dei caratteri riservati, una tabella che dice cosa usare in ogni contesto e gli errori che ricorrono più spesso.
Cos’è un’entità HTML? (anatomia)
Un’entità HTML, detta anche riferimento a carattere, è un codice breve che sta al posto di un singolo carattere. Ogni entità inizia con una e commerciale & e finisce con un punto e virgola ;. Ciò che sta in mezzo determina quale carattere ottieni.
Esistono tre forme:
&name;— un riferimento con nome, come<o©.&#decimal;— un riferimento numerico decimale, come<.&#xhex;— un riferimento numerico esadecimale, come<.
Il browser legge il riferimento, cerca il carattere a cui punta e renderizza quel singolo carattere. Niente cambia nel risultato visibile: < e un < grezzo si mostrano in modo identico. L’unica differenza è che l’entità viene trattata come testo, mai come l’inizio di un tag.
Le tre notazioni: con nome, decimale, esadecimale
Tutte e tre le notazioni fanno riferimento allo stesso code point Unicode; differiscono solo nella scrittura. Un’entità con nome è la forma leggibile, ma esiste soltanto per i caratteri che hanno un nome definito. Un’entità decimale scrive il code point in base 10. Un’entità esadecimale scrive lo stesso code point in base 16, che corrisponde uno a uno alla notazione U+XXXX che vedi nello standard Unicode.
| Carattere | Con nome | Decimale | Esadecimale |
|---|---|---|---|
< | < | < | < |
& | & | & | & |
© | © | © | © |
é | é | é | é |
Poiché l’esadecimale rispecchia direttamente U+XXXX (é è U+00E9, da cui é), molti sviluppatori vi ricorrono quando documentano o ragionano su uno specifico code point. Per il markup di tutti i giorni, le entità con nome si leggono meglio.
I cinque caratteri riservati a cui devi fare escape
Questi sono i caratteri speciali HTML che cambiano il modo in cui il browser analizza un documento. Se uno di essi compare in un contenuto che dovrebbe essere mostrato anziché eseguito, fai escape.
| Carattere | Con nome | Decimale | Esadecimale | Cosa si rompe se non fai escape |
|---|---|---|---|---|
< | < | < | < | Avvia un tag — il browser legge il testo seguente come markup |
> | > | > | > | Chiude un tag prematuramente |
& | & | & | & | Avvia un’entità — il resto può essere interpretato male come riferimento |
" | " | " | " | Termina in anticipo un valore di attributo tra virgolette doppie |
' | ' | ' | ' | Termina in anticipo un valore di attributo tra virgolette singole |
L’entità HTML della e commerciale è la radice dell’intero sistema. Il carattere & inizia ogni entità, quindi va sottoposto a escape per primo: se fai escape delle parentesi angolari prima della e commerciale, ti ritrovi a fare di nuovo l’escape della & nelle entità che hai appena prodotto. Più sotto vediamo perché.
Quando serve davvero fare escape? (in base al contesto)
È qui che si annida la maggior parte dei bug e delle vulnerabilità. La regola è una sola: fai escape al momento dell’output, in base al contesto in cui finisce il valore. Un valore sicuro in un punto è pericoloso in un altro, perciò la codifica che applichi deve corrispondere alla destinazione.
Contenuto di un elemento HTML
Quando inserisci un valore tra i tag, dentro un <p>, un <div> o un <td>, fai escape di <, > e &. Qui fare escape delle virgolette è innocuo ma superfluo. Se vuoi mostrare il testo <strong> come caratteri letterali invece di rendere grassetto la parola successiva, codificalo in <strong> e il browser stampa il tag anziché applicarlo.
Valori di attributo HTML
Dentro un attributo, i caratteri di virgoletta diventano cruciali. Se un valore sta in title="…" e contiene un " non sottoposto a escape, termina l’attributo in anticipo e permette a un attaccante di aggiungere nuovi attributi, un classico vettore XSS. Fai escape di " (e idealmente di ') nel contesto degli attributi. Un valore come He said "hi" deve diventare He said "hi" per restare contenuto.
Dentro <script> o JavaScript inline
Qui le entità HTML non aiutano. Una stringa inserita in un blocco <script> o in un gestore di eventi inline ha bisogno dell’escape delle stringhe JavaScript o JSON, non dei riferimenti a carattere. Scrivere " dentro un literal di stringa JS produce i sei caratteri letterali, non una virgoletta. Per questo contesto, usa lo strumento Escape JSON e leggi la guida completa all’escape delle stringhe JSON per le regole \uXXXX che si applicano davvero dentro uno script.
Dentro un URL
Un URL ha il suo schema di escape: la codifica percentuale. Le entità HTML non rendono sicuro un valore per gli URL. La stringa a&b c in una query va scritta come a%26b%20c, non come a&b c: lo spazio continua a rompere l’URL e la & continua a separare i parametri. Usa il Codificatore / Decodificatore URL per questo, e la guida alla codifica e decodifica degli URL per le regole complete sui caratteri riservati e non riservati.
La matrice decisionale
| Contesto | Fai escape con | Esempio | Scelta sbagliata che fallisce |
|---|---|---|---|
| Contenuto di elemento HTML | Entità HTML (< > &) | <strong> → <strong> | Lasciare < grezzo inietta un tag |
| Valore di attributo HTML | Entità HTML (" ' cruciali) | "hi" → "hi" | Un " non sottoposto a escape esce dall’attributo |
<script> / JS inline | Escape delle stringhe JS / JSON | " → \" | Le entità HTML sono inerti in JS |
| URL / query string | Codifica percentuale | spazio → %20 | & e le entità rompono comunque l’URL |
Con nome o numeriche: quali usare?
Le entità con nome sono leggibili e sono la scelta predefinita giusta per i comuni caratteri riservati e i simboli ben noti: <, &, ©, —. Esistono però solo per i caratteri che hanno un nome definito. Le entità numeriche, decimali o esadecimali, possono codificare qualsiasi code point, compresi quelli senza nome, il che le rende il ripiego universale. Quando non puoi garantire che il sistema ricevente supporti una particolare entità con nome, la numerica è la scelta sicura.
Perché l’apostrofo è ' e non '
L’entità con nome ' è stata introdotta solo in HTML5 e XML. È indefinita in HTML4, perciò una manciata di parser e client di posta più datati la renderizzano come testo letterale ' invece di un apostrofo. Il riferimento numerico ', e il suo gemello decimale ', punta esattamente allo stesso carattere, U+0027, ed è compreso da ogni parser conforme mai scritto. Le librerie di escape ben collaudate come he emettono ' per l’apice singolo proprio per questo motivo, e un buon encoder segue quella convenzione perché l’output sia sicuro da inserire in qualsiasi contesto HTML, XML o di attributo.
Charset e entità: quando codificare i caratteri non-ASCII
Un set di caratteri, come UTF-8, decide come i caratteri vengono memorizzati come byte. Un’entità è un modo di scrivere un carattere usando solo ASCII semplice (&, #, ;, lettere, cifre). Sono livelli diversi, e confonderli porta a codifiche inutili.
Su una pagina UTF-8, cioè quasi ogni pagina moderna che dichiara <meta charset="utf-8">, lettere accentate, trattini ed emoji sono caratteri grezzi validi. Lascia é, — e 😀 esattamente come sono. Codificare tutto in entità conta solo quando il testo deve sopravvivere a un charset legacy a byte singolo o a un sistema che corrompe l’UTF-8 grezzo; una modalità “codifica tutti i non-ASCII” esiste proprio per questi casi. Se non sei sicuro di come si relazionino byte, code point e caratteri, la guida alla codifica UTF-8, UTF-16 e Unicode ne illustra il modello.
Insidie comuni delle entità HTML
Fare escape della & per ultima causa il doppio escape
L’ordine conta. Se sostituisci < e > prima di &, le entità che hai appena creato (<, >) si vedono sottoporre a escape anche la loro & iniziale, così < finisce come &lt; e renderizza come il testo letterale <. Fai sempre escape della & per prima, poi del resto. È la singola regola che evita il bug di codifica più frequente.
Doppia codifica di testo già sottoposto a escape
Passare di nuovo attraverso un encoder un testo già sottoposto a escape lo ricodifica. & diventa &amp;, e il visitatore vede & sulla pagina invece di &. Fai escape esattamente una volta, al momento dell’output. Se un valore attraversa più livelli, assicurati che solo uno di essi faccia escape.
Mojibake durante la decodifica
Andare nella direzione opposta ha la sua trappola. Decodifica con il charset sbagliato, o decodifica due volte, e ottieni un output illeggibile: il classico mojibake. Se una pagina mostra il letterale &lt; dove ti aspettavi <, incollalo nel Decodifica entità HTML per vedere esattamente in cosa si risolvono le entità; gestisce nomi, decimali, esadecimali e perfino i riferimenti legacy non terminati come © senza punto e virgola finale.
Affidarsi all’escape come cura completa contro l’XSS
L’escape è la prima linea di difesa, non l’unica. Poiché l’HTML ha diversi contesti con regole diverse, fare escape per quello sbagliato lascia un buco: virgolette negli attributi, escape JS negli script, codifica percentuale negli URL. Abbina un escape corretto e consapevole del contesto a una Content Security Policy e all’auto-escape del tuo framework, così se una linea cede ne resta un’altra dietro.
Come codificare e decodificare le entità nella pratica
Quando costruisci l’HTML a mano, fai l’escape tu stesso. Ecco una escapeHtml() corretta che gestisce l’ordinamento con la & per prima, più la pratica migliore per il codice applicativo reale.
// The five reserved characters and their safe entities:
// < → < > → > & → & " → " ' → '
function escapeHtml(str) {
return str
.replace(/&/g, '&') // & FIRST, so later entities are not double-escaped
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, '''); // numeric form — safe in HTML4, HTML5 and XML
}
const userInput = `<a href="x">Tom & Jerry's</a>`;
const safe = escapeHtml(userInput);
// → <a href="x">Tom & Jerry's</a>
// Better in app code: let the platform escape for you.
// el.textContent = userInput; // the browser escapes; no manual replace
// React / Vue / Angular escape interpolated text by default
// Server templates (Jinja, ERB, Blade) auto-escape unless you opt out
La funzione fatta a mano è utile per capire cosa succede e per le conversioni occasionali, ma in produzione preferisci la via integrata. Impostare element.textContent lascia che sia il browser a fare l’escape per te, e i framework moderni fanno escape automaticamente dei valori interpolati. Riserva l’escape manuale ai casi che la piattaforma non copre.
Per il lavoro estemporaneo, Codifica entità HTML fa escape dell’insieme riservato (con nome, decimale o esadecimale), e Decodifica entità HTML lo inverte. I due sono inversi esatti per i caratteri riservati, così puoi far compiere al testo l’andata e il ritorno tra entrambi senza perdite.
Domande frequenti
Cos’è un’entità HTML?
Un’entità HTML è un codice breve, che inizia con & e finisce con ;, e rappresenta un singolo carattere. Il browser renderizza il carattere a cui l’entità punta invece di trattarlo come markup. Per esempio, < mostra un < letterale e & mostra una & letterale.
A quali caratteri devo fare escape in HTML?
I cinque caratteri speciali HTML riservati: <, >, &, " e '. Nel contenuto degli elementi ti servono soprattutto <, > e &; nei valori di attributo diventano cruciali anche le virgolette " e '. Fai escape della & per prima così le altre entità non subiscono un doppio escape.
Dovrei usare entità con nome o numeriche (decimali/esadecimali)?
Usa le entità con nome (<, ©) per leggibilità con i caratteri comuni, dato che sono facili da riconoscere. Usa le entità numeriche (decimale < o esadecimale <) quando devi codificare un carattere senza nome definito, o quando non puoi garantire che il consumatore supporti una data entità con nome. Entrambe le forme fanno riferimento allo stesso code point.
Le entità HTML proteggono dall’XSS?
Sono la base, se applicate correttamente. Fare escape dei cinque caratteri riservati prima di inserire input non attendibile nel contenuto di un elemento o di un attributo HTML ferma l’iniezione di tag e script. Ma l’escape dipende dal contesto: i blocchi script richiedono l’escape JavaScript e gli URL la codifica percentuale. Combina un escape corretto e consapevole del contesto con CSP e auto-escape del framework.
Perché la mia pagina mostra &lt; invece di <?
È un doppio escape: il testo è stato codificato due volte, oppure la & è stata sottoposta a escape dopo le parentesi angolari, così la & in < è diventata &. Il visitatore vede quindi < come testo letterale. Fai escape esattamente una volta e fai sempre escape della & per prima. Lo strumento di decodifica può confermare in cosa si risolvono le entità.
Devo fare escape di caratteri come é, — o emoji?
Di solito no. Su una pagina che dichiara <meta charset="utf-8">, lettere accentate, trattini ed emoji sono caratteri grezzi validi e non hanno bisogno di codifica: lasciali così come sono. Codifica i non-ASCII solo quando il testo deve attraversare un charset legacy a byte singolo o un sistema che corrompe l’UTF-8 grezzo.