man wearing headphones working on a laptop

Cómo forzar las cabeceras de la política de seguridad de contenido (CSP) en WordPress

La política de seguridad de contenido (CSP) es una función del navegador que bloquea el contenido no seguro. Indica al navegador qué recursos puede cargar, lo que puede evitar ataques como las secuencias de comandos entre sitios (XSS). También ayuda a evitar problemas de contenido mixto, que se producen cuando las páginas seguras cargan archivos no seguros.

Aunque la CSP pueda parecer complicada, no necesitas conocimientos técnicos avanzados para usarla: basta con una política inicial sencilla, una forma segura de probarla y unos pequeños ajustes. Esta guía explica cómo planificar una política, probarla de forma segura, aplicarla y mantenerla con el tiempo. Incluye un itinerario para principiantes que usa un plugin y otro para desarrolladores que utiliza cabeceras a nivel del servidor o del código.

Para quién es esta guía y cómo usarla

Esta guía se adapta a dos niveles de experiencia:

  • El itinerario para principiantes: tienes acceso de administración a WordPress, pero no quieres editar la configuración del servidor. Usarás un plugin para añadir la CSP y seguirás un ciclo de pruebas claro.
  • El itinerario para desarrolladores: puedes editar Apache, Nginx, las cabeceras de CDN o el código de WordPress. Quieres control directo, control de versiones y compatibilidad con nonces o políticas basadas en rutas.

Puedes leer primero los fundamentos comunes y después pasar directamente a tu itinerario.

Conceptos básicos de la CSP antes de empezar

Para implementar una política sólida, necesitas entender algunos términos:

  • Directiva: Es una regla para un tipo de recurso. Ejemplo: script-src controla JavaScript.
  • Expresión de origen: Es un valor dentro de una directiva. Ejemplo: ‘self’ o https://cdn.example.com.
  • ‘self’. Esto permite cargar recursos de tu propio dominio y subrecursos servidos desde él.
  • Modo de solo informes: El navegador registra las infracciones, pero sigue cargando los recursos bloqueados.
  • Modo de aplicación: El navegador bloquea las infracciones en lugar de limitarse a registrarlas.
  • Nonce: Un token aleatorio que incluye en la lista de permitidos un único script o estilo insertado para una solicitud.
  • Hash: Una huella basada en SHA que incluye en la lista de permitidos el texto exacto de un único script o estilo insertado.

Una cabecera CSP es una lista de directivas separadas por punto y coma. Los navegadores aplican las reglas a cada respuesta de página que incluye la cabecera.

Antes de configurar la CSP, asegúrate de que:

  • Puedes borrar todas las cachés. Esto incluye la caché de los plugins, de tu proveedor de hosting o de una CDN.
  • Puedes probar en un entorno de staging o durante un periodo de poco tráfico. La CSP puede alterar el diseño o el código de tu sitio si se configura incorrectamente.
  • Sabes qué servicios de terceros utiliza tu sitio. Esto incluye elementos como herramientas de analítica, fuentes, anuncios, contenido incrustado, pasarelas de pago y widgets de chat.

Decide las reglas de la política

Al elegir qué recursos permitir, ten en cuenta:

  • Scripts (script-src): De elementos como plugins, herramientas de analítica y código insertado
  • Estilos (style-src): Como el CSS del tema y las fuentes externas
  • Imágenes (img-src): De tu biblioteca de medios y de servidores de imágenes externos
  • Conexiones (connect-src): De la REST API y de APIs externas
  • Otros recursos: Como fuentes, marcos, etc.

Empieza con una política sencilla. Por ejemplo:

default‑src 'self';
script‑src 'self' https://www.google‑analytics.com;
style‑src 'self' 'unsafe‑inline';
img‑src 'self' data:;

Esto permite archivos de tu sitio, scripts de Google Analytics, estilos insertados e imágenes insertadas. Más adelante puedes ampliarla.

