Política de seguridad de contenido para aplicaciones web
Diseña, despliega y mantiene una política CSP con responsables claros, observaciones de informe, pruebas de compatibilidad y límites de reversión.
BotBrowser Team
Quieres la documentación estructurada de Despliegue?
Este artículo forma parte de la biblioteca editorial. Para pasos de configuración, material de referencia y actualizaciones continuas, entra en la sección de docs.
La Content Security Policy (CSP, política de seguridad de contenido) es una política de respuesta de la aplicación que indica a los navegadores compatibles qué tipos de recursos puede cargar o ejecutar un documento. Puede reducir el impacto de ciertos errores de inyección al limitar scripts, conexiones, marcos, Workers y otros recursos. No es un programa completo de seguridad: la autorización del servidor, la codificación de salida, la revisión de dependencias, el diseño de sesiones, la seguridad del transporte y la respuesta a incidentes siguen siendo responsabilidades distintas. La especificación CSP Level 3 de W3C define el modelo; la guía CSP de MDN describe decisiones prácticas de despliegue.
Trata CSP como una decisión de producto y despliegue. El equipo de aplicación es responsable de los recursos intencionales; infraestructura, de entregar la respuesta; y cada proveedor, de su propio servicio. Un informe de violación observa una solicitud y una política. No demuestra que hubo un ataque, que la falta de informes implique una aplicación limpia ni que la operación de negocio terminara. Mantener claros estos límites evita presentar un control útil del navegador como una garantía universal.
Usa este artículo para planificar diseño, responsables, despliegue Report-Only, pruebas deterministas, compatibilidad y reversión. Los ejemplos utilizan páginas sintéticas e informes acotados. No ofrecen una forma de debilitar la política para cargar contenido no confiable, recopilar credenciales, neutralizar controles del navegador ni alterar un servicio ajeno. Para otros encabezados de respuesta, consulta la guía de encabezados HTTP personalizados y, para evidencia de versiones, la guía de validación de navegadores.
Define el propósito y los límites
Empieza por los recorridos de usuario que debe proteger la política y los recursos requeridos. Inventaría scripts, estilos, fuentes, imágenes, medios, marcos, Workers, WebSockets, destinos de fetch, formularios y navegación. Incluye recursos incorporados por gestores de etiquetas, pagos, analítica, soporte y Service Workers. El inventario es un documento de propiedad, no una lista copiada de registros del navegador. Para cada entrada, anota propósito, responsable, sensibilidad de datos, entorno y duración prevista.
Separa el límite de aplicación del límite de ejecución del navegador. script-src puede restringir solicitudes de scripts, pero no autoriza una llamada API ni concede privilegios del servidor al script. connect-src restringe conexiones del navegador, no sustituye el control de acceso del destino. Una directiva de marcos puede limitar dónde se inserta un documento, pero no verifica el código ni la política del documento hijo. Registra estas diferencias antes de elegir valores.
Usa la política más acotada que corresponda a un contrato de aplicación propio. Prefiere orígenes explícitos y rutas estables; evita comodines amplios cuando sea viable enumerar menos fuentes. Revisa esquemas, puertos, redirecciones y subdominios: una expresión aparentemente propia puede incluir más hosts de los previstos. Trata cada origen externo como una dependencia con responsable y revisión. Si el equipo no puede explicar por qué lo necesita, no lo agregues solo para silenciar una violación.
Define qué significa pasar para cada recorrido. Puede ser “se muestra la aplicación, carga el módulo aprobado y se bloquea el recurso sintético no aprobado”. No significa “no hubo informes, por tanto la aplicación es segura”. Registra el estado visible esperado, la política entregada al documento final y la evidencia de aplicación necesaria para confirmar la finalización. No conserves secretos, contenido de clientes, cuerpos completos ni atributos del navegador que no sean pertinentes.
| Pregunta | Evidencia | Responsable y decisión |
|---|---|---|
| ¿Qué código ejecutable es intencional? | URL finales, código en línea y artefacto de despliegue | La aplicación aprueba un nonce, resumen o fuente explícita |
| ¿Qué destinos de red son necesarios? | Destinos de fetch, WebSocket, Worker y formulario | Aplicación y servicio documentan orígenes exactos |
| ¿Qué documentos incrustados son confiables? | URL de marcos, redirecciones y responsable hijo | Producto aprueba relación y alternativa |
| ¿Qué debe reportarse? | Configuración report-to o report-uri y retención | Seguridad fija privacidad y límites operativos |
Elige directivas sin debilitar la confianza
La política debe expresar un modelo de confianza deliberado, no una colección de excepciones. default-src ofrece una base para tipos sin directiva específica. Directivas como script-src, style-src, img-src, font-src, connect-src, frame-src, worker-src, media-src, object-src, base-uri, form-action y frame-ancestors describen decisiones distintas. El soporte y los valores de reserva varían por navegador; prueba las versiones que admite el producto.
Para código ejecutable, haz explícito qué está aprobado. Los nonces son valores por respuesta que el servidor coloca en elementos en línea aprobados y en la política. Un resumen vincula un bloque conocido con un valor exacto de integridad. Los scripts externos también requieren un origen permitido y control de dependencias. No trates un nonce como contraseña ni reutilices uno en respuestas no relacionadas. Autoriza un elemento para una respuesta; no autoriza una API, un usuario ni una cuenta de proveedor.
Revisa con el equipo los permisos de estilos y scripts en línea. Una excepción amplia facilita el despliegue, pero reduce protección. Si un framework antiguo requiere comportamiento en línea, documenta la dependencia, prueba la migración y mantén una excepción temporal y acotada. No añadas unsafe-eval, unsafe-inline, comodines ni un dominio de proveedor completo porque una violación resulte incómoda. Toda excepción necesita razón, responsable, fecha de revisión y alternativa observable.
Otras directivas protegen otros límites. base-uri impide que una URL base inesperada cambie la resolución relativa; form-action restringe envíos; frame-ancestors controla quién puede insertar el documento y es distinta de frame-src; object-src 'none' suele ser apropiada cuando no se necesitan complementos antiguos. upgrade-insecure-requests cambia el tratamiento de URL, pero no corrige todas las integraciones mixtas. Define el efecto esperado antes de habilitar cada directiva.
No confundas CSP con otros encabezados. Permissions Policy controla la delegación de funciones; COOP y COEP definen relaciones entre contextos y recursos; los encabezados de transporte cubren amenazas distintas. CSP los complementa, pero no reemplaza sus garantías. La guía de contextos seguros explica que el estado de seguridad del navegador también es distinto de la política de aplicación. Asigna responsable y aceptación a cada control.
Despliega con evidencia Report-Only
Empieza con Content-Security-Policy-Report-Only en preproducción o una ruta de producción controlada. Report-Only permite que un navegador compatible evalúe una candidata y envíe observaciones sin bloquear recursos. Ayuda a descubrir dependencias omitidas, pero no es una aprobación de seguridad. Puede no haber informes porque el navegador carece de soporte, no se recorrió la ruta, el informe se perdió o el recurso pertenece a otro documento. La ausencia significa “no observado”, no “seguro”.
Asigna una versión y un responsable a cada política candidata. Guarda su texto, ruta o plantilla que la emite, navegadores admitidos, recorrido de prueba y fecha de revisión. Normaliza los informes para guardar solo origen del documento, clase de URI bloqueada, directiva efectiva, disposición, familia de navegador y escenario. Elimina consultas, tokens, cookies, texto de página y otros campos sensibles. El colector debe ser un servicio aprobado, con control de acceso y retención documentada.
Clasifica cada informe frente al inventario. Un URI bloqueado puede ser una denegación intencional, un recurso propio ausente, una dependencia externa, una redirección inesperada o un valor generado por el navegador que no es un recurso de aplicación. Verifica la solicitud y respuesta finales en el entorno aprobado. No agregues automáticamente el origen informado. Averigua quién lo controla, qué datos recibe, si admite la política y qué resultado ve el usuario cuando no carga. El informe prueba una evaluación del navegador, no la confiabilidad del origen.
Ejecuta casos positivos y negativos. El recorrido positivo carga todos los recursos prometidos. El fixture negativo solicita un recurso sintético que la política debe bloquear y comprueba una alternativa visible y acotada. Prueba tanto el encabezado como el comportamiento; un resultado correcto no debe deberse a que la página nunca solicitó el recurso. Usa un origen de prueba controlado por el equipo y conserva solo el resultado breve y la limpieza.
| Etapa | Respuesta del navegador | Evidencia | Regla de promoción |
|---|---|---|---|
| Inventario | Aún sin política candidata | Responsables y recorridos | Cada dependencia necesaria tiene dueño |
| Report-Only | Informa, pero carga recursos | Política versionada, informes redactados y resultados | Cada informe se clasifica o queda como excepción explícita |
| Preproducción aplicada | Puede bloquear recursos | Encabezado final, resultado visible y matriz de compatibilidad | Los recorridos esenciales pasan en navegadores admitidos |
| Producción aplicada | Bloquea fuera del contrato | Registro de despliegue, monitoreo y reversión | Responsable acepta el riesgo de compatibilidad restante |
Ejecuta un fixture determinista de recurso bloqueado
El fixture usa una página propia y una imagen bloqueada deliberadamente. Comprueba una alternativa visible, no registra datos privados y elimina el nodo temporal incluso si falla una aserción. Sirve la página por la misma ruta de encabezados que la aplicación candidata. Configura el resultado esperado en el caso de prueba, no a partir del resultado observado. Es una observación del navegador; no demuestra que el servidor rechazara una solicitud, que se impidiera un ataque o que se completara una operación de negocio.
async function checkCspFallback(page, expectedBlocked) {
const result = await page.evaluate(async expected => {
const host = document.createElement('section');
const image = document.createElement('img');
const status = document.createElement('output');
let violation = false;
host.dataset.test = 'owned-csp-blocked-image';
status.setAttribute('aria-live', 'polite');
status.textContent = 'Esperando el resultado de la política';
image.alt = 'Recurso propio del fixture';
const outcome = new Promise(resolve => {
document.addEventListener(
'securitypolicyviolation',
event => {
if (event.blockedURI.endsWith('/fixtures/csp-owned-image.png')) {
violation = true;
resolve('blocked');
}
},
{ once: true }
);
image.addEventListener('load', () => resolve('loaded'), { once: true });
image.addEventListener('error', () => resolve('error'), { once: true });
});
image.src = '/fixtures/csp-owned-image.png';
host.append(image, status);
document.body.append(host);
let timeoutId;
const timeout = new Promise(resolve => {
timeoutId = window.setTimeout(() => resolve('not-observed'), 5000);
});
const observed = await Promise.race([outcome, timeout]);
window.clearTimeout(timeoutId);
const blocked = violation;
status.textContent = blocked
? 'Alternativa: la política de aplicación bloqueó la imagen'
: observed === 'loaded'
? 'Control: el fixture propio cargó'
: 'El fixture falló sin una violación de política';
const passed = expected
? observed !== 'error' && observed !== 'not-observed' && violation
: observed === 'loaded' && !violation;
return { marker: host.dataset.test, observed, blocked, passed };
}, expectedBlocked);
try {
if (!result.passed) throw new Error(`Unexpected CSP fixture result: ${result.observed}`);
return result;
} finally {
await page.evaluate(() => document.querySelector('[data-test="owned-csp-blocked-image"]')?.remove());
}
}
Sirve /fixtures/csp-owned-image.png desde el stub propio de pruebas con una respuesta de imagen válida y pequeña. La política de control permite img-src 'self', por lo que la imagen debe cargar; la candidata usa img-src 'none', por lo que el navegador emite securitypolicyviolation y se registra la alternativa visible. Si no aparece el evento esperado, registra “no observado” e investiga política, compatibilidad y fixture. No conviertas un error de red o de política en un aprobado. El fallo determinista debe dejar limpio el contexto y el directorio de artefactos.
Ejecuta el fixture una vez con la política de control y otra con la candidata, pasando false y true respectivamente. Mantén separados los recibos. “Bloqueado” solo es útil si el control demuestra que el stub propio era accesible y la candidata informa una violación de política. Incluye URL final, versión de política, versión del navegador, marcador, resultado visible y limpieza. No guardes cookies, encabezados de autorización, registros completos ni una respuesta de producción copiada.
Si configuración, aserción y limpieza pueden fallar, conserva como principal el primer error del recorrido. Informa la limpieza en un campo distinto y cierra página y contexto en un finalizador. Cada reintento usa contexto e informe nuevos. Un aprobado posterior no elimina la incertidumbre de una solicitud previa, sobre todo con Report-Only, donde el recurso pudo llegar al servicio real. Usa un origen sintético para evitar mutaciones remotas.
Valida compatibilidad y responsables
Prueba en navegadores, sistemas, modos de documento y rutas admitidos por el equipo. Incluye redirecciones, caché, Service Workers, scripts de módulo, Workers, marcos, formularios e importaciones dinámicas cuando se usen. La política en un archivo de configuración perimetral no demuestra que el navegador la recibió. Inspecciona la respuesta final después de redirecciones y confirma qué documento posee la política. Un documento anidado puede tener política y decisiones de recursos propias.
Haz explícitos los contratos. Aplicación define recursos necesarios y alternativa UX; alojamiento o CDN confirma que el encabezado llega a todas las rutas canónicas; seguridad determina informes, retención e incidentes; proveedores confirman sus orígenes, redirecciones y manejo de datos; el responsable de publicación resuelve conflictos y registra la versión aceptada. Si el servicio es opcional, documenta la alternativa; si es esencial, no promociones hasta que el contrato sea compatible.
Revisa las interacciones con caché y plantillas. Un nonce por respuesta no debe reutilizarse, y el HTML almacenado debe llevar el nonce que coincide con su política. Un colector no debe exponer valores sensibles de consultas. Un Service Worker puede servir un documento antiguo, por lo que prueba contexto limpio y contexto recurrente cuando corresponda. El aislamiento de estado del navegador facilita recorridos repetibles, pero no elimina registros del servidor ni repara un despliegue obsoleto.
Revisa cambios de política como código e infraestructura. Compara directivas, fuentes, generación de nonce o resumen, ruta de respuesta, destino de informes y esquema de recibo. Asigna dueño a cada fuente añadida. Pon fecha de caducidad o revisión a las excepciones. Retira una fuente solo cuando un recorrido positivo confirme que ya no se usa y un despliegue aprobado la haya eliminado. Un flujo limpio de informes sin recorrer la aplicación no demuestra que se retiró una dependencia.
| Caso de compatibilidad | Comprobación | Si falla |
|---|---|---|
| Inicio en línea | Nonce o resumen coincide con la respuesta | Corrige generación o usa un módulo externo propio |
| Importación de módulo o Worker | URL final y directiva aplicable | Añade fuente propia exacta o usa alternativa admitida |
| Marco o formulario | Origen hijo, redirecciones y frame-src, frame-ancestors, form-action | Coordina con su dueño; no añadas comodín global |
| Caché o respuesta de Service Worker | Política y recurso pertenecen a la candidata | Purga por proceso aprobado o espera expiración controlada |
Supervisa, revierte y mantén
Activa la aplicación por rutas o grupos acotados primero. Supervisa recursos bloqueados por versión, ruta, familia de navegador y dependencia. Agrega solo lo necesario para no conservar contenido del usuario. Un aumento puede indicar dependencia nueva, desajuste de caché, redirección, cambio de navegador o problema del colector. Compáralo con un recorrido positivo conocido antes de modificar la política. El volumen de informes no es una métrica universal de seguridad o disponibilidad.
Prepara la reversión antes de aplicar. Conserva la política y versión de aplicación anteriores y los recibos. Si falla un recorrido esencial, restaura juntas la política conocida y la ruta de aplicación, y vuelve a ejecutar los fixtures positivo y negativo. Si el código depende del recurso nuevo, protégelo con una alternativa en tiempo de ejecución o publica la versión compatible. La reversión no debe retirar transporte seguro, autorización ni registros necesarios para explicar el fallo.
Después de revertir, conserva los informes candidatos como históricos. No borres evidencia ni presentes Report-Only como resultado aplicado. Abre un seguimiento acotado para responsables del recurso, política o publicación. La próxima candidata debe cambiar una condición conocida y repetir el fixture, para distinguir fuente ausente, nonce erróneo, redirección, caché o alternativa de aplicación.
Mantén actualizado el registro: encabezado y rutas, versión, responsables de fuentes, destino de informes, retención, navegadores admitidos, excepciones y fecha de revisión. Revalida tras actualizar el framework, cambiar reglas CDN, proveedor, marco, Worker o host canónico. CSP es parte del contrato desplegado, así que documentación obsoleta también es un riesgo de mantenimiento.
Qué puede validar BotBrowser
Los contextos controlados de BotBrowser permiten ejecutar un recorrido de aplicación autorizado con estado de navegador limpio o declarado, observar si el navegador bloquea un recurso sintético y comparar una alternativa visible entre ejecuciones repetibles. La documentación de aislamiento de varias cuentas de BotBrowser describe BrowserContexts aislados y los límites del estado que gestionan. Esto valida la parte visible del caso CSP: URL final, metadatos de política que la prueba esté autorizada a consultar, resultado de carga o bloqueo y recibo de limpieza.
BotBrowser no redacta ni despliega encabezados, elige una lista segura para la aplicación, valida autorización del servidor o cadena de suministro, ni demuestra que no haya vulnerabilidades de inyección. No puede hacer confiable un recurso ajeno, conceder una excepción al proveedor ni garantizar igual soporte de directivas en todo navegador. Tampoco prueba que se creara un registro, se aceptara un pago, se revocara una sesión o no ocurriera un incidente. Para esos hechos se requiere evidencia de aplicación, servicio, infraestructura y seguridad.
BotBrowser soporta recorridos autorizados que observan el bloqueo de un recurso en un contexto aislado, pero no puede redactar ni desplegar la política, validar la autorización del servidor ni demostrar un resultado de seguridad. Mantén acotados sus recibos: escenario, versión de política, URL final, compilación, resultado visible, clasificación de ruta sintética y limpieza. No incluyas contenido de clientes, credenciales, cookies ni cargas completas. Etiqueta el resultado como “observación de política del navegador” y enlaza evidencia independiente para afirmaciones de negocio. Un contexto limpio es una condición de ejecución, no un mecanismo de borrado del servidor ni una certificación de seguridad.
Antes de publicar, los responsables deben confirmar cuatro límites: un informe no prueba un ataque; la falta de informes no prueba seguridad; un recurso bloqueado no prueba rechazo o eliminación por el servidor; y observar con BotBrowser no sustituye autorización ni revisión de dependencias. Registra política aceptada, compatibilidad, alternativa, responsable de monitoreo y artefacto de reversión. Así se mejora la protección sin debilitarla para cargar una dependencia desconocida.
Repite los mismos recorridos cuando cambien la política o una dependencia propia. Una comparación estrecha y versionada ayuda a identificar si cambió la decisión del navegador, la alternativa de la aplicación o el resultado de un servicio separado.
BotBrowser Team
Fuentes
Artículos Relacionados
Lleva BotBrowser de la investigación a producción
Usa estas guías para entender el modelo y después avanzar hacia validación multiplataforma, contextos aislados y despliegue de navegador preparado para escalar.