Codificatore / Decodificatore entità HTML
Converti i caratteri speciali in entità HTML e viceversa.
Entità HTML comuni
| Carattere | Entità | Numerica | Descrizione |
|---|---|---|---|
| & | & | & | E commerciale |
| < | < | < | Minore di |
| > | > | > | Maggiore di |
| " | " | " | Virgolette doppie |
| ' | ' | ' | Apostrofo |
| |   | Spazio insecabile | |
| © | © | © | Copyright |
| ® | ® | ® | Marchio registrato |
| ™ | ™ | ™ | Marchio commerciale |
| € | € | € | Simbolo dell'euro |
Perché usare le entità HTML?
I caratteri come <, > e & hanno un significato speciale in HTML. Se li includi letteralmente nel tuo HTML, il browser li interpreta come codice, non come contenuto. Codificare questi caratteri in entità evita problemi di rendering e vulnerabilità di cross-site scripting (XSS).
Domande frequenti
Qual è la differenza tra entità nominate e numeriche?
Le entità nominate usano nomi descrittivi (&, ©) mentre le entità numeriche usano punti di codice Unicode (&, ©). Entrambe vengono visualizzate in modo identico. Le entità nominate sono più leggibili; le entità numeriche funzionano per qualsiasi carattere Unicode.
Devo codificare tutti i caratteri speciali?
Come minimo, devi codificare &, <, > e " nel contenuto HTML e nei valori degli attributi. I browser moderni gestiscono la maggior parte degli altri caratteri nativamente se il tuo documento usa la codifica UTF-8.
Tre forme, un carattere
Un'«entità» HTML, formalmente una character reference: è una sequenza di escape che rappresenta un carattere tramite una sequenza di normali caratteri ASCII. L'HTML Living Standard definisce tre forme sintattiche concrete:
- Denominato:
&seguito da un nome dalla tabella delle named-character-reference WHATWG, terminato da un punto e virgola. Esempio:©per ©. - Decimale numerico:
&#seguito dal code point Unicode in base 10, terminato da un punto e virgola. Esempio:©. - Esadecimale numerico:
&#xseguito dal code point in base 16, terminato da un punto e virgola. Esempio:©.
Tutte e tre le forme sono intercambiabili quando renderizzate: ©, © e © producono tutte il carattere visibile © perché si risolvono tutte nel code point Unicode U+00A9. La scelta tra di esse è una questione di leggibilità del codice sorgente, non del comportamento del browser. Il formato esadecimale tende a corrispondere alle tabelle Unicode pubblicate (che usano la notazione U+XXXX), quindi ♥ è più vicino alla notazione ufficiale U+2665 che ♥. I riferimenti numerici funzionano per qualsiasi carattere Unicode, incluse le emoji del piano astrale: 😀 si renderizza come 😀 (U+1F600 GRINNING FACE).
Perché esistono le entità
Tre ragioni storiche e pratiche distinte:
- Per fare l'escape dei caratteri con significato sintattico in HTML. Il parser usa certi caratteri ASCII come simboli di controllo.
<apre un tag,>lo chiude,&introduce un riferimento e i caratteri di virgolettatura delimitano i valori degli attributi. Se si vuole che qualcuno di questi appaia come testo letterale, è necessario fare l'escape. - Per rappresentare caratteri non disponibili nella codifica del documento. Prima che UTF-8 diventasse universale sul web (ha superato il 50% solo intorno al 2010), la maggior parte dell'HTML veniva servito come US-ASCII, ISO-8859-1 o Windows-1252. In quelle codifiche a byte singolo, caratteri come ©, €, ≈ o α semplicemente non potevano essere espressi da un byte letterale. Scrivere
©,€o≈era l'unico modo per raggiungere quei code point. - Per segnalare l'intento dell'autore per i caratteri invisibili o ambigui. Anche su una pagina UTF-8, uno spazio non divisibile letterale (U+00A0) è visivamente identico a uno spazio normale; scrivere
rende l'intento ovvio a chiunque legga il sorgente.
Il W3C ora raccomanda di usare caratteri Unicode letterali dove possibile invece delle entità, «per accessibilità e leggibilità.» Le entità rimangono utili per i cinque escape obbligatori, più i caratteri genuinamente invisibili o ambigui.
I cinque fondamentali
I cinque caratteri che è assolutamente necessario sottoporre a escape quando si inserisce contenuto non attendibile in HTML sono <, >, &, " e '. Il Cross-Site Scripting Prevention Cheat Sheet di OWASP li enumera come il set minimo di escape richiesti:
| Carattere | Denominato | Decimale | Esadecimale |
|---|---|---|---|
| < | < | < | < |
| > | > | > | > |
| & | & | & | & |
| " | " | " | " |
| ' | ' / ' | ' | ' |
La regola pratica: ogni volta che si inserisce testo non attendibile nell'output HTML, fare l'escape di questi cinque caratteri prima di tutto. Non farlo è la causa principale della grande maggioranza delle vulnerabilità XSS stored e reflected.
La trappola dell'apostrofo
' non fa parte di HTML 4; era originariamente definito solo da XML 1.0 ed ereditato in XHTML 1.0. Internet Explorer prima della versione 9 (rilasciata nel 2011) si rifiutava di renderizzarlo come ' e mostrava il testo letterale '. L'entità è stata aggiunta specificamente a HTML5 ed è ora sicura in ogni browser moderno, ma per la massima compatibilità cross-browser e cross-spec, OWASP e la maggior parte delle librerie di sanificazione enterprise raccomandano ancora di emettere ' invece di ' quando si esegue l'escape delle virgolette singole, in particolare nel codice critico per la sicurezza.
Quando codificare) e quando non farlo
La decisione di codifica dipende da dove il testo atterrerà nell'output, non da cosa contiene. Questo è il punto più frainteso nella sicurezza HTML. Le linee guida di OWASP distinguono i contesti:
- Contenuto di elemento HTML: fare l'escape di
< > & "(e'per massima cautela). - Valori degli attributi HTML: fare l'escape degli stessi più il carattere di virgolettatura; usare sempre attributi virgolettati.
- Contesto JavaScript: usare l'escape JavaScript, non l'escape HTML:
\xHHo\uHHHH. - Contesto CSS: usare l'escape CSS:
\HHseguito da uno spazio. - Contesto URL / parametro URI: usare la codifica percentuale (
%HH), non la codifica HTML.
Ogni contesto ha le proprie regole di escape. Mescolarle è di per sé una vulnerabilità: ad esempio, la codifica percentuale di < in %3C non protegge dall'XSS nel contesto di elemento HTML, dove %3C è solo il testo letterale %3C.
Evitare la doppia codifica. Un bug comune è fare l'escape dei dati quando vengono letti nel sistema, di nuovo quando vengono memorizzati, di nuovo quando vengono letti e di nuovo quando vengono renderizzati. Il risultato: l'utente ha digitato 5 < 10, il database memorizza 5 &lt; 10, la pagina renderizza 5 < 10 invece dell'originale. La disciplina è: memorizzare Unicode grezzo, codificare una volta sola, al momento dell'output, per il contesto specifico.
Codifica HTML vs codifica URL
Due sistemi di escape diversi per due contesti diversi, spesso confusi:
| Entità HTML | URL / percentuale | |
|---|---|---|
| Standard | HTML Living Standard | RFC 3986 |
| Formato | &name; o &#NN; | %HH (byte esadecimale) |
| Contesto | Markup HTML, corpo degli elementi e attributi | URL, stringhe di query, body di richiesta con codifica form |
| Spazio | (non divisibile), mai uno spazio normale | %20 o + |
| Funzione JS | - (gestito dal parser) | encodeURIComponent() / encodeURI() |
Un URL all'interno di un valore di attributo HTML riceve entrambe le codifiche a strati: prima la codifica percentuale per i caratteri non consentiti negli URL, poi la codifica HTML per eventuali & < > " nell'URL risultante. Ecco perché le e commerciali nelle stringhe di query all'interno di un attributo href diventano & nella serializzazione HTML.
Una breve storia
HTML 2.0 (RFC 1866, 1995) ha ereditato il meccanismo di entità di SGML con circa 50 entità denominate per ISO Latin 1. HTML 3.2 (W3C, gennaio 1997) ha aggiunto le entità matematiche e simboliche. HTML 4.01 (W3C, dicembre 1999) ha finalizzato tre set di entità (Latin-1, Special e Symbol) per un totale di 252 entità denominate, che è la fonte della cifra «252» ancora vista nei tutorial più vecchi. HTML5 / WHATWG (Living Standard, in corso) ha assorbito e ampliato notevolmente la tabella a oltre 2.000 voci, principalmente per coprire MathML e un insieme Unicode più ampio. XML 1.0 (1998) definisce il proprio set minimale composto solo dai cinque fondamentali (< > & " '); quel set minimale è l'origine di '.
Altre domande
Nel codice moderno, cosa si dovrebbe usare?
Il codice in produzione generalmente non implementa manualmente la codifica delle entità, ma chiama una libreria. DOMPurify per la sanificazione HTML lato client. html.escape() nella libreria standard di Python. htmlspecialchars() in PHP. html/template in Go (auto-escape attivo per impostazione predefinita). OWASP Java Encoder per Java. In React, scrivere <div>{userInput}</div> esegue l'escape automaticamente; l'escape hatch dangerouslySetInnerHTML è denominato in modo da scoraggiarne l'uso casuale. Un encoder standalone come questo è utile come strumento di verifica/debug, non come sostituto di quelle librerie.
E i tag all'interno dei template email?
I client email più vecchi (Outlook in particolare) interpretano & non codificato come un attributo malformato e potrebbero rimuovere il markup circostante. Gli sviluppatori di email HTML imparano a codificare ogni carattere speciale in modo difensivo. Lo stesso vale per i sistemi BBCode-style dei forum che riscrivono il contenuto prima di memorizzarlo; i round-trip possono introdurre entità letterali inaspettate.
Cosa sono textContent e innerHTML in JavaScript?
La regola più importante per la prevenzione XSS in vanilla JavaScript: usare element.textContent = userInput anziché element.innerHTML = userInput. Impostare textContent scrive la stringa come testo letterale; il browser gestisce internamente tutto l'escaping. Impostare innerHTML analizza la stringa come HTML, eseguendo qualsiasi tag <script> o attributo di event-handler che contiene. Se il markup è genuinamente necessario, usare una libreria come DOMPurify per sanificare prima.
L'encoder può gestire le emoji?
Sì, tramite riferimenti numerici. Non esistono entità denominate per le emoji; usano tutte la forma numerica. 😀 si renderizza come 😀, ❤️ come il cuore rosso ❤️ (code point del cuore più il selettore di presentazione emoji). Il browser gestisce internamente la conversione implicita delle surrogate pair UTF-16; non si dovrebbero scrivere le metà surrogate manualmente.
Vengono inviati dati a un server?
No. La codifica e la decodifica sono trasformazioni di stringhe a funzione pura che girano interamente nel browser tramite JavaScript. Nulla del vostro input viene caricato; la pagina funziona offline una volta caricata. Questo è importante perché gli encoder basati su cloud che fanno il round-trip del payload di test possono diventare essi stessi un vettore XSS se il sito di test è compromesso.