En este punto, es hora de elegir tu itinerario. Si eres principiante, continúa con la siguiente sección. Si tienes más experiencia, baja hasta el itinerario para desarrolladores.

Itinerario para principiantes: añade la CSP con un plugin

Paso 1: instala y configura un plugin de CSP

Aquí usaremos el plugin Headers Security Advanced & HSTS WP, pero funciona cualquier plugin que te permita establecer cabeceras de respuesta personalizadas.

  1. Instala el plugin desde el directorio de plugins de WordPress.
  2. Ve a Ajustes → Encabezados de seguridad avanzados y HSTS de WP.
  3. Busca la sección Contenido de la cabecera CSP y pega tu política. Si necesitas ayuda para redactar una política, utiliza la sección «plantilla de política inicial» que aparece más abajo.
  4. Añade una URI de informes CSP si estás en modo de solo informe (recomendado). Puedes usar:
    • Un servicio como Report URI o los informes CSP de Sentry.
    • Tu propio endpoint si ya registras informes de seguridad.
  5. Guarda los ajustes.
  6. Borra todas las cachés.
Contenido de la cabecera CSP y ajustes del URI de informes

Plantillas de políticas iniciales

Elige la que coincida con tu configuración y después ajústala.

Plantilla estándar:

• default-src 'self';
• script-src 'self';
• style-src 'self' 'unsafe-inline';
• img-src 'self' data:;
• font-src 'self';
• connect-src 'self';

Configuración habitual de WordPress con Google Fonts y Google Analytics:

• default-src 'self';
• script-src 'self' https://www.google-analytics.com https://www.googletagmanager.com;
• style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
• font-src 'self' https://fonts.gstatic.com data:;
• img-src 'self' data:;
• connect-src 'self';

WordPress con contenido incrustado de YouTube:

• default-src 'self';
• script-src 'self';
• style-src 'self' 'unsafe-inline';
• img-src 'self' data: https://i.ytimg.com;
• frame-src https://www.youtube.com https://www.youtube-nocookie.com;

Paso 2: comprueba los informes

Después de activar el modo de solo informes, navega por tu sitio y revisa los informes. Puedes hacerlo con herramientas como Chrome DevTools, prestando atención a las advertencias de CSP.

Un informe habitual contiene claves como estas:

  • blocked-uri: el recurso que el navegador bloquearía en el modo de aplicación.
  • violated-directive: la regla que lo bloquearía.
  • source-file: la página en la que se produjo la infracción.

Tu tarea es sencilla:

  1. Decide si el recurso bloqueado es necesario y de confianza.
  2. Si lo es, añade su dominio a la directiva correspondiente.
  3. Guarda, borra la caché y vuelve a cargar la página.

Repite el proceso hasta que tus páginas esenciales no generen infracciones importantes.

Paso 3: pasa al modo de aplicación

Cuando los informes estén limpios, cambia al modo de aplicación.

  1. Sustituye la cabecera de solo informes por una cabecera CSP aplicada.
  2. Pega exactamente la misma política.
  3. Guarda y borra las cachés.
  4. Vuelve a cargar las páginas clave y confirma que no se bloquea ningún recurso esencial.

Seguirás viendo infracciones, pero ahora el navegador bloqueará lo que incumpla la política.

Método 1 del itinerario para desarrolladores: añade la CSP a nivel del servidor

¿Eres desarrollador y quieres tener más control? Hay dos formas principales de añadir una CSP a WordPress.

Apache, usando .htaccess 

En .htaccess añade lo siguiente, personalizándolo según sea necesario:

<IfModule mod_headers.c>
  Header set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;"
</IfModule>

Después de probarlo, cambia al modo de aplicación:

<IfModule mod_headers.c>
  Header set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;"
</IfModule>

Nginx

En el bloque del servidor, añade lo siguiente, adaptado a tu situación:

add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;" always;

Después, aplica lo siguiente:

add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;" always;

La palabra clave «always» garantiza que las cabeceras se envíen incluso en las respuestas de error.

CDN o un proxy inverso

