Principales conclusiones
- Cargo Audit solo tiene constancia de los avisos que ya se han presentado.
- Los scripts de compilación y las macros «proc» ejecutan código arbitrario en tiempo de compilación, y la versión estable de Cargo no permite desactivar esa función.
- Una caja abandonada no tiene fecha de caducidad, por lo que nada caduca y solo se recibe una advertencia si alguien la denuncia.
- Cuando se publica un aviso sin una versión parcheada, la solución pasa a ser tu problema.
Un equipo de Rust se toma en serio la seguridad de las dependencias, y el primer paso suele ser siempre el mismo: instalar cargo audit, integrarlo en la integración continua (CI), comprobar que pasa las pruebas y sentirse más tranquilo.
Es una buena medida. Pero la auditoría de la carga responde a una pregunta más concreta de lo que la mayoría de los equipos dan por hecho. Dice así: Cargo.lock y te indica qué paquetes tienen avisos registrados. Eso no es lo mismo que saber si el código que estás a punto de compilar es seguro.
Las herramientas de Rust se centran en lo que la comunidad del lenguaje ha considerado prioritario: compilaciones reproducibles, versiones inmutables y archivos de bloqueo con suma de comprobación. Las carencias no se deben a descuido, sino a lo que ocurre cuando se crea una cadena de herramientas basada en dependencias honestas, en lugar de hostiles.
Qué se comprueba realmente en una auditoría de carga
Tres cosas, aunque se le atribuyan más a esta herramienta.
Comprueba las cajas de tu archivo de bloqueo con la base de datos de avisos de RustSec. Marca las versiones retiradas. Y muestra avisos informativos, que es precisamente donde Rust hace algo que la mayoría de los gestores de paquetes omiten por completo.
cargo install cargo-audit --locked
cargo audit
RustSec clasifica sus hallazgos en categorías, y los tres tipos que no son vulnerabilidades tienen más relevancia práctica de lo que la mayoría de los equipos espera.
| Tipo de aviso | Qué significa | No supera la auditoría de carga por defecto |
|---|---|---|
| Vulnerabilidad | Una vulnerabilidad de seguridad a la que se le ha asignado un identificador RUSTSEC | Sí |
| Sin mantenimiento | El responsable del mantenimiento ha declarado, o ha dejado claro, que ha dejado de ocuparse de su mantenimiento | No, solo es una advertencia |
| Unsound | Una API segura que puede provocar un comportamiento indefinido | No, solo es una advertencia |
| Aviso | Otra información que conviene tener en cuenta | No, solo es una advertencia |
Ninguna de las categorías informativas falla por sí sola, por lo que una tarea de CI que ejecute una simple auditoría de Cargo da resultado positivo aunque haya crates sin mantener justo ahí, en el árbol. Eso suele ser precisamente lo que los equipos creen que están detectando.
cargo audit --deny warnings
Eso cambia las cosas. También puedes descartar categorías más específicas, como «sin mantenimiento», «defectuoso» o «retirado», si quieres destacar un tipo concreto de hallazgo sin incluir el resto. Es de esperar que la primera ronda en un proyecto maduro genere mucho revuelo.
La etiqueta «unmaintained» solo existe si alguien la aplica. Un crate cuyo mantenedor dejó de publicar commits discretamente en 2023 y nunca lo anunció no genera ningún aviso. Una ejecución de «cargo audit» sin errores no te indica si tus dependencias siguen teniendo a alguien al frente.
Qué abarca cada herramienta de seguridad de Rust
Las herramientas se dividen en dos categorías que son más importantes que el número de funciones: si es necesario que una persona haya revisado realmente el código y si pueden detener una compilación.
| Herramienta | Comprobación inicial | Puede provocar un error en la compilación | Requiere revisión humana |
|---|---|---|---|
| auditoría de carga | Lockfile frente a los avisos de RustSec | Sí, a través de su estado de salida | No |
| negación de la carga | Avisos, licencias, jaulas prohibidas, fuentes | Sí, basada en políticas | No |
| veterinario de carga | Si se cumplen tus criterios de auditoría | Sí, cuando faltan las auditorías y no hay nada que exima a la caja | Sí |
| grieta en la carga | Redes distribuidas de revisiones de código basadas en la confianza | No | Sí |
| Cargo Geiger | Volumen de código inseguro en el árbol | No | No |
| carga verificable | Incorpora la lista de dependencias en el archivo binario | No | No |
«cargo deny» es la herramienta menos utilizada en comparación con lo que realmente ofrece. Cubre los mismos aspectos que los avisos de RustSec, al igual que «cargo audit», añade políticas de licencias y restricciones, y permite incluir fuentes en una lista blanca para que un crate procedente de un registro que nunca hayas aprobado no pueda colarse sin que te des cuenta. Las versiones actuales no superan la comprobación de avisos de vulnerabilidad y notificaciones; por defecto, dan error ante los que no se mantienen en cualquier parte del árbol, y dan error ante los avisos poco fiables en tus dependencias directas, que es el comportamiento que la mayoría de los equipos deseaban desde el principio.
«cargo auditable» resuelve un problema distinto. Una vez compilado un binario de Rust, recuperar su lista exacta de dependencias no es fiable. El comando «cargo audit bin» puede reconstruirla parcialmente analizando los mensajes de pánico, y su propia documentación es refrescantemente sincera acerca de sus límites. El código C incrustado le resulta invisible, y aproximadamente la mitad de las dependencias de Rust no aparecen porque el compilador es muy eficaz a la hora de eliminar los «panics» que nunca pueden activarse. Incrustar la lista real en el momento de la compilación soluciona eso, y solo te cuesta una palabra en tu comando de compilación.
Ejecutar cargo tree --duplicates además de cualquier auditoría que estés realizando. La existencia de varias versiones de la misma biblioteca en un mismo árbol complica más la corrección de lo que parece, ya que al actualizar una ruta de dependencias puede quedar una versión anterior compilada en tu binario.
La primera diferencia está en el momento oportuno
Todas las herramientas de esa tabla funcionan a partir de un gráfico de dependencias que Cargo ya ha resuelto. Pueden provocar el fallo de una compilación o bloquear una publicación. Lo que ninguna de ellas hace es excluir un crate del gráfico resuelto desde el principio.
Para la mayoría de los problemas de dependencia, eso está bien. Un crate que se sabe que es vulnerable sigue siéndolo diez minutos después, y detectarlo en la integración continua (CI) es lo suficientemente pronto.
En el caso del código malicioso, se encuentra en el lado equivocado de la línea temporal, ya que Rust ejecuta el código no fiable durante la compilación. Los scripts de compilación se ejecutan como parte de cargo build. Las macros de procedimiento se ejecutan dentro del compilador. Ninguna de las dos dispone de un entorno aislado proporcionado por Cargo, por lo que ambas se ejecutan con los permisos de quien haya iniciado la compilación, con acceso al sistema de archivos, a la red y a cualquier credencial que tenga el entorno de compilación en ese momento.
«Stable Cargo» no dispone de ninguna opción para desactivar ninguna de las dos.
cargo vendor vendored/
find vendored/ -name build.rs | wc -l
Prueba eso en un proyecto real. Un servicio de tamaño medio con unos cuantos cientos de crates en el árbol de proyectos puede generar fácilmente docenas de scripts de compilación, y cada uno de ellos, correspondiente a un crate que realmente se compila para tu destino, se ejecuta en una compilación limpia. Lo más probable es que nadie del equipo haya leído ni uno solo de ellos.
No es una hipótesis. En mayo de 2026, unos investigadores que documentaban el Campaña «TrapDoor» encontré cajas como, por ejemplo, sui-framework-helpers y move-compiler-tools dirigido a los desarrolladores de Sui y Move. Su build.rs Los scripts buscaban los archivos de claves de las carteras locales en el momento en que se compilaba un proyecto y enviaban lo que encontraban a GitHub Gists. Sin gancho de instalación, sin importación, simplemente cargo build haciendo exactamente lo que está diseñado para hacer.
Rust no tiene nada parecido a npm install --ignore-scripts. Puedes leer el código fuente de un crate antes de compilarlo, y deberías hacerlo siempre que contenga información confidencial. Lo que Cargo estable no hace es ejecutar una compilación normal omitiendo los scripts de compilación de dependencias y las macros proc, por lo que «auditar primero y luego compilar» sigue siendo una tarea manual en lugar de una opción de configuración.
La comprobación de un crate antes de que llegue a un desarrollador y su compilación a partir de código fuente verificado en un entorno controlado se encuentran entre los pocos controles que se aplican antes de la ejecución en tiempo de compilación. Ese problema de sincronización es en lo que se basa SecureChain para Rust, en lugar de añadir otra pasada sobre un árbol que ya se ha descargado.
La segunda carencia es que nadie corrige nada
RustSec registra las vulnerabilidades. No las soluciona.
Esa distinción sigue siendo teórica hasta que la nota informativa que tienes delante no cuenta con una versión parcheada. En ese momento, el problema se agrava y las opciones para resolverlo se reducen rápidamente.
El volumen también sigue creciendo. RustSec cuenta con 170 avisos con fechas de divulgación en 2025, y los avisos con fecha de 2026 superaron ese total ya en mayo, alcanzando los 257 a mediados de agosto. Es el cuarto año consecutivo en que la cifra ha aumentado, con aproximadamente 160 de las entradas de este año registradas como vulnerabilidades y el resto repartido entre hallazgos sin mantenimiento y defectuosos. Esas cifras también van aumentando a posteriori, ya que siguen llegando avisos sobre revelaciones más antiguas meses después. Esto es positivo para el proyecto. Pero también supone una carga operativa cada vez mayor para cualquiera que utilice los datos, porque un mayor número de hallazgos en un árbol que nadie corrige en la cadena de desarrollo solo significa más problemas que no se pueden resolver simplemente actualizando una versión.
Rust también mantiene satisfechos a sus usuarios actuales. Los desarrolladores lo han vuelto a clasificar como el lenguaje más admirado en la encuesta a desarrolladores de Stack Overflow de 2025, con un 72 por ciento, aunque el indicador «admirado» mide cuántos usuarios actuales quieren seguir utilizándolo, más que la rapidez con la que está aumentando su adopción. En cualquier caso, muchas empresas utilizan ahora Rust en producción sin que exista una práctica establecida sobre qué hacer con un crate que tiene un aviso de seguridad y carece de solución.
Cuando no existe una versión parcheada, todas las opciones son poco satisfactorias. Puedes crear una bifurcación del crate, aplicar la corrección y mantenerla a tu nombre. Puedes sustituir la dependencia, lo que normalmente implica reescribir todo aquello que la utilizaba. Puedes parchearla localmente a través de [patch.crates-io] y conservar ese parche de forma indefinida. Puedes documentar un control compensatorio y aceptar el riesgo. O bien, puedes recurrir a alguien cuyo trabajo consista precisamente en aplicar retroactivamente las correcciones al código original que se hayan quedado atrás.
La retrocompatibilidad de una corrección de seguridad a una versión cuyo responsable ya no está al frente es una disciplina diferente a la de escribir nuevas funcionalidades. Requiere pruebas de regresión, validación de la compatibilidad y un compromiso deliberado de no modificar el comportamiento, lo cual es, más o menos, lo contrario de lo que se pretende con el desarrollo en el proyecto original.
La tercera laguna son las jaulas que nunca se retiran oficialmente
PHP publica las fechas de fin de vida útil (EOL). Lo mismo hace Node, según su propio calendario. Una crate que alguien publicó en 2019 no publica nada, porque, para empezar, nunca hubo un compromiso de soporte que fuera a finalizar.
El registro en crates.io Esto complica las cosas en un aspecto concreto. Las versiones publicadas son, a efectos prácticos, inmutables. La eliminación solo es posible en un margen muy reducido, en el caso de crates que casi no tienen descargas y de los que no depende nada, por lo que la eliminación directa es la verdadera herramienta. Esa inmutabilidad constituye una auténtica ventaja de seguridad frente a los registros que permiten etiquetas mutables. También significa que un crate abandonado sigue pudiendo instalarse, se resuelve con normalidad y no deja ningún rastro en Cargo.lock lo que sugiere que su responsable lo abandonó hace tres años.
No hay ninguna herramienta que agrupe las señales que te darían esa información, así que esta parte hay que hacerla manualmente. Compara la fecha de la última versión con el número de incidencias abiertas. Comprueba si el repositorio de GitHub está archivado, algo que Cargo nunca menciona. Cuenta los propietarios que aparecen en la página de crates.io, ya que un solo propietario supone un «factor de autobús» igual a uno. Y ten en cuenta si el crate es una dependencia de compilación o una macro «proc», ya que estas se ejecutan en tiempo de compilación independientemente de lo bien mantenidas que estén.
Ejecutar cargo owner --list <crate> frente a cualquier elemento relevante para la seguridad en tu árbol de código. Un único propietario en un crate que se compila en tu binario de producción supone un riesgo para la cadena de suministro que la comparación de avisos por sí sola no detectará.
Para saber qué hallazgos son realmente importantes, se necesita ese tipo de contexto. El estado de mantenimiento, si existe una solución, si el crate se encuentra en la ruta de compilación o solo en las dependencias de desarrollo. La coincidencia de avisos no te proporciona nada de eso, por lo que los equipos acaban clasificando los avisos según el ID de RUSTSEC en lugar de según la exposición real.
En qué aspectos ayuda «Cargo Vet» y en cuáles no
Cargo Vet adopta un enfoque diferente y merece una mayor aceptación de la que ha tenido hasta ahora. En lugar de comparar avisos, aplica criterios de auditoría en todo tu gráfico de dependencias, utilizando las auditorías que realiza tu propio equipo, además de las que importas de organizaciones que publican las suyas.
cargo vet init
cargo vet suggest
Lo que conviene saber antes de empezar: cargo vet init excluye deliberadamente todo lo que ya está en tu árbol, para que la adopción no colapse la integración continua desde el primer día. La lista de tareas pendientes sale a la luz a través de cargo vet suggest, y cambias las exenciones por auditorías reales al ritmo que tu equipo pueda mantener. Importar auditorías de organizaciones más grandes permite cubrir una parte considerable del trabajo atrasado sin que nadie de tu equipo tenga que revisar ese código por sí mismo.
Los límites son de carácter estructural. La cobertura depende de que alguien haya auditado una versión de la que realmente dependas, y cada nueva versión requiere nuevas pruebas, a menos que ya esté cubierta por una auditoría importada o una exención. Las auditorías delta permiten que esto sea manejable, ya que normalmente se revisa la diferencia respecto a una versión ya aprobada, en lugar de empezar desde cero. Una auditoría humana también supone una valoración subjetiva sobre la calidad y la intención del código, no una garantía. A los revisores se les pasan cosas por alto, sobre todo en scripts de compilación ofuscados.
La confianza delegada sigue siendo mejor que la falta de confianza. Simplemente tiene una curva de cobertura, y esa curva es más estrecha precisamente donde se encuentran los crates nuevos o poco conocidos, que es precisamente donde los paquetes maliciosos suelen aparecer.
Qué se debe ejecutar realmente en la integración continua
Elige en función de en qué fase se encuentre tu proyecto, en lugar de instalarlo todo de una vez.
Como hoy no hay nada preparado, empieza por cargo deny check advisories sources. Abarca los aspectos de los avisos de RustSec, añade la lista de fuentes permitidas en un solo paso y, por defecto, trata las categorías principales de los avisos como errores que impiden la compilación.
Si la auditoría de carga ya se está realizando, añade --deny warnings Para que los hallazgos sin mantenimiento y con fallos dejen de pasar desapercibidos, clasifica la lista resultante según si el crate se encuentra en tu ruta de compilación.
Si envías binarios a clientes o a entornos regulados, activa la opción «cargo auditable» para que el artefacto que envíes incluya su propia lista de dependencias. Reconstruirla a posteriori resulta tedioso y el resultado es incompleto.
Si tus agentes de compilación disponen de credenciales en la nube o claves de firma, considera que la ejecución en tiempo de compilación es el principal riesgo y reduce la vigencia de dichas credenciales, ya que, una vez que se inicia una compilación, los scripts de compilación de dependencias pueden ejecutarse antes incluso de que se ejecute tu propio código.
Y si la ejecución en tiempo de compilación resulta inaceptable en tu modelo de amenazas, Cargo por sí solo no puede garantizar ese límite. El control debe situarse antes de la resolución, en la fase de filtrado y recompilación de los crates antes de que lleguen a la compilación, o en un entorno de compilación aislado que parta de la base de que el código es malicioso.
Los resultados variarán en función de la estructura del árbol. Un proyecto con 40 dependencias directas y sin marcos de trabajo que hagan un uso intensivo de proc-macros es una auditoría manejable. Un servicio que utilice entornos de ejecución asíncronos, serialización y un marco de trabajo web puede alcanzar fácilmente varios cientos de crates transitivos con numerosos puntos de ejecución en tiempo de compilación, y cualquier consejo que trate estos dos casos por igual proviene de alguien que no ha ejecutado «cargo tree» en el segundo caso.
Dónde encaja SecureChain para Rust
Todo lo anterior se refiere a detectar vulnerabilidades, no a subsanarlas. «cargo audit» te indica lo que ya se ha señalado. «cargo vet» te indica lo que alguien ya ha revisado. Ninguna de las dos herramientas hace nada respecto a una caja que ejecute código malicioso antes de que cualquiera de ellas la examine, y ninguna ofrece una solución para un aviso de seguridad que no cuente con un parche de origen.
Ese es precisamente el ámbito para el que se ha diseñado SecureChain para Rust. Recompila los crates a partir del código fuente en entornos aislados, los analiza en busca de malware y patrones sospechosos durante la instalación, y sigue aplicando parches según el SLA a medida que surgen nuevas vulnerabilidades (CVE). Cuando finaliza el mantenimiento del desarrollador original, el servicio «Endless Lifecycle Support» se hace cargo de ese mismo crate y sigue proporcionando correcciones mientras permanezca en tu pila, de modo que una dependencia abandonada nunca se convierta silenciosamente en una sin parchear en tu árbol de código.
Si quieres adelantarte a lo que se esconde en tus dependencias transitivas, el seminario web de TuxCare sobre el «iceberg de las dependencias» analiza en profundidad cómo se propagan las CVE a través de cadenas de dependencias que permanecen invisibles incluso cuando tu panel de control parece estar limpio.
PREGUNTAS FRECUENTES
¿En qué consiste la auditoría de carga?
Compara las cajas que tienes en tu Cargo.lock comparándolo con la base de datos de avisos de RustSec e informa de vulnerabilidades, versiones retiradas y avisos informativos sobre crates sin mantenimiento o defectuosos. No lee el código fuente de los crates ni intercepta las instalaciones, aunque su estado de salida lo convierte en un filtro de CI perfectamente válido. Un sistema experimental cargo audit fix El subcomando puede actualizar algunos requisitos de dependencias vulnerables, pero para ello es necesario instalar «cargo audit» con la función «fix» activada.
¿Falla la auditoría de la carga en el caso de las cajas sin mantenimiento?
No de forma predeterminada. Los avisos informativos, incluidos los que ya no reciben mantenimiento, se muestran como advertencias a menos que se configure lo contrario. Ejecuta cargo audit --deny warnings no cumplir con ellos, o descartar una sola categoría —como «sin mantenimiento»—, y esperar que la primera ejecución de un proyecto consolidado se prolongue mucho.
¿Cuál es la diferencia entre una auditoría de carga y una inspección de carga?
La auditoría de carga comprueba si existe algún aviso registrado sobre una caja, lo cual no te exige ninguna acción por tu parte. La verificación de carga comprueba si tu gráfico de dependencias cumple los criterios de auditoría que hayas configurado, utilizando tus propias auditorías, auditorías importadas, auditorías delta y cualquier exención que hayas establecido. Una nueva versión requiere nueva evidencia, a menos que ya exista algo que la cubra, y una auditoría delta suele implicar revisar únicamente las diferencias respecto a una versión ya auditada.
¿Puede Cargo impedir que se ejecuten los scripts de compilación?
No. Stable Cargo no dispone de ninguna opción que permita desactivar los scripts de compilación ni las macros procedimentales, ya que ambos ejecutan código arbitrario durante la compilación y tienen acceso a todo lo que contenga el entorno de compilación.
¿Cómo puedo encontrar cajas abandonadas en mi árbol de dependencias?
No hay un comando específico para eso. Ejecuta cargo audit --deny warnings para detectar avisos archivados sin mantenimiento, comprueba las fechas de la última publicación, si el repositorio está archivado y el número de propietarios mediante cargo owner --list para cualquier asunto relacionado con la seguridad.
¿Qué ocurre cuando un aviso de RustSec no tiene una versión parcheada?
No hay nada que lo solucione automáticamente. Tienes que crear una rama y corregir el crate, sustituir la dependencia y aplicar un parche local mediante [patch.crates-io] y mantenerlo, documentar un control compensatorio o recurrir a un proveedor que incorpore retroactivamente correcciones a los crates cuyos mantenedores originales hayan dejado de ocuparse de ellos.


