En una frase
La Integridad de Subrecursos (SRI, por sus siglas en inglés) es una característica de seguridad que permite a los navegadores verificar que los archivos que obtienen de fuentes externas, como los CDNs, no han sido alterados en secreto.
El problema que resuelve
Imagínate esto: estás construyendo una nueva y flamante aplicación web. Para que sea súper rápida, usas una Red de Distribución de Contenidos (CDN) para servir librerías comunes como React, Vue, o incluso solo unas tipografías elegantes. Esta es una práctica estándar. Tus usuarios obtienen una experiencia más rápida porque es probable que el archivo ya esté en la caché de su navegador por haber visitado otro sitio, o se sirve desde un servidor físicamente más cercano a ellos. Todos ganan, ¿verdad?
Casi. Pero acabas de introducir un elemento masivo de confianza. Estás confiando en que el proveedor de CDN siempre servirá el archivo exacto que tú querías. ¿Y si ese CDN es hackeado? Un atacante podría reemplazar el amigable y útil react.min.js con una versión maliciosa: react.min.js-más-un-criptominero-y-ladrón-de-contraseñas.
De repente, este código malicioso se está ejecutando en tu sitio web, con la plena confianza de los navegadores de tus usuarios. Puede robar credenciales de inicio de sesión, desfigurar tus páginas o reclutar a tus visitantes para una botnet. Este es un ataque clásico a la cadena de suministro, y es aterrador porque tú no hiciste nada malo en tu propio servidor. Simplemente confiaste en la parte equivocada en el momento equivocado.
Antes de SRI, no existía un mecanismo nativo en el navegador para defenderse de esto. Los desarrolladores usaban soluciones alternativas, pero eran toscas. SRI fue creado por el W3C para resolver este problema específico de frente. Proporciona una forma simple y estandarizada de decirle al navegador: "Oye, ve a buscar este script, pero antes de ejecutarlo, asegúrate de que es el que estoy esperando. Si difiere aunque sea en un byte, descártalo como si quemara y avísame".
Cómo funciona por dentro
SRI es una combinación ingeniosa de un simple atributo HTML y algunos principios criptográficos serios. Vamos a desglosarlo.
El atributo integrity
La magia comienza con un nuevo atributo que puedes agregar a tus etiquetas <script> y <link>. Se llama, apropiadamente, integrity.
<script
src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha384-oBqDVmMz9ATKxIep9tiCxS/Z9fNfEXiDAYTujMAeBAsjFuCZSmKbSSUnQlmh/jp3"
crossorigin="anonymous"></script>
Este atributo contiene una cadena con dos partes: un prefijo de algoritmo de hash (aquí, sha384-) y un hash criptográfico codificado en Base64. Esta es la "huella digital" del archivo que esperas recibir.
El Hash: una Huella Digital
Una función de hash criptográfico es un algoritmo matemático que toma una entrada (como todo el contenido de un archivo JavaScript) y produce una cadena de caracteres corta y de tamaño fijo, llamada hash. Piénsalo como un checksum con superpoderes.
Estos hashes tienen algunas propiedades cruciales:
- Determinista: El mismo archivo de entrada siempre producirá exactamente el mismo hash.
- Efecto avalancha: Cambia solo un carácter en el archivo de entrada —agrega un espacio, cambia el nombre de una variable— y el hash resultante será completamente diferente e irreconocible.
- Unidireccional: Es prácticamente imposible revertir el proceso. No puedes tomar el hash y averiguar cuál era el contenido original del archivo.
El estándar SRI admite tres algoritmos de hash seguros: SHA-256, SHA-384 y SHA-512. El número se refiere a la longitud en bits del hash, y más grande es generalmente más fuerte. SHA-384 es una excelente opción para todo uso.
Entonces, cuando estás a punto de enlazar a un archivo de un CDN, primero generas su hash. Básicamente, estás tomando una instantánea del archivo en ese momento y diciéndole al navegador: "Así es como se ve el verdadero jquery-3.6.0.min.js".
El atributo crossorigin
¿Ves ese crossorigin="anonymous" en el ejemplo? No está ahí de adorno; es obligatorio. Para que un navegador obtenga un recurso de un origen diferente (por ejemplo, tu sitio mi-app.com obteniendo un script de code.jquery.com) e inspeccione su contenido para la verificación de SRI, necesita permiso a través del Intercambio de Recursos de Origen Cruzado (CORS).
Establecer crossorigin="anonymous" le dice al navegador que haga la solicitud sin enviar ninguna credencial de usuario como cookies o cabeceras de autenticación HTTP. Esto es imprescindible por seguridad y privacidad. Si olvidas este atributo, el navegador se negará a realizar la verificación de integridad y simplemente bloqueará la carga del recurso, lo que resultará en un sitio roto.
Juntándolo todo: La lista de verificación del navegador
Cuando un navegador encuentra una etiqueta con un atributo integrity, sigue este estricto protocolo:
- Ve la etiqueta
<script>y anota los atributossrc,integrityycrossorigin. - Envía una solicitud para el archivo en la URL de
src. Gracias acrossorigin, esta es una solicitud CORS. - El archivo se descarga.
- Crucialmente, antes de ejecutar nada, el navegador calcula su propio hash del contenido del archivo descargado, usando el mismo algoritmo especificado en el atributo
integrity(por ej.,sha384). - Luego compara su hash recién calculado con el hash que proporcionaste en el atributo.
- Si coinciden: ¡Genial! El archivo es auténtico. El navegador ejecuta el script o aplica la hoja de estilos.
- Si no coinciden: ¡ALERTA ROJA! El navegador asume que el archivo ha sido manipulado. Descarta completamente el archivo y no lo ejecuta. Luego, dispara un error
Failed to find a valid digesten la consola del desarrollador. Tu sitio puede parecer roto (por ejemplo, un gráfico o una fuente que faltan), pero has esquivado una bala con éxito.
Historias del mundo real
El panel de análisis desfigurado
Un equipo de marketing dependía de un panel que usaba una librería de gráficos de terceros, obtenida de un CDN de nicho, para visualizar los datos de su campaña. El desarrollador, que acababa de leer sobre las mejores prácticas de seguridad, había agregado hashes SRI a la etiqueta <script> de la librería. Un lunes por la mañana, el CDN sufrió un breve compromiso de seguridad. Un atacante reemplazó la popular librería de gráficos con un script que solo mostraba una cara gigante y burlona en arte ASCII.
Cuando el equipo de marketing cargó su panel, los gráficos estaban rotos. Vieron cajas vacías. Llamaron a TI, molestos. El desarrollador revisó la consola del navegador y vio el hermoso, hermoso error de validación de SRI. El navegador había detectado el archivo modificado, se había negado a ejecutarlo y había evitado la desfiguración. En lugar de un incidente de seguridad mayor y unos altos directivos en pánico, fue una investigación de 15 minutos que terminó con apuntar temporalmente a un CDN diferente.
Lección: SRI convierte una posible catástrofe de seguridad en un problema de disponibilidad contenible.
El criptominero sigiloso
Una popular y ligera librería de utilidades JavaScript alojada en un CDN gratuito era una de las favoritas de los desarrolladores independientes. Un atacante obtuvo acceso al CDN y modificó el archivo de la librería, agregando unas pocas líneas de código ofuscado que activaban un criptominero en WebAssembly. El tamaño del archivo apenas cambió y las funciones principales de la librería seguían funcionando perfectamente.
Los sitios web que usaban la librería sin SRI de repente comenzaron a hacer que los ventiladores de las laptops de sus usuarios se aceleraran y sus baterías se agotaran. Los usuarios se quejaban de lentitud, pero era difícil de diagnosticar. Los sitios en sí se veían bien. Sin embargo, los sitios que habían implementado SRI eran inmunes. Sus navegadores bloquearon el script modificado y, aunque las funciones de utilidad se rompieron, las CPU de sus usuarios estaban a salvo.
Lección: SRI no solo detecta desfiguraciones obvias, sino también ataques sutiles y parasitarios que pueden dañar la reputación de tu sitio.
La actualización de fuente olvidada
Un diseñador insistió en usar una versión específica de una fuente de una fundición tipográfica de terceros, servida a través de su CDN. El desarrollador copió diligentemente la etiqueta <link>, completa con su hash SRI. El sitio se lanzó y se veía genial. Seis meses después, la fundición actualizó el archivo de la fuente para agregar nuevos símbolos de moneda y mejorar el kerning. Fue una actualización legítima y útil.
De repente, el texto del sitio volvió a una fea Arial por defecto. El desarrollador quedó perplejo hasta que revisó la consola y vio el error de SRI. El navegador estaba bloqueando correctamente el nuevo archivo de fuente modificado porque su hash ya no coincidía con el antiguo en el HTML. El "ataque" fue solo una actualización benigna, pero SRI hizo su trabajo. La solución fue simple: generar un nuevo hash para la fuente actualizada y desplegar el cambio.
Lección: SRI impone un versionado estricto. Te protege de cambios maliciosos y de actualizaciones inesperadas de terceros, forzándote a ser intencional sobre los assets que utilizas.
Errores y trampas comunes
- Olvidar
crossorigin="anonymous". Este es el error número 1. Sin él, el navegador no tiene permiso CORS para inspeccionar el recurso, así que por seguridad, simplemente lo bloquea. No se realiza ninguna verificación de integridad. Tu script o estilo simplemente no se carga. - Hashear lo incorrecto. Debes hashear el contenido exacto del archivo que recibe el navegador. No hashees una versión local y sin comprimir de un script si estás enlazando a la versión minificada del CDN. No hashees la cadena de la URL en sí. Necesitas el hash del cuerpo del archivo.
- Usar algoritmos de hash débiles. MD5 y SHA-1 tienen vulnerabilidades conocidas y no deben usarse con fines de seguridad. La especificación requiere que los navegadores admitan al menos SHA-256, SHA-384 y SHA-512. Quédate con esos.
- No actualizar el hash después de una actualización legítima. SRI es una característica, no un error. Si el archivo que estás enlazando se actualiza por cualquier motivo, debes generar un nuevo hash de integridad y actualizar tu atributo
integrityen el HTML. No hacerlo resultará en el bloqueo del recurso. - Pensar que protege tu propio servidor. SRI está diseñado para validar recursos de terceros. Si un atacante ha comprometido tu servidor lo suficiente como para alterar tus archivos HTML, simplemente puede cambiar el hash SRI para que coincida con su script malicioso. No proporciona ningún beneficio para los recursos del mismo origen.
Por qué debe estar en tu radar
Deberías pensar en SRI cada vez que escribes un <script src="..."> o <link rel="stylesheet" href="..."> que apunta a un dominio que no controlas.
Es una pieza fundamental de la seguridad web moderna. En un mundo construido sobre NPM, CDNs y una compleja red de dependencias de terceros, tu cadena de suministro es una superficie de ataque masiva. SRI es una de las herramientas más simples y efectivas para fortalecer esa superficie. Es tu primera línea de defensa contra un CDN comprometido. Junto con una Política de Seguridad de Contenido (CSP), proporciona una protección robusta y en capas.
Agregar SRI toma unos segundos extra cuando agregas un recurso, pero puede ahorrarte un mundo de problemas en el futuro. Transforma un exploit silencioso y peligroso en un fallo ruidoso y seguro.
Profundiza más
- MDN Web Docs: Subresource Integrity - La referencia definitiva para desarrolladores.
- W3C Recommendation: Subresource Integrity - La especificación técnica oficial. Si quieres la inmersión más profunda, es esta.
- Can I use... Subresource Integrity - Tabla de compatibilidad de navegadores actualizada para SRI.
- Wikipedia: Cryptographic hash function - Para entender mejor la magia de la "huella digital" detrás de SRI.
- Scott Helme: Subresource Integrity - Un excelente post de un experto en seguridad sobre el qué, el porqué y el cómo.