Si tu CSP debe aplicarse en varios orígenes o quieres un único punto de control:

  • Añade la cabecera CSP a las reglas de cabeceras de respuesta de tu CDN.
  • Guarda la cadena de la política en el control de versiones si tu CDN admite la configuración como código.
  • Evita configurar la CSP tanto en el origen como en CDN, a menos que quieras sustituir el valor del origen.

Método 2 para desarrolladores: añade la CSP mediante código de WordPress

Puede que quieras incluir la CSP en WordPress cuando tu configuración requiera un comportamiento dinámico. Por ejemplo:

  • Necesitas políticas específicas para cada página, como una regla más estricta en las páginas del panel de administración.
  • Tienes previsto añadir nonces a los scripts integrados que controlas.
  • Quieres vincular la implementación de la CSP al despliegue del tema o del plugin.

Ejemplo con wp_headers:

<IfModule mod_headers.c>
  Header set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;"
</IfModule>

Después de hacer las pruebas, cambia la clave de la cabecera a Content-Security-Policy.

CSP avanzada en WordPress: nonces y hashes

Los scripts integrados son habituales en WordPress, ya que los maquetadores de páginas, los temas y los plugins pueden insertarlos. Hay tres formas de gestionarlos:

  • Permitir globalmente los scripts integrados con «unsafe-inline». Es el método más sencillo, pero no ofrece tanta seguridad como los demás.
  • Añadir hashes para bloques integrados específicos. Es una opción estable cuando el contenido no cambia con frecuencia.
  • Añadir nonces en cada solicitud. Este método es seguro y flexible, pero debes inyectar el nonce en cada bloque integrado que quieras permitir.

Supón que tu tema genera este script integrado:

<script>
  console.log("hi");
</script>

Puedes calcular un hash SHA 256 del contenido del script y añadirlo a script-src:

script-src 'self' 'sha256-BASE64HASHVALUE';

Este es un ejemplo de nonces con WordPress:

add_action('send_headers', function() {
  $nonce = base64_encode(random_bytes(16));
  $policy = "default-src 'self'; script-src 'self' 'nonce-$nonce'; style-src 'self' 'unsafe-inline';";
  header("Content-Security-Policy: $policy");
  add_filter('script_loader_tag', function($tag, $handle) use ($nonce) {
    return str_replace('<script ', '<script nonce="' . esc_attr($nonce) . '" ', $tag);
  }, 10, 2);
});

Este ejemplo añade el nonce a los scripts puestos en cola. Aun así, debes añadir el mismo atributo nonce a cualquier script integrado que generes en las plantillas.

Advertencia: Los nonces en un entorno con distintos plugins requieren trabajo. Si la mayoría de tus scripts integrados proceden de plugins de terceros, los hashes o un «unsafe-inline» cuidadosamente delimitado pueden ser una opción más práctica.

Problemas habituales de CSP en WordPress y sus soluciones

Estos son algunos elementos que pueden causar problemas y cómo ajustar la configuración para cada uno:

Maquetadores de páginas y temas con CSS integrado

  • Problema: el diseño aparece sin estilos.
  • Solución: mantén «unsafe-inline» en style-src o cambia a hashes si controlas los bloques integrados.

Herramientas de analítica y gestores de etiquetas de terceros:

  • Problema: la consola muestra scripts bloqueados de Google u otras herramientas.
  • Solución: añade sus dominios a script-src.

Scripts de pago y de la página de pago:

  • Problema: los botones de pago no funcionan o los marcos de pago integrados no se cargan.
  • Solución: añade los dominios de pago a script-src, connect-src y frame-src según sea necesario.

Contenido multimedia o publicaciones sociales integrados:

  • Problema: hay contenedores de contenido integrado vacíos.
  • Solución: añade los dominios de los proveedores a frame-src o img-src.

Un resumen rápido

