HTML Encode / Decode

Escapa y desescapa entidades HTML para prevenir inyecciones al pintar contenido.

toolboox.app/herramientas/html-encode-decode

Herramienta

Resultado

Qué problema resuelve

Renderizar contenido de usuario sin abrir la puerta a XSS.

Escapar HTML consiste en sustituir los caracteres que el navegador interpreta como marcado (`<`, `>`, `&`, comillas) por sus entidades equivalentes, de modo que se muestren como texto en lugar de ejecutarse como código. Es la defensa fundamental contra el cross-site scripting, la vulnerabilidad que más años lleva en el top 10 de OWASP. Esta herramienta codifica y descodifica al instante, útil tanto para preparar contenido como para leer un fragmento escapado que llega en un log o en un correo.

Las cinco entidades imprescindibles

& se convierte en &amp;, < en &lt;, > en &gt;, " en &quot; y ' en &#39; (la entidad &apos; es válida en XML y HTML5, pero no en HTML4, así que la forma numérica es más portable). El orden importa: hay que escapar primero el ampersand, porque si lo haces al final convertirás los & de las entidades ya generadas y obtendrás &amp;lt;. Ese doble escapado es el motivo por el que a veces se ve literalmente &lt;b&gt; en una página: el contenido pasó dos veces por el mismo filtro.

El contexto manda: HTML, atributo, JavaScript y URL

No existe un escapado universal. Dentro del cuerpo de un elemento basta con escapar < y &. Dentro de un atributo hay que escapar también las comillas, o el valor se cerrará antes de tiempo y podrá inyectarse un onmouseover. Dentro de un bloque <script> el escapado HTML no protege: hay que serializar como JSON y escapar </. Y dentro de una URL lo que aplica es la codificación porcentual, no las entidades. Usar el escapado equivocado da una falsa sensación de seguridad; para las URL, el codificador de URL del sitio hace la conversión correcta.

Por qué el XSS sigue siendo la vulnerabilidad número uno

Un XSS almacenado permite ejecutar JavaScript en el navegador de cualquier visitante con la sesión de ese visitante: robar cookies no marcadas como HttpOnly, realizar peticiones autenticadas en su nombre o modificar lo que ve en pantalla. Se cuela por cualquier punto donde la aplicación pinte datos de usuario sin escapar: un nombre de perfil, un comentario, el asunto de un ticket, incluso un mensaje de error que refleja el parámetro recibido. Y basta con un punto olvidado en toda la aplicación.

Defensa en profundidad: escapado, sanitización y CSP

El escapado se aplica al pintar, no al guardar: si escapas en la entrada, luego no puedes saber si el dato original tenía realmente un <, y acabas con doble escapado en unos sitios y ninguno en otros. Cuando de verdad necesitas permitir HTML del usuario (un editor enriquecido), lo correcto es sanitizar con una lista blanca usando DOMPurify o equivalente, nunca con expresiones regulares propias. Encima de todo, una cabecera Content-Security-Policy que prohíba scripts en línea convierte muchos XSS en inofensivos; puedes añadirla desde el generador de .htaccess o desde el VirtualHost de Apache.

Frameworks modernos: seguros por defecto y sus escapes

React, Vue, Angular y los motores de plantillas actuales escapan automáticamente cualquier interpolación, y por eso el XSS clásico casi ha desaparecido de las aplicaciones nuevas. Los agujeros que quedan son las puertas traseras explícitas: dangerouslySetInnerHTML en React, v-html en Vue, bypassSecurityTrustHtml en Angular y cualquier manipulación directa de innerHTML. Cada aparición de esas APIs en el código debería llevar un comentario justificando por qué es segura y una sanitización delante. Buscarlas con grep -rn "innerHTML\|v-html\|dangerouslySet" src/ es una auditoría de cinco minutos que merece la pena.

Entidades para caracteres especiales y tipografía

Más allá de la seguridad, las entidades resuelven problemas de composición: &nbsp; evita que se separen "10" y "km" al final de una línea, &mdash; y &hellip; dan la raya y los puntos suspensivos correctos, y &#8203; inserta un punto de corte invisible en URLs largas. Con documentos en UTF-8 puedes escribir la mayoría de estos caracteres directamente, y es lo recomendable por legibilidad; reserva las entidades para los casos en los que el carácter es invisible o ambiguo en el editor.

Casos de uso comunes

  • Mostrar fragmentos de código HTML dentro de una página sin que se rendericen.
  • Preparar contenido de usuario para pintarlo de forma segura en una plantilla.
  • Leer un valor escapado que aparece en un log o en el cuerpo de un correo.
  • Insertar caracteres especiales y espacios de no separación en un texto.
  • Revisar si una entrada sospechosa de un WAF contenía marcado ejecutable.

Buenas prácticas

  • Escapa al pintar, nunca al guardar, y hazlo según el contexto de destino.
  • Escapa el `&` en primer lugar para evitar el doble escapado.
  • Sanea con lista blanca cuando debas permitir HTML real del usuario.
  • Añade Content-Security-Policy como segunda barrera frente a scripts en línea.

Preguntas frecuentes

¿Qué diferencia hay entre codificar HTML y codificar URL?

El escapado HTML sustituye caracteres de marcado por entidades (`&lt;`) para que el navegador no los interprete. La codificación de URL sustituye caracteres no permitidos en una dirección por `%XX`. No son intercambiables.

¿Por qué veo `&amp;lt;` en mi página?

Es doble escapado: el contenido pasó dos veces por el filtro. Escapa una sola vez y siempre en el momento de pintar.

¿Basta con escapar para evitar el XSS?

Es la defensa principal, pero debe ser contextual. Complétala con sanitización cuando permitas HTML y con una Content-Security-Policy que bloquee scripts en línea.

¿React me protege del XSS?

Escapa automáticamente toda interpolación, así que sí en el uso normal. El riesgo está en `dangerouslySetInnerHTML` y en la manipulación directa de `innerHTML`.

¿Debo usar `&apos;` o `&#39;`?

La forma numérica `&#39;` es más portable porque `&apos;` no existe en HTML4. Ambas funcionan en HTML5 y en XML.