# Análisis estático: PHPStan y Psalm

> PHPStan y Psalm explicados: niveles de reglas, baseline, análisis de taint y qué puede aportar el análisis estático a la seguridad de PHP y qué no.

Fuente: https://phpsos.de/es/php/statische-analyse/  
Actualizado: 25/10/2026  
Proveedor: PHP SOS, Ayuda de emergencia para PHP y seguridad de servidores. Ayuda inmediata por WhatsApp: https://wa.me/491736494914?text=Hola%20PHP%20SOS%2C%20necesitamos%20ayuda%20con%20nuestro%20servidor%20PHP.%20Empresa%3A%20%E2%80%A6%20Sitio%20web%3A%20%E2%80%A6

**En resumen:** el análisis estático revisa el código PHP sin ejecutarlo y encuentra así errores de tipo, variables sin definir, código muerto y llamadas sobre valores posiblemente vacíos. Las dos herramientas más extendidas son PHPStan (niveles de reglas 0 a 10) y Psalm (niveles de error 1 a 8, además de un análisis de taint para flujos de datos inseguros). Encuentran errores en su aplicación, no en el intérprete de PHP; frente a vulnerabilidades como PHP2Shell solo ayuda la actualización de PHP.

## ¿Qué es el análisis estático?

Una prueba ejecuta el código y compara el resultado. El análisis estático, en cambio, lee el código como un revisor muy minucioso y deduce a partir de los tipos, los valores devueltos y las llamadas dónde puede salir algo mal. Encuentra errores también en ramas que ninguna prueba alcanza nunca.