Aquí tienes un breve resumen de los pasos para implementar una CSP y mantenerla a lo largo del tiempo.

  1. Redacta primero una política pequeña.
    • Empieza con default-src ‘self’.
    • Añade únicamente las directivas que sepas que necesitas, normalmente script-src, style-src, img-src, font-src y connect-src.
    • Mantén corta la lista de permitidos. Cada dominio debe tener una finalidad.
  2. Ejecuta la política en modo de solo informe.
    • Establece Content-Security-Policy-Report-Only.
    • Navega por varias páginas, no solo por la página de inicio. Incluye entradas, archivos, formularios y páginas de pago.
    • Recopila los informes en DevTools o en un endpoint de informes.
  3. Analiza las infracciones.
    • Lee primero violated-directive. Eso te indica qué debes corregir.
    • Comprueba blocked-uri. Decide si el recurso es de confianza y necesario.
    • Si lo es, añade el origen a la directiva correspondiente. Si no, déjalo bloqueado.
    • Cambia una sola cosa cada vez y vuelve a hacer las pruebas.
  4. Aplica la política cuando los informes estén limpios.
    • Cambia a Content-Security-Policy con la misma política.
    • Vacía las cachés, vuelve a cargar las páginas clave y confirma que el sitio funciona.
    • Vigila la consola por si aparece alguna sorpresa de última hora.
  5. Endurécela con cuidado.
    • Si controlas el código integrado, cambia de «unsafe-inline» a hashes o nonces.
    • Si los plugins de terceros inyectan scripts integrados que no puedes modificar, acepta el riesgo concreto y documéntalo.
  6. Mantén la política.
    • Después de añadir plugins o funciones nuevas, adáptala a los nuevos orígenes.
    • Revisa la lista de permitidos cada pocos meses y elimina las entradas obsoletas.

Esta configuración requiere tiempo al principio. Pero, una vez en funcionamiento, bloqueará muchos ataques habituales y reducirá los problemas de contenido mixto. Proporcionará a tu sitio de WordPress una base de seguridad más sólida.

Cómo encaja la CSP con otras cabeceras de seguridad de WordPress

Junto con la CSP, considera estas cabeceras de seguridad para WordPress:

  • Cabecera X-Frame-Options: Evita el clickjacking controlando qué sitios pueden insertar tus páginas en iframes.
  • Cabecera X-Content-Type-Options: nosniff: Evita los ataques de detección del tipo MIME.
  • Cabecera Referrer-Policy: Limita la cantidad de información del referente que se envía a sitios externos.
  • Seguridad de transporte estricta (HSTS): Obliga a los navegadores a utilizar únicamente HTTPS.

La CSP se centra en qué recursos pueden cargarse, mientras que estas otras cabeceras controlan cómo tratan los navegadores tu sitio y dónde puede insertarse.

Preguntas frecuentes

¿Qué es una política de seguridad de contenido (CSP)?

Una política de seguridad de contenido (CSP) es una cabecera HTTP que indica al navegador qué scripts, estilos, imágenes, fuentes y otros recursos pueden cargarse en una página.

En WordPress, la CSP ayuda a bloquear la carga de scripts maliciosos y contenido no seguro en tu sitio. Funciona enumerando los dominios permitidos y los tipos de recursos, y el navegador bloquea cualquier recurso que no coincida con las reglas. Esto dificulta que los atacantes inyecten código dañino en tu sitio de WordPress.

Los sitios de WordPress suelen utilizar muchos plugins, temas y servicios de terceros, por lo que la CSP puede ayudar a proteger los formularios, los inicios de sesión, las páginas de pago y las áreas del panel de administración. Puedes añadir la CSP mediante plugins, ajustes del servidor o código de PHP en tu sitio de WordPress.

¿Por qué debería añadir una cabecera CSP a mi sitio de WordPress?

Deberías añadir una cabecera CSP para reducir el riesgo de ataques de secuencias de comandos entre sitios (XSS), inyección de datos y problemas de contenido mixto en tu sitio de WordPress. La CSP limita los scripts y estilos que pueden ejecutarse, de modo que, aunque se añada un script dañino a tu página, es posible que el navegador no lo cargue. Esto ayuda a proteger los datos de los usuarios, las sesiones iniciadas, la información de pago y las áreas del panel de administración.

