# Plan de mitigación para vulnerabilidades críticas y altas

**Proyecto:** `/Users/oq/Developer/multi-php-docker/php-prod/sasis`  
**Fecha:** 2026-06-02  
**Fuente:** reportes `03-sca-composer-audit-mgmt.md`, `04-sca-composer-audit-api.md` y `06-sca-trivy-fs.md`

## Resumen para el equipo

La prioridad óptima es **actualizar dependencias vulnerables usando Composer dentro de Docker**, revisar compatibilidad funcional y repetir los escaneos. No conviene “parchar a mano” archivos dentro de `vendor/`: eso se pierde en la siguiente instalación y deja el proyecto en un estado difícil de auditar.

Orden recomendado:

1. Corregir `api/firebase/php-jwt` por vulnerabilidad crítica.
2. Corregir `mgmt/phpoffice/phpspreadsheet` por SSRF/RCE y DoS.
3. Corregir `mgmt/symfony/mime` por inyección SMTP/header.
4. Corregir `mgmt/symfony/cache` por riesgo de SQL Injection.
5. Corregir dependencias medias/bajas relacionadas para dejar Composer limpio.
6. Reejecutar el script de pruebas y validar que Composer audit / Trivy ya no reporten críticos ni altos.

---

## 1. `api` - `firebase/php-jwt` crítico

### Vulnerabilidad

- **Paquete:** `firebase/php-jwt`
- **Versión instalada:** `v5.2.0`
- **CVE crítica:** `CVE-2021-46743`
- **Problema:** confusión de tipo entre clave y algoritmo (`Key/algorithm type confusion`).
- **Versión corregida mínima:** `6.0.0`
- **Sugerencia óptima:** actualizar a `^7.0` si el código es compatible, porque también elimina `CVE-2025-45769` reportada para versiones `<7.0.0`.

### Riesgo

Un atacante podría abusar de una validación JWT incorrecta si el código acepta algoritmos/llaves de manera ambigua. En endpoints autenticados, esto puede impactar autenticación y autorización.

### Paso a paso de solución

Desde la raíz del proyecto:

```bash
cd /Users/oq/Developer/multi-php-docker/php-prod/sasis
```

Actualizar primero a la opción óptima:

```bash
docker run --rm -v "$PWD:/app" -w /app/api composer:2 composer require firebase/php-jwt:^7.0 --with-all-dependencies
```

Si `^7.0` rompe compatibilidad, aplicar mitigación mínima temporal:

```bash
docker run --rm -v "$PWD:/app" -w /app/api composer:2 composer require firebase/php-jwt:^6.0 --with-all-dependencies
```

Luego revisar el código que decodifica JWT:

```bash
grep -R "JWT::decode\|JWT::encode" api
```

Validar que el algoritmo esperado esté fijado explícitamente y que no venga de entrada del usuario.

Ejemplo conceptual seguro:

```php
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

$decoded = JWT::decode($jwt, new Key($secret, 'HS256'));
```

### Validación

```bash
docker run --rm -v "$PWD:/app" -w /app/api composer:2 composer audit --locked --format=plain
```

Resultado esperado:

- Sin `CVE-2021-46743`.
- Sin advisories críticos en `api`.

---

## 2. `mgmt` - `phpoffice/phpspreadsheet` crítico / alto

### Vulnerabilidades

- **Paquete:** `phpoffice/phpspreadsheet`
- **Versión instalada:** `1.30.1`
- **CVE crítica:** `CVE-2026-34084`
- **CVEs altas:** `CVE-2026-40863`, `CVE-2026-40902`
- **Problema principal:** SSRF/RCE cuando `IOFactory::load()` recibe un `$filename` controlado por usuario.
- **Versiones corregidas reportadas:** `1.30.4`, `2.1.16`, `2.4.5`, `3.10.5`, `5.7.0` según rama.
- **Sugerencia óptima para este proyecto:** subir dentro de la rama 1.x a `^1.30.4` para minimizar ruptura funcional.

### Riesgo

Si el sistema procesa archivos Excel cargados por usuarios, un archivo malicioso podría provocar lectura remota, consumo excesivo de CPU/memoria o ejecución de comportamiento no esperado según el parser afectado.

### Paso a paso de solución

Actualizar dependencia:

```bash
cd /Users/oq/Developer/multi-php-docker/php-prod/sasis
docker run --rm -v "$PWD:/app" -w /app/mgmt composer:2 composer require phpoffice/phpspreadsheet:^1.30.4 --with-all-dependencies
```

Buscar usos peligrosos de carga de archivos:

```bash
grep -R "IOFactory::load\|createReader\|load(\$" mgmt api
```

Mitigación de código recomendada:

