DevToolBoxGRATIS
Blog

Content Security Policy (CSP) Guía completa: De lo básico a producción

12 min de lecturapor DevToolBox

CSP es una de las defensas más efectivas contra ataques XSS. Al indicar al navegador qué recursos pueden cargarse, CSP previene la inyección de código malicioso.

¿Qué es CSP?

CSP es una cabecera HTTP que controla qué recursos puede cargar el navegador.

Cómo funciona CSP

El navegador bloquea recursos que violan la política:

Browser receives HTTP response:
  Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com

Browser allows:
  ✅ <script src="/app.js">              (same origin = 'self')
  ✅ <script src="https://cdn.example.com/lib.js">

Browser blocks:
  ❌ <script src="https://evil.com/steal.js">
  ❌ <script>alert('XSS')</script>       (inline = not allowed)

Todas las directivas CSP

DirectivaControlaEjemplo
default-srcFallback for all resource types'self'
script-srcJavaScript files and inline scripts'self' https://cdn.example.com
style-srcCSS stylesheets and inline styles'self' 'unsafe-inline'
img-srcImages (img, favicon, CSS background)'self' data: https:
font-srcWeb fonts (@font-face)'self' https://fonts.gstatic.com
connect-srcXHR, fetch, WebSocket, EventSource'self' https://api.example.com
media-srcAudio and video elements'self'
frame-srcIframes and embedded frames'self' https://www.youtube.com
object-srcPlugins (Flash, Java applets)'none'
base-uriBase element URLs'self'
form-actionForm submission targets'self'
frame-ancestorsWho can embed this page (anti-clickjacking)'self'
upgrade-insecure-requestsUpgrade HTTP requests to HTTPS(no value needed)

Valores de origen

OrigenSignificado
'self'Same origin (protocol + host + port)
'none'Block all resources of this type
'unsafe-inline'Allow inline scripts/styles (reduces security!)
'unsafe-eval'Allow eval(), Function(), setTimeout(string)
'strict-dynamic'Trust scripts loaded by already-trusted scripts
'nonce-abc123'Allow specific inline script with matching nonce attribute
'sha256-...'Allow inline script matching this hash
https:Allow any HTTPS resource
data:Allow data: URIs (e.g., inline images)
blob:Allow blob: URIs
*.example.comAllow all subdomains of example.com

Implementación paso a paso

Paso 1: Modo solo reporte

Desplegar primero en modo reporte:

Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report

Paso 3: Construir política

Crear política:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://cdn.example.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://api.example.com;
  frame-ancestors 'self';
  base-uri 'self';
  form-action 'self';
  object-src 'none';
  upgrade-insecure-requests

Configuraciones comunes

Política estricta

Content-Security-Policy:
  default-src 'none';
  script-src 'self';
  style-src 'self';
  img-src 'self';
  font-src 'self';
  connect-src 'self';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'none';
  object-src 'none';
  upgrade-insecure-requests

Moderada (SPA típica)

Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'unsafe-inline' 'unsafe-eval';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: blob: https:;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://api.example.com wss://ws.example.com;
  frame-ancestors 'self'

Con Google Analytics

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://www.googletagmanager.com https://www.google-analytics.com;
  img-src 'self' https://www.google-analytics.com https://www.googletagmanager.com;
  connect-src 'self' https://www.google-analytics.com https://analytics.google.com

Métodos de implementación

Nginx

add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always;

Apache

Header set Content-Security-Policy "default-src 'self'; script-src 'self'"

Express.js

// Using helmet middleware (recommended)
const helmet = require('helmet');
app.use(helmet.contentSecurityPolicy({
  directives: {
    defaultSrc: ["'self'"],
    scriptSrc: ["'self'", "https://cdn.example.com"],
    styleSrc: ["'self'", "'unsafe-inline'"],
    imgSrc: ["'self'", "data:", "https:"],
  }
}));

// Or manually
app.use((req, res, next) => {
  res.setHeader('Content-Security-Policy',
    "default-src 'self'; script-src 'self'");
  next();
});

Meta tag HTML

<meta http-equiv="Content-Security-Policy"
  content="default-src 'self'; script-src 'self'">

Errores comunes

ErrorImpactoSolución
unsafe-inline para scriptsProtección XSS desactivadaUsar nonces o hashes
unsafe-evalPermite eval()Refactorizar sin eval()
Wildcard en script-srcScripts de cualquier dominioListar dominios específicos
Olvidar estilos inlineBloquea CSS-in-JSAgregar unsafe-inline a style-src
No probar en report-onlyRompe el sitioSiempre empezar en report-only
Falta base-uriInyección de tag baseAgregar base-uri 'self'

FAQ

¿Qué ataques previene CSP?

Principalmente XSS. También clickjacking e inyección de datos.

¿CSP reemplaza la validación de entrada?

No. CSP es defensa en profundidad.

¿Cómo usar CSP con scripts inline?

Usar nonces o hashes. Evitar unsafe-inline.

¿CSP ralentiza el sitio?

No. El impacto en rendimiento es despreciable.

𝕏 Twitterin LinkedIn
¿Fue útil?

Mantente actualizado

Recibe consejos de desarrollo y nuevas herramientas.

Sin spam. Cancela cuando quieras.

Prueba estas herramientas relacionadas

🛡️CSP Header Generator.ht.htaccess GeneratorNXNginx Config Generator🏷️Meta Tag Generator

Artículos relacionados

Hoja de referencia Docker Compose: Servicios, volúmenes y redes

Referencia Docker Compose: definiciones de servicios, volúmenes, redes, variables de entorno y ejemplos de stacks.

Cómo solucionar errores CORS: Guía completa de solución de problemas

Soluciona errores CORS paso a paso. Access-Control-Allow-Origin, preflight, credenciales y configuración de servidor.