Para quienes toman decisiones, el beneficio es sencillo: los fallos que se encuentran antes de la puesta en producción cuestan una fracción de los que notan los clientes. Para los desarrolladores es un acompañante constante que se ejecuta en el entorno de desarrollo y en la canalización de CI. Si el análisis salta ante un cambio, este no se integra hasta que se corrija el fallo. Así no se acumula una herencia nueva mientras se reduce poco a poco la existente. Junto con las [pruebas con PHPUnit y Pest](https://phpsos.de/es/php/php-testen/) constituye la base de la calidad del código.

## PHPStan: niveles de reglas de 0 a 10

PHPStan se instala como dependencia de desarrollo y necesita PHP 7.4 o superior para funcionar:

```bash
composer require --dev phpstan/phpstan
vendor/bin/phpstan analyse src tests
```

Sin más indicaciones, PHPStan comprueba solo lo imprescindible. La exigencia se controla mediante once niveles, cada uno de los cuales incluye los inferiores:

| Nivel | Qué se comprueba además (selección) |
|---|---|
| 0 | clases y funciones desconocidas, número incorrecto de argumentos, variables siempre sin definir |
| 3 | tipos devueltos y tipos que se asignan a propiedades |
| 5 | tipos de los argumentos en llamadas a funciones y métodos |
| 6 | indicaciones de tipo ausentes |
| 8 | llamadas a métodos y accesos a propiedades sobre valores que pueden ser null |
| 10 | el tratamiento más estricto de `mixed`, también con tipos ausentes |

Con `--level max` se ejecuta siempre el nivel más alto. La documentación advierte, sin embargo, de que una actualización de PHPStan puede traer entonces muchos avisos nuevos. Un hallazgo típico desde el nivel 8:

```php
<?php
function kundenname(?Kunde $kunde): string
{
    return $kunde->name();   // PHPStan: llamada sobre un valor que puede ser null
}
```

## Introducir PHPStan sin una avalancha de errores: la baseline

En proyectos con muchos años, PHPStan suele notificar cientos de puntos en un nivel alto. La baseline resuelve el problema: guarda todos los avisos existentes en un archivo y, a partir de ese momento, PHPStan solo notifica los errores nuevos.

```bash
vendor/bin/phpstan analyse --level 6 src tests --generate-baseline
```

El archivo generado `phpstan-baseline.neon` se incluye en la configuración:

```neon
includes:
    - phpstan-baseline.neon

parameters:
    level: 6
    paths:
        - src
        - tests
```

Así, la herencia acumulada queda documentada de forma visible, mientras que el código nuevo debe estar limpio desde el principio.

## Psalm y el análisis de taint

Psalm persigue objetivos similares a los de PHPStan. Los niveles van al revés: 1 es el más estricto, 8 el más indulgente, y el valor por defecto es 2. Psalm necesita PHP 8.2 o superior y se configura así:

```bash
composer require --dev vimeo/psalm
./vendor/bin/psalm --init
./vendor/bin/psalm --taint-analysis
```

El análisis de taint es especialmente interesante para la seguridad. «Taint» significa contaminación: Psalm marca los datos procedentes de fuentes que un atacante puede controlar, como `$_GET`, `$_POST`, `$_COOKIE`, `$_REQUEST` o `php://input`. Después sigue si esos datos llegan sin protección a puntos peligrosos, los llamados sumideros: salida con `echo`, `include`, `header` o consultas SQL. Entre las categorías integradas están, entre otras, `sql`, `html`, `shell`, `include`, `eval`, `ssrf` y `unserialize`.

```php
<?php
// Psalm notifica un flujo de $_GET a la salida HTML (categoría html)
echo 'Hallo ' . $_GET['name'];

// Corregido: escapar la salida según el contexto
echo 'Hallo ' . htmlspecialchars($_GET['name'] ?? '', ENT_QUOTES, 'UTF-8');
```

La documentación de Psalm reconoce abiertamente los límites: el análisis supone que el escapado se hace correctamente. Fallos sutiles, como unas comillas ausentes alrededor de un atributo HTML, pueden aun así dejar vulnerabilidades. Por eso Psalm recomienda consultas parametrizadas para SQL y plantillas que tengan en cuenta el contexto para HTML. Los resultados pueden emitirse en formato SARIF, que entiende, entre otros, GitHub Code Scanning.

## Análisis estático y seguridad tras PHP2Shell

Aquí conviene una delimitación honesta. PHP2Shell, es decir, CVE-2026-109618 y CVE-2026-109619, está en el intérprete de PHP. Ninguna herramienta que lea el código de su aplicación encuentra estas vulnerabilidades, y ningún cambio de código las cierra. Eso solo lo consigue la actualización a PHP 8.5.12, 8.4.27, 8.3.36 o 8.2.35.

Aun así, el análisis estático contribuye a la seguridad en tres puntos:

1. **Capacidad de actualización:** encuentra código que ya no funciona en las nuevas versiones de PHP. Así baja la barrera para pasar de 8.1 u 8.2 a una versión con soporte.
2. **Vulnerabilidades propias:** el análisis de taint encuentra caminos hacia la [inyección SQL](https://phpsos.de/es/ratgeber/sql-injection-php/), el cross-site scripting o la inclusión de archivos. El proyecto PHP aclara en su política de seguridad que las entradas sin comprobar enviadas a funciones como `mysqli_query()` no son un fallo de PHP, sino que son responsabilidad de la aplicación.
3. **Robustez:** muchos errores fatales surgen de llamadas sobre null o de tipos incorrectos. En relación con CVE-2026-109619, php.net aconseja expresamente corregir en la aplicación los errores fatales que puedan provocarse desde fuera.

El análisis estático no sustituye a una [revisión de código de seguridad](https://phpsos.de/es/blog/sicherheits-code-review-php/) hecha por personas, pero la hace más eficiente, porque los errores rutinarios ya se han descartado antes.

## ¿Cómo ayuda PHP SOS en concreto?

En el marco de la [auditoría de seguridad y prueba de penetración](https://phpsos.de/es/leistungen/sicherheitsaudit-penetrationstest/) procedemos así:

- **Configurar las herramientas:** PHPStan o Psalm con el nivel adecuado y la baseline, integrados en su canalización existente.
- **Valorar los hallazgos de seguridad:** revisamos los resultados del análisis de taint y separamos los riesgos reales de las falsas alarmas.
- **Preparar la actualización:** mostramos qué puntos bloquean el cambio a una versión de PHP con soporte.
- **Entregar los resultados:** recibirá una lista priorizada con puntos concretos del código para su equipo o su agencia.


## Preguntas frecuentes

**¿Qué diferencia hay entre PHPStan y Psalm?**  
Ambos comprueban tipos y encuentran errores sin ejecutar el código. PHPStan cuenta sus niveles de 0 (laxo) a 10 (estricto); Psalm, de 8 (laxo) a 1 (estricto). Psalm incorpora un análisis de taint integrado para problemas de seguridad.

**¿Puedo introducir PHPStan en un proyecto antiguo?**  
Sí. Con una baseline, PHPStan guarda en un archivo todos los avisos existentes y después solo notifica los errores nuevos. Así el equipo empieza sin una avalancha de errores y reduce poco a poco la herencia acumulada.

**¿Encuentra el análisis estático PHP2Shell?**  
No. PHP2Shell está en el intérprete de PHP, no en su código. Contra eso solo ayuda la actualización de PHP. El análisis estático sí ayuda a preparar el código para las nuevas versiones de PHP, de modo que la actualización sea posible con más rapidez.

**¿Qué nivel conviene elegir?**  
Para empezar, un nivel bajo sin baseline o uno más alto con baseline. Más importante que la cifra es que el análisis se ejecute automáticamente con cada cambio y no deje pasar errores nuevos.

## Fuentes

- [PHPStan](https://phpstan.org/)
- [Psalm](https://psalm.dev/)
- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)
