Política de Seguridad del Contenido Escribir una cabecera de CSP que realmente funcione
La mayoría de desarrolladores saben que deben agregar una directiva de Content Security Policy a sus aplicaciones. Pocos tienen una que realmente haga algo útil. O bien es demasiado permissive y anula el propósito, o bloquea la mitad del sitio y se elimina por frustración.
Esta guía explica qué hace la CSP, qué directivas son importantes, y cómo escribir una directiva que bloquee ataques reales sin romper tu aplicación.
Qué hace realmente la CSP
Una directiva de Content Security Policy indica al navegador dónde está permitido cargar recursos. Scripts solo de este dominio. Estilos desde ese CDN. Imágenes de cualquier lugar. Sin scripts en línea.
Cuando el navegador recibe una directiva de CSP, aplica esas reglas antes de ejecutar cualquier contenido. Si un ataque de cross-site scripting (XSS) inyecta un script malicioso en tu HTML, la CSP lo bloquea en el nivel del navegador — incluso si el script pasó por tu validación de entrada.
Ese es el valor principal: la CSP es tu segunda línea de defensa cuando la validación de entrada falla.
Las directivas que importan
La CSP tiene decenas de directivas, pero la mayoría de los encabezados en producción solo necesitan seis:
| Directiva | Qué restringe | Error común |
|---|---|---|
default-src |
Fallo de respaldo para cualquier tipo de recurso no explicitamente listado | Configuración 'self', luego olvidar que fuentes y marcos no están cubiertos |
script-src |
URLs de fuentes de JavaScript y ejecución en línea | Agregar 'unsafe-inline' para silenciar errores en consola |
style-src |
URLs de fuentes de CSS y bloques de estilo en línea | Olvidar tu CDN o estilos en línea inyectados por bibliotecas de JavaScript |
img-src |
Fuentes de imágenes incluyendo URIs de datos | Falta data: para imágenes en base64, blob: para exportaciones de canvas |
connect-src |
Destinos de XHR, fetch, WebSocket y EventSource | Olvidar puntos de terminación de análisis y subdominios de API |
frame-ancestors |
Origenes que pueden incrustar tu sitio en un <iframe> |
Dejarlo en blanco por completo — dejando el clickjacking abiertamente expuesto |
frame-ancestors reemplaza a la directiva antigua X-Frame-Options y es recomendable agregarla incluso antes de tener cobertura completa de CSP en otros lugares.
Por qué unsafe-inline Destruye el propósito
Cuando añades 'unsafe-inline' a script-srcestás diciendo al navegador: ejecuta cualquier etiqueta de script que encuentres, sin importar de dónde venga. Esto incluye scripts inyectados por ataques de XSS.
'unsafe-eval' es peor — permite eval(), Function()y setTimeout("string")que son vectores comunes de ataque incluso en bases de código limpias.
Una política con cualquiera de estos documentos declara tus fuentes sin ofrecer ninguna protección contra inyección. El atacante no se importa de dónde cargan tus scripts legítimos si pueden inyectar sus propios scripts en línea.
La forma correcta: noces y hashes
Si tienes scripts en línea legítimos, tienes dos opciones que no te abandonan tu política:
Noce genera un token único por carga de página. El servidor lo agrega al encabezado de CSP y al atributo de script en línea. nonce Solo los scripts con un nonce coincidente se ejecutan.
<!-- CSP header -->
Content-Security-Policy: script-src 'nonce-abc123xyz'
<!-- Inline script with matching nonce -->
<script nonce="abc123xyz">
window.analyticsId = '...';
</script>
Hashes calcula el fingerprint SHA-256 del contenido exacto del script. Agrega ese hash a script-src y el navegador ejecuta ese script específico — pero nada más.
Content-Security-Policy: script-src 'sha256-RFWPLDbv2BY+rCkDzsE+0fr8ylGr2R2faWMhq4lfEQc='
Los noces funcionan mejor en páginas dinámicas donde el contenido cambia por solicitud. Los hashes son adecuados para scripts estáticos que no cambian entre despliegues.
Despliega primero en modo de solo reporte
Añadir CSP a un sitio existente sin probarlo es cómo lo rompes en producción. Comienza con el encabezado de solo reporte en su lugar:
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' 'nonce-{random}'; report-uri /csp-violations
El navegador aplica las reglas y reporta violaciones — no bloquea nada aún. Ese registro de violaciones te dice exactamente qué necesitas agregar a la política antes de cambiarlo a modo de enfoque.
La mayoría de despliegues de CSP que rompen sitios omitieron este paso.
Una CSP real para una aplicación típica de SaaS
Aquí tienes un encabezado listo para producción para una aplicación que utiliza un CDN, Google Analytics y Stripe. Cada directiva está anotada:
Content-Security-Policy:
# Tight default: only load from your own origin
default-src 'self';
# Scripts: your origin, GA tag manager via nonce, Stripe.js
script-src 'self' https://www.googletagmanager.com https://js.stripe.com 'nonce-{SERVER_NONCE}';
# Styles: your origin and Google Fonts CSS
style-src 'self' https://fonts.googleapis.com;
# Fonts: your origin and Google Fonts CDN
font-src 'self' https://fonts.gstatic.com;
# Images: your origin, CDN subdomain, and base64 data URIs
img-src 'self' https://cdn.yourdomain.com data:;
# Fetch/XHR: your API, GA collection endpoint, Stripe API
connect-src 'self' https://www.google-analytics.com https://api.stripe.com;
# Stripe renders its fields in an iframe
frame-src https://js.stripe.com;
# Nobody should be framing your app
frame-ancestors 'none';
# Block <object> and <embed> entirely
object-src 'none';
# Force HTTP requests to upgrade to HTTPS
upgrade-insecure-requests;
por un origen explícito; agrega {SERVER_NONCE} con un valor aleatorio criptográfico generado por solicitud — por ejemplo, base64_encode(random_bytes(16)) en PHP o crypto.randomBytes(16).toString('base64') en Node.
Errores comunes de CSP
Wildcards que son demasiado amplios. script-src * permite scripts de cualquier origen. Podrías decir que no tienes ninguna política de scripts.
Olvidar subdominios. 'self' solo cubre tu origen exacto. https://api.yourdomain.com es un origen diferente y necesita una entrada explícita bajo connect-src.
Omitir frame-ancestors. La protección contra clickjacking es independiente de la protección contra XSS. Añádela por separado del resto de tu conjunto de directivas.
Configurar CSP en múltiples lugares. Si tu CDN y tu aplicación establecen un encabezado de CSP, el comportamiento se vuelve inesperado. Configúralo en una sola capa — normalmente en el servidor de origen o en el proxy inverso.
Usar report-uri sin un manejador. Las violaciones generan solicitudes POST a tu punto de terminación en cada carga de página afectada. O bien manejarlas o dirigirlas a un servicio como Report URI.
Construye tu encabezado sin la incertidumbre
Seguir el registro de cada dominio desde el que tu página carga recursos a través de scripts, estilos, fuentes, imágenes y llamadas a API se vuelve tedioso rápidamente. Un generador de encabezado de CSP en línea permite configurar cada directiva visualmente y genera un encabezado listo para producción que puedes pegar directamente en tu configuración del servidor. Usalo como punto de partida, luego revisa tus solicitudes reales en DevTools para capturar cualquier cosa que el generador haya omitido.
Una CSP demasiado laxa es solo decoración. Una demasiado estricta rompe la experiencia del usuario. Comienza en modo de solo reporte, ajusta desde allí, y usa noces cuando los scripts en línea sean inevitables. Tu política debe hacer que el trabajo del atacante sea más difícil — no el tuyo.
Un CSP que sea demasiado permissive es solo decoración. Uno que sea demasiado estricto rompe la experiencia del usuario. Comienza en modo de informe, ajusta desde allí y utiliza nonces cuando sea necesario ejecutar scripts en línea. Tu política debe hacer que el trabajo del atacante sea más difícil, no el tuyo.
Instalar extensiones
Agregue herramientas IO a su navegador favorito para obtener acceso instantáneo y búsquedas más rápidas
恵 ¡El marcador ha llegado!
Marcador es una forma divertida de llevar un registro de tus juegos, todos los datos se almacenan en tu navegador. ¡Próximamente habrá más funciones!
Herramientas clave
Ver todo Los recién llegados
Ver todoActualizar: Nuestro última herramienta was added on May 23, 2026