La CSP también ayuda a imponer el uso de HTTPS para los recursos y facilita saber de qué dominios externos depende tu sitio. Con el tiempo, puedes hacer más estricta tu política y eliminar los dominios innecesarios, lo que puede mejorar tanto la seguridad como las comprobaciones del rendimiento del sitio.

¿Es seguro añadir una cabecera CSP a un sitio activo de WordPress?

Puede ser seguro añadir una cabecera CSP a un sitio activo de WordPress, pero solo si haces pruebas exhaustivas primero. Si tu política es demasiado estricta, puede romper formularios, pasarelas de pago, herramientas de analítica, widgets de chat o diseños creados con constructores de páginas. El enfoque más seguro es empezar en modo de solo informes, recopilar los errores y aplicar después la política en modo de aplicación cuando tengas la certeza de que todo funciona.

En un sitio activo de WordPress, lo mejor es hacer las pruebas en una copia de staging si es posible, o utilizar una pequeña parte del tráfico. También deberías guardar una copia de seguridad de la configuración del servidor y de .htaccess antes de hacer cambios. Si algo deja de funcionar, puedes eliminar rápidamente la cabecera y restaurar la configuración anterior.

¿Cómo pruebo una política CSP en WordPress antes de aplicarla?

Puedes probar una política CSP en WordPress utilizando Content-Security-Policy-Report-Only en lugar de Content-Security-Policy. Así, el navegador sigue las reglas y registra las infracciones sin bloquear el contenido. Después, puedes consultar la consola de desarrollo del navegador o un servicio de informes para ver qué recursos están bloqueados.

Por ejemplo, puedes añadir una cabecera como esta:

Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self';

Después, visita distintas páginas de tu sitio, incluidos los formularios, las páginas de pago y el área de administración. Busca errores en la consola y ajusta los dominios permitidos. Cuando veas pocas infracciones o ninguna, puedes cambiar la cabecera a Content-Security-Policy y hacerla más estricta gradualmente.

¿Por qué mi CSP rompe Google Analytics, el píxel de Facebook u otros scripts?

CSP puede romper Google Analytics, el píxel de Facebook u otros scripts porque esos servicios se cargan desde dominios externos que no están incluidos en tu política. Por ejemplo, si tu CSP solo permite script-src ‘self’, cualquier script de http://www.google-analytics.com o connect.facebook.net se bloqueará. El navegador se negará a cargarlos y el seguimiento se detendrá.

Para solucionarlo, debes añadir los dominios necesarios a tu política. Por ejemplo:

script-src 'self' www.google-analytics.com connect.facebook.net;

También deberías evitar utilizar unsafe-inline salvo que sea absolutamente necesario. Si utilizas scripts insertados directamente, puedes cambiar a nonces o hashes para mejorar la seguridad.

¿Debería permitir unsafe-inline en mi política CSP de WordPress?

Deberías evitar unsafe-inline en tu política CSP de WordPress salvo que no tengas otra opción. Permitir unsafe-inline significa que el navegador puede ejecutar scripts y estilos insertados directamente, lo que abre la puerta a ciertos tipos de ataques de secuencias de comandos entre sitios. Si tu sitio utiliza constructores de páginas, plugins o temas que dependen en gran medida de scripts insertados directamente, CSP puede romper los diseños o la funcionalidad.

Si debes permitir unsafe-inline, deberías documentar el motivo y revisarlo periódicamente. A largo plazo, una opción mejor es migrar a nonces o hashes para scripts de confianza insertados directamente. También puedes utilizar una política más estricta para la interfaz pública y otra independiente, menos estricta, para el área de administración.

¿Cómo funcionan los nonces y los hashes en una CSP de WordPress?

