# REPORTE DE SEGURIDAD — SGE
Generado: 2026-04-08

## RESUMEN EJECUTIVO
**Nivel de riesgo residual: CRITICO**
- Criticos: 18
- Altos: 5
- Medios: 1
- Controles OK: 4

## HALLAZGOS CRITICOS
- SQLI: public/accesoweb.php L145: $sqlCount = "SELECT COUNT(*) FROM tb_acceso $where";
- SQLI: public/dialibre.php L87: $sql = "INSERT INTO tb_dias_libres (".implode(',', $cols).") VALUES (".implode('
- SQLI: public/dialibre.php L111: $sql = "INSERT INTO tb_dias_libres (".implode(',', $cols).") VALUES (".implode('
- SQLI: public/dialibre.php L131: $sql = "UPDATE tb_dias_libres SET ".implode(',', $sets)." WHERE id_libre = :id_l
- SQLI: public/empleados.php L165: $sqlCount  = "SELECT COUNT(*) FROM tb_empleados $where";
- SQLI: public/externos.php L158: $sqlCount  = "SELECT COUNT(*) FROM tb_externos $where";
- SQLI: public/feriados.php L35: $sql = "INSERT INTO tb_feriados (".implode(',', $cols).") VALUES (".implode(',',
- SQLI: public/feriados.php L46: $sql = "UPDATE tb_feriados SET ".implode(',', $sets)." WHERE id_feriado = :id_fe
- SQLI: public/feriados.php L102: $sqlCount = "SELECT COUNT(*) FROM tb_feriados $where";
- SQLI: public/tipos.php L46: $sql = "INSERT INTO $table ($idField, $nameField) VALUES (:codigo, :nombre)";
- SQLI: public/tipos.php L65: $sql = "UPDATE $table SET $nameField = :nombre WHERE $idField = :codigo";
- SQLI: public/tipos.php L105: $sql = "DELETE FROM $table WHERE $idField = :codigo";
- SQLI: public/tipos.php L182: $where = "WHERE ($idField LIKE :search OR $nameField LIKE :search)";
- SQLI: public/tipos.php L186: $sqlCount = "SELECT COUNT(*) FROM $selectedTable $where";
- SQLI: public/tipos.php L192: $sql = "SELECT $idField AS codigo, $nameField AS nombre
- SQLI: public/php/writeRegEmpleados.php L36: $sql = "INSERT INTO tb_empleados (".implode(',', $cols).")
- SQLI: app/Controllers/user_helpers.php L26: $sql = "SELECT $nameCol AS nombre, $emailCol AS correo, $statusCol AS estado
- SQLI: app/Controllers/user_helpers.php L28: WHERE $fkField = :id

## HALLAZGOS ALTOS
- HARDCODED: app/Controllers/email_baja_creada.php L22: credencial SMTP embebida (ya tratada y removida del paquete).
- CSRF_FALTANTE: public/ajuste_vacaciones.php — form POST sin token CSRF
- CSRF_FALTANTE: public/forgot.php — form POST sin token CSRF
- CSRF_FALTANTE: public/reporteBajas.php — form POST sin token CSRF
- CSRF_FALTANTE: public/reset.php — form POST sin token CSRF

## HALLAZGOS MEDIOS
- DISPLAY_ERRORS_ON: public/dialibre.php

## CONTROLES VERIFICADOS (OK)
- DB fuera del web root: db/gestion.sqlite en /db/ (privado)
- vendor/ fuera del web root (privado)
- .htaccess en public/ con protecciones activas
- Credenciales SMTP centralizadas y preparadas para variables de entorno

## TODOS — Requieren revision manual
- TODO: Mover SMTP_PASS a variable de entorno (.env fuera del repo, cargado con vlucas/phpdotenv)
- TODO: Implementar rate limiting en login.php (max 5 intentos / 15 min por IP)
- TODO: Agregar 2FA opcional para administradores
- TODO: Configurar log rotation para /logs/ (logrotate o cron)
- TODO: Crear backup automatico de gestion.sqlite (cron diario fuera del web root)
- TODO: Revisar session timeout — actualmente no hay expiración de inactividad
- TODO: Validar longitud máxima de contraseña (evitar DoS por hashing de passwords muy largos)
- TODO: accrual.php — mover a job de cron, no debe ser un endpoint web
- TODO: Implementar Content-Security-Policy sin 'unsafe-inline' (requiere nonces en scripts inline)
