Codificación de entidades HTML vs codificación de URL: diferencias clave
La codificación de entidades HTML convierte caracteres como <, >, & y " en entidades HTML (<, >, &, ") para mostrarlos de forma segura en páginas web. La codificación de URL convierte caracteres al formato %XX para transmitirlos de forma segura en las URL. Protegen frente a distintos tipos de ataques y se utilizan en contextos diferentes.
¿Qué es la codificación de entidades HTML?
La codificación de entidades HTML (también llamada escape de HTML) convierte los caracteres que tienen un significado especial en HTML en referencias de entidad que los navegadores muestran como el carácter literal en lugar de interpretarlos como marcado. Los caracteres más importantes que hay que codificar son <, >, &, " y '.
Sin la codificación HTML, una cadena como <script>alert('XSS')</script> sería ejecutada como JavaScript por el navegador. Con la codificación, se convierte en <script>alert('XSS')</script> y se muestra como texto inofensivo.
Las entidades HTML pueden escribirse de dos formas: entidades con nombre como &, < y ", o entidades numéricas como &, < y ". Las entidades numéricas usan el punto de código Unicode del carácter y pueden representar cualquier carácter Unicode.
<!-- Antes de la codificación HTML -->
<p>The formula is: x < y & y > z</p>
<!-- ¡El navegador interpreta < como el inicio de una etiqueta! -->
<!-- Después de la codificación HTML -->
<p>The formula is: x < y & y > z</p>
<!-- El navegador muestra: x < y & y > z -->
<!-- Entidades HTML comunes -->
& → & (ampersand / signo &)
< → < (menor que)
> → > (mayor que)
" → " (comillas dobles)
' → ' (comilla simple / apóstrofo)
→ (espacio de no separación)
¿Qué es la codificación de URL?
La codificación de URL (percent-encoding) convierte los caracteres que no son seguros en las URL en un signo de porcentaje seguido de dos dígitos hexadecimales que representan el valor del byte. Está definida por el RFC 3986 y garantiza que las URL contengan únicamente caracteres ASCII válidos que puedan transmitirse de forma segura por internet.
La codificación de URL es necesaria porque las URL tienen una sintaxis estricta en la que ciertos caracteres actúan como delimitadores (/, ?, &, #, =). Cuando estos caracteres aparecen en los datos (como los valores de los parámetros de consulta), deben codificarse para evitar que se interpreten como elementos estructurales.
// Ejemplos de codificación de URL
space → %20
& → %26
= → %3D
? → %3F
# → %23
/ → %2F
+ → %2B
// URL completa con un parámetro de consulta codificado
https://example.com/search?q=salt%20%26%20pepper
// El valor de q es "salt & pepper"
Tabla comparativa
| Característica | Codificación de entidades HTML | Codificación de URL |
|---|---|---|
| Propósito | Mostrar de forma segura en páginas HTML | Transmitir de forma segura en las URL |
| Estándar | Especificación HTML/WHATWG | RFC 3986 |
| Formato | &name; o &#number; |
%XX (valor del byte en hexadecimal) |
| El espacio se convierte en | (de no separación) o se deja igual |
%20 o + |
| & se convierte en | & |
%26 |
| < se convierte en | < |
%3C |
| Previene | Ataques XSS, HTML roto | URL rotas, ataques de inyección |
| Contexto | Cuerpo y atributos del documento HTML | Rutas, cadenas de consulta y fragmentos de URL |
| Función JS | Sin función integrada (usa una librería o las API del DOM) | encodeURIComponent() |
¿Cuándo necesitas ambas?
Hay situaciones habituales en las que necesitas tanto la codificación HTML como la codificación de URL. El caso más frecuente es cuando colocas una URL dentro de un atributo HTML, como un atributo href o src. Primero hay que codificar correctamente la URL con codificación de URL y, a continuación, cualquier carácter HTML especial del resultado debe codificarse con codificación HTML.
<!-- Paso 1: codifica con URL el valor del parámetro de consulta -->
<!-- Valor: "Tom & Jerry" → codificado con URL: "Tom%20%26%20Jerry" -->
<!-- Paso 2: construye la URL -->
<!-- URL: https://example.com/search?q=Tom%20%26%20Jerry -->
<!-- Paso 3: codifica con HTML la URL para usarla en un atributo href -->
<a href="https://example.com/search?q=Tom%20%26%20Jerry">
Search for Tom & Jerry
</a>
<!-- En este caso, las secuencias % no necesitan codificación HTML -->
<!-- porque % no es un carácter HTML especial -->
<!-- Pero si la URL contiene & como delimitador, DEBE codificarse con HTML: -->
<a href="https://example.com/search?q=cats&sort=name">
Search cats sorted by name
</a>
<!-- Sin &, el navegador podría interpretar &sort como una entidad HTML -->
En los frameworks modernos como React, Vue y Angular, la codificación HTML se gestiona automáticamente cuando usas expresiones de plantilla o JSX. Sin embargo, la codificación de URL todavía debe realizarse de forma explícita al construir URL a partir de datos dinámicos.
// React: la codificación HTML es automática, la de URL no
function SearchLink({ query }) {
// La codificación de URL debe ser explícita
const url = '/search?q=' + encodeURIComponent(query);
// La codificación HTML es automática en JSX
return <a href={url}>Search for {query}</a>;
// React codifica automáticamente con HTML tanto el href como el contenido de texto
}
Prevención de XSS: qué codificación usar y dónde
La prevención del Cross-Site Scripting (XSS) exige aplicar la codificación correcta según el contexto en el que se coloque la entrada del usuario. Usar el tipo de codificación equivocado en un contexto determinado no ofrece ninguna protección.
- Contexto del cuerpo HTML: usa la codificación de entidades HTML. Esto evita que las etiquetas inyectadas como
<script>se interpreten como marcado. - Contexto de atributo HTML: usa la codificación de entidades HTML y entrecomilla siempre los valores de los atributos. Los atributos sin comillas pueden vulnerarse incluso con codificación HTML.
- Contexto de URL (href, src): usa la codificación de URL para las partes dinámicas y, después, codifica con HTML toda la URL si la colocas en HTML. Valida que la URL empiece por un esquema seguro (
https:) para evitar URL de tipojavascript:. - Contexto de JavaScript: usa el escape de cadenas de JavaScript (JSON.stringify o una librería específica). Ni la codificación HTML ni la de URL son suficientes en un contexto de JavaScript.
- Contexto de CSS: usa el escape de CSS. La codificación HTML y la de URL no protegen frente a la inyección de CSS.
El principio clave es: codifica para el contexto de salida, no para el origen de entrada. Una misma entrada de usuario puede necesitar codificaciones diferentes según dónde aparezca en la respuesta. Nunca confíes únicamente en la validación de entrada para prevenir el XSS; aplica siempre la codificación de salida.