Cabeceras de seguridad para sitios estáticos
CSP, HSTS, X-Content-Type-Options y compañía: cómo blindar un sitio estático sin romper nada en el camino.
Un sitio estático ya parte con ventaja: sin base de datos ni código en el servidor, la mayoría de ataques clásicos desaparecen. Pero el navegador sigue necesitando instrucciones claras. Ahí entran las cabeceras de seguridad HTTP.
Las imprescindibles
| Cabecera | Qué evita |
|---|---|
Content-Security-Policy | XSS e inyección de recursos externos |
Strict-Transport-Security | Downgrade a HTTP |
X-Content-Type-Options | MIME sniffing |
X-Frame-Options | Clickjacking |
Referrer-Policy | Fuga de URLs internas |
Content-Security-Policy sin sufrir
La CSP de este blog es estricta: solo se permiten recursos del propio origen. El único permiso extra es wasm-unsafe-eval, que necesita Pagefind para ejecutar su motor de búsqueda en WebAssembly.
/* Content-Security-Policy: default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; upgrade-insecure-requests X-Content-Type-Options: nosniff X-Frame-Options: DENY Referrer-Policy: strict-origin-when-cross-origin Permissions-Policy: camera=(), microphone=(), geolocation=() Strict-Transport-Security: max-age=31536000; includeSubDomainsOjo: una CSP con
script-src 'self'bloquea cualquier<script>inline. Astro empaqueta sus scripts como archivos externos, así que no hay problema, pero si pegas un snippet de analytics inline, dejará de funcionar. Es una característica, no un bug.
¿Y los scripts inline del modo oscuro?
Muchos blogs usan un script inline en el <head> para evitar el “flash” del tema incorrecto. Este blog lo resuelve sin JavaScript: el modo oscuro sigue la preferencia del sistema con prefers-color-scheme.
@media (prefers-color-scheme: dark) { /* Tailwind aplica las variantes dark: automáticamente */}Menos JavaScript, menos superficie de ataque y una cabecera CSP sin excepciones.