Los nonces y los hashes te permiten autorizar scripts específicos insertados directamente sin habilitar unsafe-inline en todo tu sitio. Un nonce es un valor breve y aleatorio que cambia cada vez que se carga una página. Añades ese nonce a tu CSP y después lo incluyes en la etiqueta del script. El navegador solo ejecuta los scripts que tienen el nonce correcto.

Los hashes funcionan de forma similar. Calculas un hash criptográfico del contenido del script y añades ese hash a tu CSP. El navegador comprueba si el script coincide con el hash y solo lo ejecuta si es así. En WordPress, algunos plugins y temas pueden generar nonces o hashes por ti, o puedes añadirlos manualmente en la cabecera CSP y en los archivos de plantilla.

¿Puedo utilizar un plugin para añadir CSP a WordPress en lugar de código del servidor?

Puedes utilizar un plugin para añadir CSP a WordPress en lugar de editar el código del servidor. Muchos plugins de seguridad o de cabeceras te permiten configurar una cabecera Content-Security-Policy desde el panel de administración. Esto resulta útil si no te sientes cómodo editando .htaccess, la configuración de Nginx o los archivos de PHP. Los plugins suelen ofrecer una interfaz sencilla para añadir dominios permitidos y probar la configuración.

Sin embargo, es posible que los plugins no admitan todas las directivas o funciones avanzadas de CSP. También pueden añadir sobrecarga si generan cabeceras en cada solicitud. Si gestionas varios sitios de WordPress o necesitas un control detallado, la CSP a nivel de servidor (Apache o Nginx) suele ser más eficiente y fácil de gestionar para usuarios avanzados.

¿Con qué frecuencia debería actualizar mi política CSP en un sitio de WordPress?

Deberías revisar y actualizar tu política CSP en un sitio de WordPress cada 3–6 meses o siempre que añadas nuevos plugins, temas o servicios de terceros. Cada vez que instalas un plugin nuevo, puede cargar scripts, estilos o fuentes desde dominios nuevos que no están incluidos en tu política actual. Si esos dominios están bloqueados, algunos elementos pueden dejar de funcionar o no cargarse.

Durante cada revisión, deberías consultar la consola del navegador o el servicio de informes de CSP para comprobar si hay nuevos informes de infracciones. Después, puedes decidir si permites los dominios nuevos, haces más estrictas las reglas existentes o eliminas los dominios que ya no se utilizan. Mantener la política actualizada ayuda a conservar tanto la seguridad como la funcionalidad.

¿CSP sustituye otras medidas de seguridad de WordPress, como los cortafuegos o las copias de seguridad?

CSP no sustituye otras medidas de seguridad de WordPress, como los cortafuegos, el análisis de malware o las copias de seguridad. Es una capa más entre muchas. CSP ayuda a controlar qué recursos puede cargar el navegador, pero no detiene los ataques de fuerza bruta, las modificaciones de archivos, las vulnerabilidades de los plugins ni la pérdida de datos. Estos riesgos siguen gestionándose mediante cortafuegos, protección de acceso, escáneres de malware y copias de seguridad periódicas.

Para contar con una configuración de seguridad completa de WordPress, CSP debería combinarse con HTTPS, contraseñas seguras, autenticación en dos pasos, cabeceras de seguridad y un plugin de seguridad como Jetpack Security. En conjunto, estas capas reducen la probabilidad de que un ataque tenga éxito y aumentan las posibilidades de que puedas recuperarte rápidamente si algo sale mal.

Protegemos tu sitio.
Tú diriges tu negocio.

Jetpack Security ofrece una seguridad completa y fácil de usar para sitios de WordPress, con copias de seguridad en tiempo real, un firewall de aplicaciones web, análisis de malware y protección contra el spam.

Protege tu sitio

¿Tienes alguna pregunta?

La sección de comentarios está cerrada para este artículo, pero seguimos aquí para ayudarte. ¡Visita el foro de soporte y estaremos encantados de responder a tus preguntas!

Ver foro de soporte