Cómo inspeccionar el código de un paquete NuGet antes de confiar en él
Un paquete NuGet distribuye DLLs compiladas, no el código fuente que lees en GitHub — así que la única forma de auditar el código exacto que estás a punto de ejecutar es decompilarlo. Aquí tienes cómo decompilar un paquete NuGet de vuelta a C#, qué señales de alarma buscar, y cómo un decompilador gratuito hace la revisión rápida.
Para inspeccionar un paquete NuGet antes de confiar en él, decompila sus DLLs de vuelta a C# y lee lo que el código realmente hace. Un paquete NuGet distribuye ensamblados compilados, no el código fuente que examinas en GitHub — y no se garantiza que el binario que instalas coincida con ningún repositorio público — así que decompilar es la única forma de auditar el código exacto que estás a punto de ejecutar en tu compilación y tu producto. Un decompilador gratuito como Glass.NET convierte esto en una revisión de unos pocos minutos.
Aquí tienes por qué importa, cómo hacerlo, y qué buscar.
Por qué no puedes confiar plenamente en una dependencia compilada
Cuando haces dotnet add package, estás trayendo un artefacto compilado de un feed y dándole los mismos privilegios que al resto de tu aplicación. Unas cuantas cosas convierten eso en una decisión de confianza genuina en lugar de una formalidad:
- El binario no es el repositorio. El código fuente de GitHub podría estar limpio mientras el
.nupkgpublicado se compiló a partir de otra cosa. A menos que un paquete esté verificablemente compilado a partir del código fuente (las compilaciones deterministas y reproducibles siguen siendo la excepción), la DLL es la fuente de verdad de lo que se ejecuta — y es opaca hasta que miras dentro. - Los ataques a la cadena de suministro apuntan a este hueco. Los nombres de paquete con errores tipográficos a propósito, una cuenta de mantenedor comprometida, o una dependencia-de-una-dependencia “utilitaria” maliciosa son todas técnicas muy conocidas. El código malicioso suele ser una pequeña adición enterrada en una biblioteca por lo demás útil.
- Los paquetes pueden ejecutar código en tiempo de compilación. Más allá del ensamblado en tiempo de ejecución, un paquete puede incluir archivos MSBuild
.targets/.propsque se ejecutan durante tu compilación, y los paquetes clásicos podían incluir PowerShell (install.ps1/init.ps1). Eso es ejecución en tu máquina, con tus credenciales, antes de que tu aplicación siquiera se ejecute.
Nada de esto significa que NuGet sea inseguro — significa que “popular y con marca de verificación verde” no es lo mismo que “leí lo que hace”. Para una dependencia sensible, leerla es un seguro barato.
Cómo decompilar una DLL de NuGet de vuelta a C#
Un .nupkg es solo un archivo ZIP, y los ensamblados dentro se decompilan como cualquier otra DLL de .NET — porque un ensamblado administrado lleva un plano casi completo de su código fuente en IL y metadatos (la misma razón por la que tu propio código se decompila tan limpiamente).
1. Consigue el paquete en disco
O descarga el .nupkg de nuget.org, o deja que una restauración lo obtenga y mira en la caché global de paquetes:
- Windows:
%USERPROFILE%\.nuget\packages\<id>\<version>\ - Linux / macOS:
~/.nuget/packages/<id>/<version>/
Los ensamblados están bajo lib/<target-framework>/. (También puedes renombrar el .nupkg a .zip y extraerlo para ver los .targets/.props y cualquier script también.)
2. Abre el ensamblado en un decompilador
Abre la DLL desde lib/ en Glass.NET (arrástrala a la ventana, o Archivo ▸ Abrir ensamblado). Reconstruye C# legible bajo demanda y lista el ensamblado como un árbol de espacios de nombres ▸ tipos ▸ miembros — sin código fuente, PDB ni compilación especial requeridos.
3. Léelo, o expórtalo y hazle grep
Para un vistazo rápido, examina los tipos y lee el C#. Para una auditoría sistemática, exporta a un proyecto compilable (glass export MyPackage.dll --output ./src en la CLI) y luego haz grep sobre el código fuente reconstruido para las APIs específicas que importan — lo que nos lleva a la lista de verificación.
Qué buscar: las señales de alarma
Estás leyendo con una pregunta en mente: ¿hace esta biblioteca algo que una biblioteca de su propósito declarado no tiene razón para hacer? Concretamente:
- Llamadas de red.
HttpClient,WebClient,Socket/TcpClienten crudo, búsquedas de DNS, y especialmente URLs o direcciones IP codificadas a fuego. ¿Por qué un ayudante de formato de fechas está llamando a casa? Vigila las balizas de telemetría que exfiltran más de lo que admiten. - Generación de procesos.
Process.Start, o cualquier cosa que invoque acmd,powershell,bash, o un binario descargado. Una biblioteca pura rara vez necesita lanzar procesos. - Reflexión usada para ocultar la ejecución.
Assembly.Load(byte[])desde un recurso incrustado o un blob descargado,Activator.CreateInstance/Type.GetTypedirigidos por cadenas, o cadenas deMethodInfo.Invoke. Cargar y ejecutar código que no es visible en el ensamblado es una técnica de preparación clásica. - Acceso a credenciales y entorno. Lecturas de variables de entorno, archivos de token,
~/.aws,.npmrc, almacenes del navegador, o el registro de Windows — cualquier cosa que parezca que está recolectando secretos. - Ganchos en tiempo de compilación. Targets de MSBuild que ejecutan tareas, o scripts de instalación, que hacen cualquiera de lo anterior durante la restauración/compilación en lugar de en tiempo de ejecución.
- Código ofuscado o virtualizado. Esta es la grande para la auditoría. Si un paquete ordinario y de aspecto de código abierto resulta tener identificadores renombrados, flujo de control aplanado, cadenas cifradas, o una VM de bytecode, pregunta por qué. Las bibliotecas OSS legítimas casi nunca se ofuscan — la ofuscación en una dependencia que te dijeron que es “solo un ayudante” es una razón para parar y escrutar, porque está ahí específicamente para impedir que hagas lo que estás haciendo ahora. (Los componentes comerciales a veces están ligeramente protegidos; una utilidad gratuita de un autor desconocido es otra historia.)
La combinación es lo que es condenatorio: reflexión + descifrado de cadenas + carga dinámica de ensamblados + un endpoint codificado a fuego en el mismo paquete es la forma de libro de texto de un cargador malicioso, incluso cuando cada pieza podría ser inocente por sí sola.
Cómo un decompilador gratuito hace la revisión rápida
Leer un ensamblado grande desplazándote es lento; un buen decompilador convierte la lista de verificación de arriba en navegación:
- Rastrea una API sospechosa. Encuentra una llamada a
Process.StartoHttpClienty usa Buscar todas las referencias y la jerarquía de llamadas para ver quién la invoca y con qué — ¿es alcanzable desde tu uso, o código muerto? - Salta por nombre. Ir a todo e Ir a la definición te dejan moverte por un ensamblado desconocido como te mueves por tu propio código fuente.
- Exporta y haz grep. Exporta a un proyecto y haz
grepdeProcess.Start,Assembly.Load,Socket,Environment.GetEnvironmentVariablea través de todo el código en una sola pasada. - Haz diff de dos versiones. La comparación de ensamblados de Glass muestra un diff línea a línea entre versiones — la forma más rápida de responder “¿esta subida de parche de aspecto inocuo añadió silenciosamente una llamada de red?” Revisa el delta, no toda la biblioteca, en cada actualización.
- Comprueba autenticidad e inventario. Glass incluye una comprobación de autenticidad de paquetes NuGet para confirmar que un paquete coincide con lo que publicó su autor, y exportación de SBOM (
glass sbom) para registrar exactamente lo que una dependencia arrastra.
Todo eso está en una herramienta gratuita — sin licencia, sin registro — así que una revisión de paquete es una tarea de duración de un café, no un proyecto.
Conoce los límites
La decompilación es potente pero no omnisciente. El código muy ofuscado puede no reconstruirse en C# legible — lo que, de nuevo, es en sí mismo una señal. La lectura estática no captará comportamiento que solo se manifiesta en tiempo de ejecución con entradas específicas. Y estás auditando una versión: fija tus dependencias, revísalas de nuevo al actualizar (para eso es el diff), y combina la revisión de código con señales de procedencia — paquetes firmados, reputación del publicador, historial de descargas y compilaciones reproducibles. Leer el código es la más fuerte de esas señales, no la única.
Una nota legal: analiza paquetes que tengas derecho a analizar. Auditar una dependencia que estás a punto de distribuir en tu propio producto es el caso principal y legítimo — pero algunas licencias restringen la ingeniería inversa, así que comprueba antes de meterte en algo sobre lo que por lo demás no tengas derechos.
Pruébalo
Elige una dependencia de la que dependes pero que nunca has leído de verdad, y abre su DLL en un decompilador. Es un ejercicio rápido y aleccionador — y de vez en cuando uno útil.
Descarga Glass.NET — es un decompilador de .NET gratuito construido sobre el mismo motor probado ICSharpCode.Decompiler que ILSpy, con diff de ensamblados, exportación de SBOM y comprobación de autenticidad de NuGet integrados. Más en la página de producto de Glass.NET.
Prueba Nebula.NET
Endurece tu código .NET en minutos — empieza con la edición gratuita.