Introducción

En este artículo integro DevSkim, un analizador estático de seguridad (SAST) de Microsoft, en un pipeline de GitHub Actions que escanea una API .NET 8 en cada cambio y publica el reporte en la nube.

El escaneo de vulnerabilidades busca fallas de seguridad conocidas antes de que el código llegue a producción. Las herramientas SAST revisan el código fuente sin ejecutarlo y señalan patrones riesgosos: algoritmos criptográficos débiles, credenciales escritas en el código o conexiones sin cifrar.

Elegí DevSkim porque figura en la lista de herramientas de escaneo de vulnerabilidades de OWASP, es gratuito y de código abierto, soporta C# y otros lenguajes, y genera resultados en formato SARIF, el estándar que GitHub entiende de forma nativa.

La aplicación y el repositorio público

La aplicación de ejemplo es Banco API, una Minimal API en .NET 8 con endpoints para consultar saldos, generar hashes y tokens. Incluí vulnerabilidades intencionales para que DevSkim tenga qué encontrar.

Repositorio público del equipo: github.com/viccarretero/banco-api-vulnerabilidades. El mismo pipeline también corre Grype, que analiza las dependencias y la imagen Docker; eso lo explica mi compañero Gerald Zevallos en su artículo.

Archivo Para qué sirve
src/BancoApi/Program.cs API con las vulnerabilidades de ejemplo
.github/workflows/seguridad.yml Pipeline de CI que compila, escanea y publica
scripts/sarif_to_html.py Convierte el SARIF en un reporte HTML

Un fragmento del código vulnerable:

// Credenciales en el código const string ConnectionString = "Server=db.banco.local;User Id=admin;Password=Admin123!;"; // Hash débil (MD5) using var md5 = MD5.Create(); // Aleatorio no criptográfico para tokens var random = new Random(); // Comunicación sin cifrar Results.Redirect("http://api.tipocambio.example.com/usd"); 

Automatización con GitHub Actions

El escaneo corre solo en cada push o pull request a main, sin que nadie lo ejecute a mano. El workflow tiene cuatro jobs:

  1. build: instala .NET 8 y compila la API.
  2. devskim: ejecuta la acción oficial microsoft/DevSkim-Action, sube el SARIF a GitHub Code Scanning y genera el reporte HTML.
  3. grype: escanea la imagen Docker (ver el artículo de Gerald).
  4. publicar: despliega los reportes en GitHub Pages.

La parte central del archivo .github/workflows/seguridad.yml:

- name: Ejecutar DevSkim uses: microsoft/DevSkim-Action@v1 with: directory-to-scan: src output-filename: devskim-results.sarif - name: Publicar hallazgos en GitHub Code Scanning uses: github/codeql-action/upload-sarif@v3 with: sarif\\\_file: devskim-results.sarif category: devskim - name: Generar reporte HTML run: | mkdir -p site/devskim python3 scripts/sarif\\\_to\\\_html.py devskim-results.sarif site/devskim/index.html DevSkim 

Para que funcione, el workflow pide los permisos security-events: write (subir hallazgos) y pages: write + id-token: write (publicar en Pages). También se puede correr en local:

dotnet tool install --global Microsoft.CST.DevSkim.CLI devskim analyze --source-code src --output-file devskim-results.sarif 

Resultados y publicación en la nube

Cada ejecución deja los hallazgos en dos lugares: la pestaña Security → Code scanning del repositorio y un reporte HTML público en GitHub Pages.

Reporte publicado: viccarretero.github.io/banco-api-vulnerabilidades/devskim

En la primera ejecución (2 min 8 s en total), DevSkim reportó 10 hallazgos: 8 críticos, 1 importante y 1 moderado.

Regla Hallazgo Severidad Cantidad
DS126858 Algoritmo de hash débil (MD5 y SHA1) Crítico 8
DS137138 URL insegura (http://) Importante 1
DS176209 Comentario sospechoso (TODO) Moderado 1

DevSkim no detectó la contraseña escrita en la cadena de conexión ni el uso de System.Random para tokens. Es una limitación real del SAST basado en patrones: conviene complementarlo con un detector de secretos y revisión de código.

Cómo corregir los hallazgos

Cada hallazgo tiene una corrección corta en .NET; al aplicarlas y hacer push, el pipeline vuelve a escanear y el reporte se actualiza solo.

// Credenciales: leerlas de configuración o variables de entorno var connectionString = builder.Configuration.GetConnectionString("Banco"); // Hash: usar SHA-256 (o PBKDF2/Argon2 para contraseñas) var hash = SHA256.HashData(Encoding.UTF8.GetBytes(texto)); // Tokens: generador criptográficamente seguro var token = RandomNumberGenerator.GetInt32(100000, 999999); // Comunicaciones: siempre HTTPS Results.Redirect("https://api.tipocambio.example.com/usd"); 

Si un hallazgo es un falso positivo, DevSkim permite suprimirlo con un comentario en la línea (// DevSkim: ignore DS126858), dejando constancia de la decisión.

Conclusiones

Con un solo archivo de workflow, DevSkim convierte el escaneo de seguridad en un paso automático del desarrollo: cada cambio se revisa y el equipo ve los riesgos antes de desplegar. Al ser SAST, no reemplaza a las pruebas dinámicas (DAST) ni al análisis de dependencias; lo ideal es combinarlo con ellas.

Enlaces

Victor Carretero — Calidad y Pruebas de Software, Universidad Privada de Tacna.