Saltar al contenido
Development

El error de CSP que no me correspondía arreglar

Por Victor Da Luz
astrocloudflaresecuritydev-logsite

Deep Cut Atlas se lanzó en la App Store, y el sitio tenía toda una lista de tareas esperando justo ese momento: reemplazar el texto de “en desarrollo,” agregar una insignia, conectar la línea de precio, actualizar los datos estructurados. La mayor parte fue mecánica. Una parte no lo fue, y esa parte resultó no ser un problema en absoluto.

El punto de partida

Ya había confirmado que la app estaba activa consultando el listado real de la App Store para obtener el precio real ($4.99 por el desbloqueo único de Pro) en lugar de confiar en el marcador “gratis + compra dentro de la app Pro” que llevaba en el issue desde antes del lanzamiento. Insignia agregada, texto reemplazado, JSON-LD recibió un bloque offers y un arreglo screenshot.

El verificador de tipos y el formateador, ambos limpios. La suite de accesibilidad, 15 de 15. Después abrí la página en un navegador real para verla, y la consola tenía una violación de Content Security Policy justo en el script que acababa de tocar.

La parte que parecía mi error

El error señalaba directamente el script JSON-LD: bloqueado por script-src, sin hash, sin nonce. Como acababa de editar el contenido de ese script, la lectura obvia era que se había roto la CSP. Fui a buscar qué había hecho mal.

No había hecho nada mal. El sitio calcula los hashes de CSP para los scripts en línea durante el build, un hash por script, inyectado en el archivo estático _headers que Cloudflare sirve junto con el HTML prerenderizado. astro dev no ejecuta ese paso. Nunca lo ha hecho. Cada página prerenderizada con un script en línea siempre ha mostrado exactamente esta violación bajo dev simple, ante cualquier cambio, incluso sin ningún cambio.

El comentario que está justo encima de la cadena CSP del middleware ya lo dice, si se lee antes de entrar en pánico.

Lo que realmente lo verifica

El arreglo no fue un arreglo. Fue construir el sitio y servir la salida real. npm run build dispara la inyección de hashes, y luego wrangler dev contra dist/server sirve los mismos encabezados que recibe producción. Mismo script JSON-LD, misma página, cero errores en consola, porque ahora el hash del encabezado coincide con el hash de lo que se había publicado. Esa brecha entre desarrollo y producción es la misma que ya había mordido desde el otro lado hace un tiempo.

Ya había corrido la suite completa de accesibilidad de esa manera, construye y sirve a través de wrangler dev internamente, y había pasado limpia. Esa debería haber sido la primera señal de que el error de consola en modo desarrollo no era real. Fui a mirar de todos modos, porque una violación de CSP justo en la línea que acababa de editar es lo bastante específica como para sentirse como prueba.

Lección

Cuando un entorno de verificación y un entorno real no coinciden, conviene averiguar cuál de los dos miente antes de empezar a arreglar código. A astro dev le falta un paso de build, no está simulando producción; una corrida limpia de wrangler dev contra la salida real del build se parece más a lo que recibe una persona visitante que cualquier cosa que muestre astro dev. Que el servidor de desarrollo no lo diga explícitamente es un tema recurrente.

La pista estaba en un comentario que ya había leído una vez, antes, en el mismo repositorio, y que había olvidado para cuando el error apareció en otra pestaña.

Lecturas relacionadas

Development

La CSP que solo se rompía en producción

Cuatro fallas detrás de un solo encabezado: middleware muerto, reglas de `_headers` que se combinan en vez de sobrescribirse, un worker de URL blob bajo script-src, y un script que solo inyecta el edge.

Leer