5 Hotspots de Complejidad Ciclomática (threshold=10)
🌡️Funciones con complejidad ≥ 10 — prioritarios para revisión manualengine.complexity_hotspots(threshold=10)
Función
Módulo
Complejidad
Taint
Blast
Prioridad
export_data_csv()
core/export.py:312
14
Parcial
18
P1
process_billing_event()
core/billing.py:88
11
No
7
P3
trigger_webhook_delivery()
core/webhook_engine.py:201
12
Sí
9
P1
check_team_permission()
api/teams.py:134
9
Sí
11
P2
validate_payload()
core/validator.py:45
7
No
3
P4
6 Hallazgos de Seguridad — Priorizados
🚨Findings — subgrafo tainted × privilege_boundary
#
Hallazgo
Ubicación
CWE
Vector
Severidad
F-01
SQL Injection via f-string en build_filter_query() Datos de request.body llegan interpolados directamente en SQL raw
webhook_engine.py:184
CWE-89
HTTP POST /webhooks
CRÍTICO 9.8
F-02
Privilege Escalation — role param sin enum validation Cualquier usuario puede enviar role="admin" y ser promovido
teams.py:67
CWE-269
HTTP POST /teams/invite
CRÍTICO 9.1
F-03
IDOR en GET /users/{id}/profile — sin ownership check get_user_data() no verifica que el id pertenezca al usuario autenticado
api/users.py:31
CWE-639
HTTP GET /users/{id}
ALTO 7.5
F-04
bulk_export_query() — raw SQL sin parámetros bind Aunque protegido por role=admin, usa concatenación en date_range
db/export_repo.py:219
CWE-89
GET /admin/export
ALTO 6.5
F-05
Falta 2FA en rutas admin de exportación masiva bulk_export puede exfiltrar toda la DB sin step-up auth
api/admin.py:98
CWE-308
GET /admin/export
MEDIO 5.3
7 Recomendaciones — Plan de Remediación
🔴 [F-01] Migrar a queries parametrizadas ORM
Reemplazar execute_raw_query(f"...") con session.query(Event).filter(Event.tag == filter_val) o usar text() con parámetros bind. Eliminar el método raw completamente del API público.
🔴 [F-02] Validar role con Enum tipado
Introducir class TeamRole(str, Enum): member="member"; owner="owner" y usar Pydantic para validar el body. La función check_team_permission() debe rechazar strings no reconocidos antes de cualquier write.
🟠 [F-03] Agregar ownership check en get_user_data()
Verificar if user_id != current_user.id and not current_user.is_admin: raise 403 antes de la query. Añadir test de regresión IDOR con usuario B accediendo a recurso de usuario A.
🟠 [F-04] Parametrizar bulk_export_query()
Usar session.execute(text("... WHERE date >= :start"), {"start": date_start}). El blast_radius=18 hace que este sink sea de alta prioridad aunque esté detrás de auth admin.
🟡 [F-05] Step-up auth (2FA) para /admin/export
Requerir re-autenticación TOTP para cualquier operación de exportación masiva. Implementar @require_step_up_auth(minutes=15) decorator en las rutas admin críticas.
🔵 Ejecutar genotoxic skill post-remediación
Tras los fixes, correr mutation testing sobre validate_payload() y el nuevo EnumValidator para confirmar cobertura de los controles. Usar engine.preanalysis() actualizado como input al genotoxic skill.
8 Código de Análisis Ejecutado
⚙️Script de auditoría — trailmark APIPython · uv run · ~2.3s de análisis