Cómo funciona esta comprobación
Scanaris recorre el HTML de tu página principal y se fija en dos tipos de etiqueta: <script src="..."> y <link rel="stylesheet" href="...">. Resuelve cada URL contra la de la página y la considera externa si su origen (esquema, dominio y puerto) es distinto del tuyo; eso incluye las URL que empiezan por //, que cargan del CDN con el protocolo de la página. Descarta data: y blob:. Para cada recurso externo mira si tiene el atributo integrity; si falta, lo apunta. Si hay al menos uno, abre un hallazgo de severidad baja con el número de recursos y las primeras diez URL. Los scripts y estilos de tu propio dominio no se marcan: ahí el SRI no aporta nada.
Por qué importa
Cuando cargas una librería desde un CDN estás ejecutando en el navegador de tus usuarios lo que ese CDN decida servir. Si el CDN se ve comprometido, o si su dominio cambia de manos, el fichero puede ser sustituido por otro que haga lo mismo y además robe formularios o redirija a estafas. Pasó en junio de 2024 con polyfill.io: el dominio fue vendido, el script empezó a inyectar código malicioso y más de cien mil webs que lo incluían lo sirvieron sin enterarse. El atributo integrity contiene el hash del fichero que tú revisaste; el navegador calcula el hash de lo que descarga y, si no coincide, no lo ejecuta. Es severidad baja porque exige que el CDN sea atacado primero, pero cuando ocurre, el daño es total y silencioso.
Cómo arreglarlo
Opción 1: añadir integrity a las etiquetas
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"
integrity="sha384-..." crossorigin="anonymous"></script>
El hash se obtiene descargando el fichero exacto y ejecutando:
curl -s https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js | openssl dgst -sha384 -binary | openssl base64 -A
cdnjs y jsDelivr muestran el hash listo para copiar junto a cada fichero. El atributo crossorigin="anonymous" es obligatorio para que el navegador pueda verificar un recurso de otro origen. Y la URL debe apuntar a una versión fija (@4.4.0), nunca a latest: si el CDN actualiza el fichero, el hash deja de coincidir y tu web deja de cargar esa librería, que es exactamente lo que quieres que pase ante un cambio no revisado.
Opción 2: servir las librerías desde tu dominio
Instálalas con npm y deja que tu bundler (Vite, webpack, Nuxt, Next.js) las incluya en tu build. Así el fichero sale de tu servidor, con hash en el nombre, y el SRI deja de ser necesario. Es la opción habitual en proyectos modernos y la que resuelve el hallazgo de raíz.
Lo que no admite SRI
Las hojas de estilo de Google Fonts cambian según el navegador que las pide, así que su hash no es estable: o aceptas ese hallazgo o alojas las fuentes tú mismo (que además mejora la privacidad y la velocidad). Los scripts de analítica y de anuncios que se actualizan solos (gtag.js, el píxel de Meta) tampoco admiten un hash fijo; ahí la defensa es la CSP, que limita qué puede hacer cada origen y que mide CSP débil.
Comprueba que está arreglado
curl -s https://tudominio.com | grep -oE '<(script|link)[^>]*(src|href)="(https?:)?//[^"]+"[^>]*>' | grep -v integrity
Cada línea que salga es un recurso externo sin integrity. Si solo quedan los que no lo admiten (fuentes, analítica), has terminado.
Preguntas frecuentes
¿SRI ralentiza la carga?
No de forma apreciable: calcular un hash SHA-384 de un fichero de unos cientos de kilobytes lleva milisegundos. Lo que sí hace es obligarte a fijar versiones, que es buena práctica de todos modos.
Si actualizo la librería, ¿tengo que cambiar el hash?
Sí, y es la gracia: la actualización pasa por tus manos. Si usas npm y tu bundler, el proceso es el mismo de siempre y el hash lo gestiona el build.
¿Qué pasa con las versiones viejas de las librerías del CDN?
SRI garantiza que el fichero es el que tú elegiste, no que sea seguro. Una jQuery 1.12 con el hash correcto sigue teniendo sus fallos; eso lo detecta librerías desactualizadas.