Orquesta Agentes IA que desarrollan por ti
Verificando...
40-semgrep-security-review
Procedimiento: Revisi├│n de Seguridad con Semgrep
Seguridad
1 plugin(s)
Editor
Preview
Tareas
1
Info
Titulo
Revisa hallazgos de seguridad de Semgrep (SAST). Clasifica vulnerabilidades por severidad, documenta remediaciones, y verifica que no se desplieguen issues críticos.
Descripcion
Contenido Markdown
14403 caracteres
Guardar
# Procedimiento: Revisi├│n de Seguridad con Semgrep ## Metadata - **ID**: PROC-40 - **Frecuencia**: Post-CI (cuando hay findings), Semanal, Pre-release - **Duraci├│n estimada**: 30-90 min (seg├║n cantidad de findings) - **Requiere**: Acceso a GitLab CI/CD, semgrep CLI (opcional), conocimiento de OWASP Top 10 - **Dependencias**: Pipeline CI ejecutado - **Bloquea**: Release a producci├│n si hay findings Critical/High sin revisar ## Objetivo Revisar, clasificar y resolver hallazgos de seguridad detectados por Semgrep (SAST), asegurando que no se despliega c├│digo con vulnerabilidades conocidas. ## Contexto Semgrep est├í configurado en GitLab CI como SAST (Static Application Security Testing): ```yaml # .gitlab-ci.yml sast-semgrep: stage: security allow_failure: true # No bloquea (por ahora) ``` **Objetivo**: Cambiar a `allow_failure: false` una vez que todos los findings cr├¡ticos est├®n resueltos. ## Severidades y SLAs | Severidad | Descripci├│n | SLA | Bloquea Release | |-----------|-------------|-----|-----------------| | **Critical** | RCE, SQL Injection, Auth bypass | 24h | S├¡ | | **High** | XSS, SSRF, Path traversal | 1 semana | S├¡ | | **Medium** | Info disclosure, Weak crypto | 2 semanas | Revisar | | **Low** | Best practices, code quality | Sprint | No | | **Info** | Sugerencias | Backlog | No | ## Checklist Ejecutable ### 1. Obtener findings del ├║ltimo pipeline **Opci├│n A: Desde GitLab UI** ``` 1. Ir a GitLab ÔåÆ CI/CD ÔåÆ Pipelines 2. Seleccionar ├║ltimo pipeline 3. Click en job "sast-semgrep" 4. Descargar artifact "gl-sast-report.json" ``` **Opci├│n B: Desde GitLab API** ```bash # Variables GITLAB_TOKEN="your-token" PROJECT_ID="your-project-id" PIPELINE_ID="latest" # o ID espec├¡fico # Descargar reporte SAST curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \ "https://gitlab.com/api/v4/projects/$PROJECT_ID/pipelines/$PIPELINE_ID/jobs" \ | jq '.[] | select(.name=="sast-semgrep") | .id' \ | xargs -I {} curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \ "https://gitlab.com/api/v4/projects/$PROJECT_ID/jobs/{}/artifacts/gl-sast-report.json" \ -o gl-sast-report.json ``` **Opci├│n C: Ejecutar Semgrep localmente** ```bash # Instalar semgrep si no est├í pip install semgrep # o brew install semgrep # Ejecutar con reglas de GitLab SAST cd src semgrep --config "p/gitlab-sast" --json -o semgrep-report.json . # Ver resumen semgrep --config "p/gitlab-sast" . ``` - [ ] Reporte obtenido - [ ] Fuente: GitLab UI / API / Local ### 2. Parsear y clasificar findings ```bash # Ver resumen de findings por severidad cat gl-sast-report.json | jq ' .vulnerabilities | group_by(.severity) | map({severity: .[0].severity, count: length}) ' # Listar findings Critical y High cat gl-sast-report.json | jq ' .vulnerabilities | map(select(.severity == "Critical" or .severity == "High")) | .[] | { id: .id, severity: .severity, name: .name, file: .location.file, line: .location.start_line, message: .message } ' ``` Documentar findings: | # | Severidad | Regla | Archivo | L├¡nea | Descripci├│n | |---|-----------|-------|---------|-------|-------------| | 1 | | | | | | | 2 | | | | | | - [ ] Findings clasificados - [ ] Critical: ___ - [ ] High: ___ - [ ] Medium: ___ - [ ] Low: ___ ### 3. Analizar cada finding Critical/High Para cada finding cr├¡tico o alto: ```bash # Ver detalle completo de un finding cat gl-sast-report.json | jq ' .vulnerabilities | map(select(.id == "FINDING_ID")) | .[0] ' ``` **Checklist por finding:** | Pregunta | Respuesta | |----------|-----------| | ┬┐Es un falso positivo? | S├¡ / No / Investigar | | ┬┐El c├│digo es alcanzable en producci├│n? | S├¡ / No | | ┬┐Hay input de usuario sin sanitizar? | S├¡ / No | | ┬┐Existe mitigaci├│n en otra capa? | S├¡ / No | | ┬┐Cu├íl es el vector de ataque? | ___ | | ┬┐Cu├íl es el impacto si se explota? | ___ | ### 4. Clasificar acci├│n por finding | Finding | Acci├│n | Justificaci├│n | |---------|--------|---------------| | | `FIX` - Corregir c├│digo | Vulnerabilidad real | | | `ACCEPT` - Aceptar riesgo | Mitigado en otra capa, bajo impacto | | | `FALSE_POSITIVE` - Marcar FP | Semgrep se equivoca | | | `WONTFIX` - No corregir | C├│digo legacy, se eliminar├í pronto | ### 5. Corregir findings (acci├│n FIX) #### SQL Injection **Detectado:** ```csharp // Vulnerable var query = $"SELECT * FROM Users WHERE Id = {userId}"; cmd.CommandText = query; ``` **Correcci├│n:** ```csharp // Seguro - Parameterized query var query = "SELECT * FROM Users WHERE Id = @UserId"; cmd.CommandText = query; cmd.Parameters.AddWithValue("@UserId", userId); ``` #### SSRF (Server-Side Request Forgery) **Detectado:** ```csharp // Vulnerable var url = request.Query["url"]; var response = await httpClient.GetAsync(url); ``` **Correcci├│n:** ```csharp // Seguro - Allowlist de dominios private static readonly HashSet<string> AllowedHosts = new() { "api.icecat.biz", "live.icecat.biz" }; public async Task<HttpResponseMessage> FetchAsync(string url) { var uri = new Uri(url); if (!AllowedHosts.Contains(uri.Host)) { throw new SecurityException($"Host not allowed: {uri.Host}"); } // Validar que no sea IP privada if (IsPrivateIp(uri.Host)) { throw new SecurityException("Private IPs not allowed"); } return await _httpClient.GetAsync(uri); } private static bool IsPrivateIp(string host) { if (!IPAddress.TryParse(host, out var ip)) return false; byte[] bytes = ip.GetAddressBytes(); return bytes[0] switch { 10 => true, // 10.0.0.0/8 172 => bytes[1] >= 16 && bytes[1] <= 31, // 172.16.0.0/12 192 => bytes[1] == 168, // 192.168.0.0/16 127 => true, // localhost _ => false }; } ``` #### Path Traversal **Detectado:** ```csharp // Vulnerable var filePath = Path.Combine(baseDir, userInput); var content = File.ReadAllText(filePath); ``` **Correcci├│n:** ```csharp // Seguro - Validar path resultante var filePath = Path.GetFullPath(Path.Combine(baseDir, userInput)); if (!filePath.StartsWith(Path.GetFullPath(baseDir))) { throw new SecurityException("Path traversal attempt detected"); } var content = File.ReadAllText(filePath); ``` #### Hardcoded Secrets **Detectado:** ```csharp // Vulnerable var apiKey = "sk-1234567890abcdef"; ``` **Correcci├│n:** ```csharp // Seguro - Usar configuraci├│n var apiKey = _configuration["ExternalApi:ApiKey"]; // O usar Secret Manager / Azure Key Vault var apiKey = await _secretClient.GetSecretAsync("external-api-key"); ``` - [ ] Fixes aplicados - [ ] Tests a├▒adidos para cada fix ### 6. Marcar falsos positivos Si Semgrep reporta algo que no es vulnerabilidad real: **Opci├│n A: Comentario inline (preferido)** ```csharp // nosemgrep: csharp.lang.security.sqli.csharp-sqli var query = "SELECT * FROM Config WHERE Key = 'STATIC_VALUE'"; ``` **Opci├│n B: Archivo .semgrepignore** ```bash # .semgrepignore # Ignorar archivos de test test/ *Tests.cs # Ignorar archivo espec├¡fico con justificaci├│n # REASON: C├│digo legacy, se eliminar├í en v2.0 src/Legacy/OldModule.cs ``` **Opci├│n C: Configuraci├│n en semgrep.yml** ```yaml # .semgrep.yml rules: - id: my-custom-exclusion pattern: ... paths: exclude: - "src/Legacy/*" ``` - [ ] Falsos positivos marcados con justificaci├│n ### 7. Documentar decisiones de ACCEPT/WONTFIX Crear o actualizar `docs/security/accepted-risks.md`: ```markdown # Riesgos de Seguridad Aceptados ## ACCEPT-001: SQL Din├ímico en ReportGenerator - **Finding**: csharp.lang.security.sqli.csharp-sqli - **Archivo**: src/Reports/ReportGenerator.cs:145 - **Fecha**: 2024-12-27 - **Revisor**: @ramac21 - **Justificaci├│n**: - El input viene de un enum interno, no de usuario - Validaci├│n whitelist en capa superior - No hay forma de inyecci├│n desde API p├║blica - **Mitigaci├│n existente**: Enum validation en `ReportType` - **Revisi├│n programada**: 2025-03-01 - **Ticket**: SEC-001 ``` - [ ] Decisiones documentadas en `accepted-risks.md` ### 8. Crear PR con fixes ```bash git checkout -b security/semgrep-fixes-$(date +%Y%m%d) # Aplicar cambios... git add . git commit -m "security: fix semgrep findings Fixes: - SQL Injection in UserRepository.cs (Critical) - SSRF in IcecatClient.cs (High) - Path Traversal in FileService.cs (High) False Positives marked: - ReportGenerator.cs (see accepted-risks.md) PROC-40" git push origin security/semgrep-fixes-$(date +%Y%m%d) ``` - [ ] PR creado - [ ] PR URL: ___ ### 9. Verificar que pipeline pasa ```bash # Esperar a que CI ejecute # Verificar que sast-semgrep ya no reporta los findings corregidos ``` - [ ] Pipeline ejecutado - [ ] Findings Critical: 0 - [ ] Findings High resueltos o documentados ### 10. Actualizar configuraci├│n CI (cuando corresponda) Una vez que todos los Critical/High est├®n resueltos: ```yaml # .gitlab-ci.yml sast-semgrep: stage: security allow_failure: false # Cambiar a false para bloquear ``` - [ ] CI actualizado para bloquear en findings cr├¡ticos ## Reglas Semgrep Relevantes para el Proyecto | Regla | Severidad | Descripci├│n | |-------|-----------|-------------| | `csharp.lang.security.sqli.*` | Critical | SQL Injection | | `csharp.lang.security.ssrf.*` | High | Server-Side Request Forgery | | `csharp.lang.security.path-traversal.*` | High | Path Traversal | | `csharp.lang.security.crypto.weak-crypto.*` | Medium | Criptograf├¡a d├®bil | | `csharp.lang.security.xxe.*` | High | XML External Entity | | `csharp.lang.security.deserialization.*` | Critical | Insecure Deserialization | | `generic.secrets.*` | High | Hardcoded secrets | ## OWASP Top 10 Mapping | OWASP | Reglas Semgrep | Archivos a revisar | |-------|----------------|-------------------| | A01 Broken Access Control | path-traversal, auth-bypass | Controllers, Middleware | | A02 Cryptographic Failures | weak-crypto, hardcoded-secrets | Services, appsettings | | A03 Injection | sqli, command-injection, xss | Repositories, Tools | | A04 Insecure Design | - | Architecture review | | A05 Security Misconfiguration | - | appsettings, Dockerfile | | A06 Vulnerable Components | dependency-check (otro job) | *.csproj | | A07 Auth Failures | auth-bypass, session | OAuth, JWT handling | | A08 Data Integrity | deserialization | JSON parsing | | A09 Logging Failures | - | Sentry config | | A10 SSRF | ssrf | HttpClient usage | ## Troubleshooting | S├¡ntoma | Causa | Acci├│n | |---------|-------|--------| | Semgrep muy lento | Muchos archivos | A├▒adir exclusiones en .semgrepignore | | Muchos falsos positivos | Reglas muy gen├®ricas | Configurar reglas espec├¡ficas | | Finding no desaparece tras fix | Cache de CI | Forzar rebuild, limpiar artifacts | | `nosemgrep` no funciona | Sintaxis incorrecta | Verificar ID exacto de regla | | No encuentra archivo | Path incorrecto | Verificar desde root del proyecto | ## Resultado - **├ëxito**: - 0 findings Critical - 0 findings High sin revisar - Todos los findings documentados (fix, accept, o false positive) - PR merged - **Parcial**: - Findings en progreso con tickets creados - SLA no vencido - **Fallo**: - Findings Critical sin resolver > 24h - Findings High sin resolver > 1 semana - Escalar a Lead t├®cnico ## Advertencias - **NUNCA** ignorar un finding Critical sin revisi├│n profunda - **NO** usar `nosemgrep` sin documentar justificaci├│n - **NO** desactivar Semgrep en CI sin aprobaci├│n de seguridad - Los findings ACCEPT deben tener fecha de revisi├│n programada - Secrets en commits hist├│ricos requieren rotaci├│n inmediata ## Referencias - [Semgrep Rules Registry](https://semgrep.dev/r) - [OWASP Top 10](https://owasp.org/Top10/) - [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/) - [CWE Database](https://cwe.mitre.org/) ## Mensaje de Finalizaci├│n **IMPORTANTE - ACCI├ôN REQUERIDA AL FINALIZAR:** Cuando hayas completado todos los pasos de este procedimiento, DEBES ejecutar el siguiente comando usando la herramienta Bash: Ejecuta: `echo "====== PROCESO TERMINADO [$(date +%H%M%S)] ======" && echo "RESULTADO: Semgrep 0 Critical, 0 High, X Medium, Y Low"` Sustituye X e Y por los n├║meros reales. --- ## Output Estructurado (Nexus) Al finalizar, el agente DEBE generar un bloque JSON con el siguiente formato para que Nexus pueda procesarlo automaticamente: ```json { "result": "success", "summary": "Ejecucion de PROC-40 completada. [Descripcion breve de resultados]", "metrics": { "issues_found": 0, "issues_resolved": 0, "findings_total": 5, "findings_critical": 0, "custom": { "procedure_specific_metric": "value" } }, "backlog_items": [ { "title": "Titulo del item de seguimiento", "description": "Descripcion detallada si se requiere accion futura", "priority": "medium", "type": "improvement", "tags": ["proc-40"] } ], "next_steps": [ "Accion recomendada 1", "Accion recomendada 2" ], "warnings": [ "Advertencias encontradas durante la ejecucion" ] } ``` **Campos requeridos:** - `result`: `"success"` | `"partial"` | `"failed"` - `summary`: Resumen ejecutivo en 1-3 lineas **Metricas especificas de este procedure:** - findings_total, findings_critical, findings_high, findings_fixed **Criterios de resultado:** - `success`: Procedimiento completado sin errores criticos - `partial`: Completado con algunos problemas menores o items pendientes - `failed`: Error critico o no se pudo completar ## Historial de Ejecuciones | Fecha | Ejecutor | Critical | High | Medium | Low | Fixes | Accepts | FPs | Resultado | |-------|----------|----------|------|--------|-----|-------|---------|-----|-----------| | 2026-01-04 | Security Auditor Agent (Claude) | 0 | 0 | 1 | 0 | 0 | 3 | 1 | Ô£à PASSED - Manual code review, all mitigations verified |
H1
H2
H3
Bold
Italic
Code
Lista
Num
Task
Code Block
Link
Nexus Platform
Reconectando
Recuperando la conexion
Se ha interrumpido la conexion con el servidor. Estamos reconectando automaticamente.
Reconectando...
Manten esta pestana abierta, volvemos enseguida.
No hemos podido reconectar
El servidor puede estar reiniciandose o tu conexion a internet es inestable.
Reintentar
La sesion ha expirado
Recarga la pagina para iniciar una nueva sesion.
Recargar
Si no vuelve en 30 segundos, recarga la pagina.