Command Palette

Search for a command to run...

innerHTML vs textContent: Seguridad y Rendimiento

Comprende las diferencias críticas entre las propiedades de manipulación de contenido y cómo evitar vulnerabilidades XSS. Aprende los vectores de ataque y las mejores prácticas de seguridad.

Lectura: 16 min
Nivel: Principiante

TL;DR - Resumen rápido

  • textContent es la forma más rápida y segura de insertar texto puro.
  • innerText respeta estilos CSS pero provoca reflows costosos.
  • innerHTML parsea y renderiza HTML, pero elimina event listeners existentes.
  • Usar innerHTML con datos de usuario sin sanitizar abre vulnerabilidades XSS críticas.
  • Los ataques XSS no solo vienen de <script>, también de onerror, onclick, onload, etc.
  • outerHTML reemplaza el elemento completo, incluyéndose a sí mismo.

Introducción a las Propiedades de Contenido

Cuando necesitas leer o modificar el contenido de un elemento del DOM, tienes tres opciones principales: innerHTML, textContent e innerText. Aunque parecen similares, funcionan de maneras muy diferentes tras bambalinas.

Elegir la propiedad incorrecta puede llevar a problemas de rendimiento en tu aplicación o, peor aún, a vulnerabilidades de seguridad críticas como Cross-Site Scripting (XSS).

textContent vs innerText

A primera vista, ambos parecen hacer lo mismo: manipular texto. Sin embargo, textContent es una propiedad estándar del DOM, mientras que innerText fue introducida por Internet Explorer y luego estandarizada, comportándose de manera diferente respecto a los estilos CSS.

textContent-vs-innerText.js
Loading code...

La diferencia clave es el rendimiento y la visibilidad. textContent devuelve todo el texto contenido en el nodo y sus descendientes de forma muy rápida, mientras que innerText es consciente del estilo CSS: no devolverá texto oculto con display: none y debe calcular el estilo, lo que provoca un reflow (repintado) costoso.

Consejo de Rendimiento

Usa siempre textContent a menos que necesites específicamente el texto tal como lo ve el usuario (respetando CSS).

innerHTML en Detalle

innerHTML no es inherentemente malo. De hecho, es muy útil cuando trabajas con HTML que tú controlas completamente. El problema surge cuando introduces datos externos sin validar.

¿Qué hace innerHTML realmente?

Cuando asignas un string a innerHTML, el navegador parsea ese string como HTML, construye un árbol DOM interno y lo inserta en el elemento. Este proceso implica:

  1. <strong>Elimina todo el contenido existente</strong>, incluyendo event listeners adjuntos
  2. <strong>Parsea el string HTML</strong> con el motor de parsing del navegador
  3. <strong>Crea nuevos nodos DOM</strong> basándose en el HTML parseado
  4. <strong>Inserta los nodos</strong> en el árbol DOM
innerhtml-behavior.js
Loading code...

Este comportamiento es importante entenderlo: innerHTML no "agrega" contenido, lo reemplaza completamente. Si necesitas agregar contenido, usa insertAdjacentHTML o mejor aún, append con elementos creados.

innerHTML elimina event listeners

Cuando usas innerHTML, todos los event listeners del contenido previo se pierden porque los elementos son destruidos y recreados. Si necesitas preservar eventos, usa métodos de inserción de nodos como append.

innerHTML y Riesgos de Seguridad (XSS)

innerHTML es poderoso porque permite insertar estructura HTML completa desde un string. Sin embargo, este poder conlleva una gran responsabilidad.

El Ataque XSS (Cross-Site Scripting)

Si insertas contenido que proviene de una fuente no confiable (como un input de usuario o una API externa) directamente en innerHTML, un atacante puede inyectar scripts maliciosos.

security-risk.js
Loading code...

Aunque HTML5 especifica que los tags <script> insertados vía innerHTML no deben ejecutarse, hay muchas otras formas de ejecutar JavaScript, como se muestra en el ejemplo con onerror en una imagen.