1. No pasar rutas controladas directamente por el usuario a `IOFactory::load()`.
2. Guardar uploads en un directorio controlado por la aplicación.
3. Validar extensión permitida: `.xlsx`, `.xls`, `.csv` según necesidad real.
4. Validar MIME usando `finfo_file()`.
5. Rechazar rutas remotas (`http://`, `https://`, `ftp://`, `php://`, `data://`).
6. Aplicar límite de tamaño antes de procesar.
7. Procesar archivos con usuario/permisos restringidos si el flujo es crítico.

Ejemplo conceptual de validación previa:

```php
$allowedExtensions = ['xlsx', 'xls', 'csv'];
$extension = strtolower(pathinfo($uploadedPath, PATHINFO_EXTENSION));

if (!in_array($extension, $allowedExtensions, true)) {
    throw new RuntimeException('Invalid spreadsheet extension');
}

if (preg_match('/^(https?|ftp|php|data):\/\//i', $uploadedPath)) {
    throw new RuntimeException('Remote or stream paths are not allowed');
}

if (filesize($uploadedPath) > 10 * 1024 * 1024) {
    throw new RuntimeException('Spreadsheet file is too large');
}
```

### Validación

```bash
docker run --rm -v "$PWD:/app" -w /app/mgmt composer:2 composer audit --locked --format=plain
```

Resultado esperado:

- Sin `CVE-2026-34084`.
- Sin `CVE-2026-40863`.
- Sin `CVE-2026-40902`.

---

## 3. `mgmt` - `symfony/mime` alto

### Vulnerabilidad

- **Paquete:** `symfony/mime`
- **Versión instalada:** `v6.4.26`
- **CVE alta:** `CVE-2026-45067`
- **Problema:** inyección de header / comando SMTP vía CRLF en `Symfony\Component\Mime\Address`.
- **Versión corregida recomendada:** `6.4.40` dentro de la rama 6.4.

### Riesgo

Si el sistema construye correos con nombres, emails o parámetros controlados por usuarios, un atacante podría inyectar headers adicionales o manipular contenido SMTP.

### Paso a paso de solución

Actualizar Symfony Mime y dependencias relacionadas:

```bash
cd /Users/oq/Developer/multi-php-docker/php-prod/sasis
docker run --rm -v "$PWD:/app" -w /app/mgmt composer:2 composer require symfony/mime:^6.4.40 --with-all-dependencies
```

Buscar construcción de correos:

```bash
grep -R "Symfony\\Component\\Mime\|new Address\|PHPMailer\|addAddress\|setFrom\|Reply-To\|replyTo" mgmt api
```

Mitigación de código recomendada:

1. Validar emails con `filter_var($email, FILTER_VALIDATE_EMAIL)`.
2. Rechazar cualquier valor de header con `\r` o `\n`.
3. No concatenar headers manualmente.
4. Usar APIs del mailer, no strings crudos de cabecera.

Ejemplo conceptual:

```php
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    throw new RuntimeException('Invalid email');
}

if (preg_match('/[\r\n]/', $name . $email)) {
    throw new RuntimeException('Invalid email header input');
}
```

### Validación

```bash
docker run --rm -v "$PWD:/app" -w /app/mgmt composer:2 composer audit --locked --format=plain
```

Resultado esperado:

- Sin `CVE-2026-45067`.
- Sin advisories de `symfony/mime`.

---

## 4. `mgmt` - `symfony/cache` SQL Injection

### Vulnerabilidad

- **Paquete:** `symfony/cache`
- **Versión instalada:** `v6.4.28`
- **CVE:** `CVE-2026-45073`
- **Problema:** SQL Injection en `PdoAdapter::doClear()` vía `$prefix` no sanitizado.
- **Versión corregida recomendada:** `6.4.40` dentro de la rama 6.4.

### Riesgo

Si el prefijo de cache o namespace puede depender de datos externos, puede existir manipulación SQL en operaciones de limpieza de cache.

### Paso a paso de solución

Actualizar Symfony Cache:

```bash
cd /Users/oq/Developer/multi-php-docker/php-prod/sasis
docker run --rm -v "$PWD:/app" -w /app/mgmt composer:2 composer require symfony/cache:^6.4.40 --with-all-dependencies
```

Buscar uso de `PdoAdapter` o configuración de cache:

```bash
grep -R "PdoAdapter\|Symfony\\Component\\Cache\|cache" mgmt/src mgmt/models mgmt/controllers
```

Mitigación de código recomendada:

1. No usar valores controlados por usuario como prefijo de cache.
2. Mantener prefijos constantes por ambiente, por ejemplo `sasis_prod_`.
3. Si el prefijo se genera dinámicamente, permitir solo caracteres seguros: letras, números, `_` y `-`.

Ejemplo conceptual:

```php
if (!preg_match('/^[A-Za-z0-9_-]+$/', $cachePrefix)) {
    throw new RuntimeException('Invalid cache prefix');
}
```

### Validación

```bash
docker run --rm -v "$PWD:/app" -w /app/mgmt composer:2 composer audit --locked --format=plain
```

Resultado esperado:

- Sin `CVE-2026-45073`.

---

## 5. Actualización agrupada recomendada para `mgmt`

Para reducir iteraciones, el equipo puede actualizar los paquetes vulnerables principales en un solo comando:

```bash
cd /Users/oq/Developer/multi-php-docker/php-prod/sasis
docker run --rm -v "$PWD:/app" -w /app/mgmt composer:2 composer require \
  phpoffice/phpspreadsheet:^1.30.4 \
  symfony/mime:^6.4.40 \
  symfony/cache:^6.4.40 \
  paragonie/sodium_compat:^2.5.0 \
  symfony/polyfill-intl-idn:^1.38.1 \
  --with-all-dependencies
```

Luego ejecutar:

```bash
docker run --rm -v "$PWD:/app" -w /app/mgmt composer:2 composer audit --locked --format=plain
```

Si Composer reporta conflictos, resolver uno por uno empezando por:

1. `phpoffice/phpspreadsheet`
2. `symfony/mime`
3. `symfony/cache`
4. `paragonie/sodium_compat`
5. `symfony/polyfill-intl-idn`

---

## 6. Dependencia adicional detectada en `mgmt/libreria/mPDF`

### Vulnerabilidad

- **Paquete:** `setasign/fpdi`
- **Versión instalada:** `v2.3.6`
- **Severidad:** media
- **Versión corregida:** `2.6.7`

### Paso a paso de solución

Si `mgmt/libreria/mPDF` mantiene su propio `composer.lock`, actualizarlo por separado:

```bash
cd /Users/oq/Developer/multi-php-docker/php-prod/sasis
docker run --rm -v "$PWD:/app" -w /app/mgmt/libreria/mPDF composer:2 composer require setasign/fpdi:^2.6.7 --with-all-dependencies
```

Validar:

```bash
docker run --rm -v "$PWD:/app" -w /app/mgmt/libreria/mPDF composer:2 composer audit --locked --format=plain
```

---

## 7. Verificación final obligatoria

Después de aplicar cambios, ejecutar nuevamente el reporte completo:

```bash
cd /Users/oq/Developer/multi-php-docker/php-prod/sasis
./pruebas/security/run_security_tests.sh
```

Validar estos archivos:

```text
pruebas/security/03-sca-composer-audit-mgmt.md
pruebas/security/04-sca-composer-audit-api.md
pruebas/security/06-sca-trivy-fs.md
pruebas/security/08-resumen-completo.md
```

### Criterio de aceptación

- [ ] `api` sin vulnerabilidades críticas en Composer audit.
- [ ] `mgmt` sin vulnerabilidades críticas ni altas en Composer audit.
- [ ] Trivy sin `CRITICAL` ni `HIGH` para `api/composer.lock` y `mgmt/composer.lock`.
- [ ] Funcionalidad de login/JWT validada manualmente.
- [ ] Carga/importación/exportación de Excel validada manualmente.
- [ ] Envío de correos validado manualmente.
- [ ] No se editaron archivos dentro de `vendor/` manualmente.

---

## 8. Mitigaciones temporales si no pueden actualizar hoy

Estas mitigaciones NO reemplazan la actualización, pero reducen exposición mientras el equipo corrige dependencias.

### JWT

- Rechazar tokens con algoritmos inesperados.
- No aceptar algoritmo desde el header como decisión de confianza.
- Rotar secretos si se sospecha exposición.
- Reducir TTL de tokens.

### PhpSpreadsheet

- Bloquear temporalmente carga de archivos Excel de usuarios externos si no es indispensable.
- Limitar tamaño máximo de archivo.
- Rechazar rutas remotas y wrappers como `php://`, `data://`, `http://`, `https://`.
- Procesar archivos en un entorno aislado.

### Symfony Mime / correos

- Rechazar `\r` y `\n` en nombres, correos, asuntos y cualquier campo usado en headers.
- Validar emails con `FILTER_VALIDATE_EMAIL`.
- No construir headers manualmente.

### Symfony Cache

- Usar prefijos de cache constantes.
- No construir prefijos desde parámetros de request, sesión o usuario.

---

## 9. Nota importante para el equipo

Los cambios correctos deben quedar reflejados en:

- `composer.json`
- `composer.lock`

No alcanza con modificar `vendor/`. La evidencia de remediación debe ser una nueva corrida de Composer audit y Trivy sin críticos/altos.