Regla de Oro

NUNCA uses innerHTML con datos sin sanitizar provenientes del usuario. Si solo necesitas insertar texto, usa SIEMPRE textContent.

Vectores de Ataque XSS más Allá de <script>

Un error común es pensar que solo las etiquetas <script> son peligrosas. En realidad, HTML5 especifica que scripts insertados vía innerHTML no se ejecutan, pero hay docenas de otros vectores que sí funcionan.

xss-vectors.js
Loading code...

Estos son solo algunos ejemplos. Existen literalmente cientos de vectores de ataque XSS documentados. La única defensa real es nunca confiar en datos externos y usar textContent cuando insertes texto, o sanitizar el HTML con librerías especializadas.

Content Security Policy (CSP)

Una defensa adicional contra XSS es implementar Content Security Policy en tu servidor. CSP permite definir qué scripts pueden ejecutarse, bloqueando scripts inline maliciosos incluso si logran inyectarse en el HTML.

outerHTML: Reemplazar el Elemento Completo

Mientras innerHTML reemplaza el contenido del elemento, outerHTML reemplaza el elemento completo, incluyéndose a sí mismo. Es menos común pero útil en ciertos casos.

outerhtml-example.js
Loading code...

Ten cuidado: después de usar outerHTML, la referencia al elemento original se vuelve inválida porque el elemento fue reemplazado en el DOM. Si necesitas trabajar con el nuevo elemento, debes seleccionarlo nuevamente.

¿Cuándo usar cuál?

La elección depende de tu objetivo específico:

  • Usa textContent para insertar o leer TEXTO puro (90% de los casos).
  • Usa innerHTML solo cuando necesites renderizar HTML desde un string controlado por ti.
  • Usa innerText solo si necesitas leer el texto visible respetando CSS (raro).

Alternativa Segura para HTML

Si necesitas construir estructuras complejas, es más seguro y eficiente usar createElement y append.

safe-insertion.js
Loading code...

Si realmente necesitas insertar HTML y no confías en la fuente, usa una librería de sanitización como DOMPurify. Pero pregúntate primero: ¿realmente necesitas HTML, o solo texto?

Errores Comunes

Estos son los errores más frecuentes al trabajar con estas propiedades, especialmente cuando se está aprendiendo sobre seguridad web.

Error 1: Pensar que innerHTML += es eficiente

Usar innerHTML += para agregar contenido parece conveniente, pero es muy ineficiente porque reconstruye todo el HTML existente desde cero.

innerhtml-append-error.js
Loading code...

Error 2: Confiar en validación del lado del cliente

Validar datos en JavaScript del lado del cliente no es suficiente. Un atacante puede saltarse tu validación fácilmente con herramientas de desarrollo o llamadas directas a tu API.

client-validation-error.js
Loading code...

La validación y sanitización deben ocurrir siempre en el servidor. La validación del cliente es solo para mejorar la experiencia de usuario, no para seguridad.

Defensa en profundidad

La mejor estrategia de seguridad es usar múltiples capas: validación del servidor, uso de textContent por defecto, Content Security Policy, y sanitización cuando innerHTML es inevitable.

Resumen: Seguridad y Rendimiento en Manipulación de Contenido

Conceptos Principales:

  • textContent es rápido, seguro y adecuado para el 90% de casos
  • innerText provoca reflows porque considera estilos CSS
  • innerHTML parsea HTML y elimina event listeners existentes
  • XSS no solo viene de <script>, también onerror, onclick, onload
  • outerHTML reemplaza el elemento completo, no solo su contenido

Mejores Prácticas:

  • Usa textContent por defecto, siempre que insertes texto puro
  • NUNCA uses innerHTML con datos de usuario sin sanitizar
  • Valida y sanitiza en el servidor, no solo en el cliente
  • Usa createElement y append para estructuras HTML complejas
  • Implementa Content Security Policy para defensa adicional