Principales conclusiones
- PHP publica las fechas de fin de vida útil con años de antelación, mientras que los paquetes de Composer no anuncian nada cuando un responsable del mantenimiento deja de estar activo.
- A menudo, una dependencia abandonada es la causa de que se bloquee una actualización de PHP, y no un efecto secundario de la misma.
- composer why-not te indica rápidamente qué es lo que está impidiendo tu próxima actualización de tiempo de ejecución.
- Composer puede detectar paquetes abandonados, pero ninguna herramienta de la cadena de herramientas los actualizará por ti.
Un equipo dedica cuatro meses a pasar de PHP 8.1 a 8.3. Pruebas, entorno de prueba, cambio de fin de semana… todo el proceso. Funciona.
A continuación, Composer Audit marca como abandonado un paquete que gestiona webhooks de pago. Alguien abre el repositorio y descubre que no hay commits desde 2021. No hay política de fin de vida útil, ni aviso de obsolescencia, solo un proyecto que dejó de recibir atención sin hacer ruido, situado a cuatro niveles de profundidad en un árbol de dependencias que nadie ha leído de principio a fin.
Se ha actualizado el entorno de ejecución. El riesgo de software por fin de vida útil no ha variado.
Esa diferencia entre «utilizamos una versión de PHP compatible» y «nuestra aplicación es compatible» es donde se esconde gran parte de la deuda de seguridad de PHP, y es mucho más difícil de detectar que un número de versión en php -v.
El calendario de fin de vida útil de PHP que todo el mundo sigue de cerca
La política de lanzamientos de PHP es realmente buena, y esa previsibilidad es precisamente la razón por la que el fin de vida útil (EOL) en tiempo de ejecución es la parte más sencilla de este problema. Cada rama cuenta con dos años de soporte activo, seguidos de otros dos años en los que solo se abordan los problemas de seguridad críticos.
Hay un detalle que conviene tener en cuenta antes de consultar la tabla. Ese plazo de cuatro años solo se aplica a partir de PHP 8.1, ya que el ciclo de lanzamiento se amplió en 2024. Las versiones anteriores solo contaban con un año de correcciones de seguridad en lugar de dos, por lo que las versiones 7.4 y 8.0 aparecen con un plazo más corto en la tabla.
Esta es la situación actual, según lo confirmado en la página oficial de versiones compatibles de PHP.
| Versión de PHP | Publicado | Apoyo activo hasta el | Asistencia en materia de seguridad hasta el |
| 7.4 | Noviembre de 2019 | Noviembre de 2021 | Noviembre de 2022 |
| 8.0 | Noviembre de 2020 | Noviembre de 2022 | Noviembre de 2023 |
| 8.1 | Noviembre de 2021 | Noviembre de 2023 | Diciembre de 2025 |
| 8.2 | Diciembre de 2022 | Diciembre de 2024 | Diciembre de 2026 |
| 8.3 | Noviembre de 2023 | Diciembre de 2025 | Diciembre de 2027 |
| 8.4 | Noviembre de 2024 | Diciembre de 2026 | Diciembre de 2028 |
| 8.5 | Noviembre de 2025 | Diciembre de 2027 | Diciembre de 2029 |
PHP 8.1 y 8.2 son las dos versiones que merecen tu atención hoy en día. PHP 8.1 llegó al final de su ciclo de vida en diciembre de 2025, por lo que cualquier sistema que siga funcionando con esta versión lleva meses sin recibir parches de seguridad del desarrollador original. El fin de vida útil de PHP 8.2 llegará a finales de diciembre de 2026 y, aunque la versión 8.2 sigue contando con soporte técnico en la actualidad, cualquier equipo que tenga previsto seguir utilizándola más allá de esa fecha deberá tener una solución preparada antes de entonces.
Los equipos que no puedan migrar a tiempo pueden aplicar los parches proporcionados por el proveedor directamente en el propio entorno de ejecución y seguir recibiendo correcciones de seguridad hasta que finalice la migración. Eso es lo que cubre el servicio «Endless Lifecycle Support for PHP» de TuxCare de TuxCare una vez que una versión de PHP llega al final de su ciclo de vida, mientras esa versión siga formando parte de su pila.
Nota: Encontrarse dentro del periodo de seguridad no es lo mismo que estar bajo soporte activo. Se han suspendido las correcciones periódicas de errores. Se han suspendido las mejoras de rendimiento. Se han suspendido las mejoras de compatibilidad. Lo único que queda son las correcciones de seguridad críticas en una rama de la que los gestores de lanzamientos ya se han alejado.
Por qué las dependencias de Composer nunca tienen una fecha de fin de vida útil
Casi nadie publica una política de asistencia técnica para un paquete que creó un fin de semana de 2018.
Esa es la verdadera diferencia. PHP cuenta con un grupo de gestores de lanzamientos, una política documentada y un calendario con el que puedes planificar. Un paquete de Composer suele depender de una sola persona o de un pequeño equipo, y la gente cambia de trabajo, pierde interés o se ve abocada a otras tareas. Cuando eso ocurre, no hay ningún anuncio, porque nunca hubo un compromiso de anunciar nada.
La pérdida de mantenimiento se manifiesta de varias formas diferentes, y solo una de ellas es fácil de detectar. Un paquete marcado como «abandonado» en Packagist es el caso más sencillo, ya que Composer te avisa al respecto. Un repositorio archivado en GitHub es la misma situación, pero sin ninguna advertencia, y Composer no dice nada al respecto.
Luego están los paquetes cuya última versión se publicó hace dos o tres años y cuyos problemas se acumulan sin solución; el responsable del mantenimiento, que sigue por ahí pero ha dejado de dar soporte a la versión principal más antigua en la que te has quedado atascado; el paquete que se integró en otro proyecto sin redireccionamiento; y la bifurcación que, sin hacer ruido, se convirtió en el proyecto real mientras que el original conservó el nombre.
Un paquete que, técnicamente, sigue ahí, sigue pudiéndose instalar y sigue resolviéndose sin problemas —y al que no se le presta ninguna atención en materia de seguridad— parece exactamente igual que un paquete en buen estado desde el interior de tu composer.lock.
Cómo averiguar qué sistema operativo estás utilizando realmente
Reserva unos minutos para cada solicitud. El resultado no suele ser muy agradable de leer.
Empieza por lo que Composer ya sabe.
auditoría de compositores
A partir de la versión 2.4, Composer comprueba las dependencias instaladas con la API de avisos de Packagist, que recopila la base de datos de avisos de seguridad de PHP y la base de datos de avisos de GitHub. Añade –locked si prefieres auditar composer.lock directamente sin instalarlo primero, que es la opción habitual en la integración continua (CI). Los paquetes abandonados aparecieron en Composer 2.6.3 y, desde la versión 2.7, no superan la auditoría por defecto, por lo que una ejecución limpia en un Composer moderno ya te proporciona más información de la que solía ofrecer.
Si quieres la lista de elementos abandonados sin que se rompa la compilación, en la versión 2.8 se añadió un parámetro precisamente para eso.
auditoría de compositor –abandonado=informe
De este modo, los paquetes abandonados pasan de considerarse un error a considerarse un aviso, que suele ser lo que se busca en la integración continua (CI) mientras se va resolviendo la lista de tareas pendientes.
Ahora fíjate en cuánto se han retrasado realmente tus dependencias directas.
composer show –outdated –direct
El opción –direct es importante. Si la omites, obtendrás el árbol completo, donde la información útil se pierde entre el ruido. Las dependencias directas son aquellas que has elegido a propósito, por lo que son el punto de partida más útil. Añade –sort-by-age y aparecerán primero las versiones más antiguas, lo que es una forma más rápida de detectar las que están realmente obsoletas.
Si algo te parece obsoleto, comprueba el estado real del paquete en lugar de fiarte del número de versión.
composer show vendor/package
Esto extrae los metadatos propios del paquete, incluyendo si Packagist lo ha marcado como abandonado y qué ha sugerido el responsable del mantenimiento como sustituto, en caso de que se haya molestado en sugerir alguno. Para tener una visión real de la actividad de mantenimiento, las últimas modificaciones, las versiones publicadas, los problemas abiertos y si las solicitudes de incorporación de cambios llegan a alguna parte, consulta directamente el repositorio.
Por qué actualizar PHP no soluciona este problema
Ahora, dale la vuelta a la suposición habitual. La dependencia abandonada suele ser la razón por la que sigues utilizando una versión antigua de PHP, no un síntoma de ello.
An unmaintained package requiring php: >=8.1 <8.3 will refuse to install on 8.4, and with nobody maintaining it, that upper bound never gets loosened. The upgrade stalls on a library that stopped receiving maintenance years ago.
Composer te mostrará exactamente qué paquetes lo están bloqueando.
composer why-not php 8.4
Ejecuta eso antes de plantearte cualquier actualización del entorno de ejecución. Convierte la afirmación de que «la migración a PHP 8.4 es una gran incógnita» en una lista concreta y, por lo general, más corta de lo esperado, y a menudo incluye uno o dos nombres que hacen que se haga el silencio en la sala.
Esto es, más o menos, lo que se obtiene:
No se ha encontrado el paquete «php» con la restricción «8.4»; es muy probable que los resultados que se muestran a continuación estén incompletos.
acme/webhook-handler 2.0.0 requires php (>=8.1 <8.3)
¿No has encontrado lo que buscabas? Prueba a ejecutar `composer require “php:8.4” –dry-run` para ver el problema desde otra perspectiva.
composer why-not te proporciona la lista sin procesar, indicando qué paquetes y qué restricciones hay. Lo que hagas con cada uno de ellos dependerá de una rápida comprobación posterior: composer show vendor/package además de echar un vistazo al repositorio. Hay cuatro resultados que cubren casi todo lo que te puedes encontrar.
| Qué ofrece «Why Not» | Lo que suele significar | Trayectoria realista |
| Nada | Las restricciones ya permiten la actualización | Pasemos ahora a la compatibilidad y las pruebas de las aplicaciones |
| Uno o dos paquetes mantenidos | A la espera de las versiones de los desarrolladores | Consulta sus sistemas de seguimiento de incidencias y las próximas versiones |
| Un paquete abandonado con una bifurcación conocida | La comunidad se mudó y tú no | Cambia a la bifurcación y reserva un presupuesto para las pruebas de compatibilidad |
| Un paquete abandonado sin sustitución | Ahora eres el propietario de este código | Véndelo, actualízalo o paga a alguien para que lo actualice |
Incorporar una biblioteca abandonada a tu propio repositorio significa que tu equipo pasa a ser responsable de sus CVE, y la mayoría de los equipos que optan por esta vía no cuentan con personal dedicado a ello. El código se copia, pero la responsabilidad no viene incluida.
Aplicar parches a los paquetes de Composer cuando el desarrollador original deja el proyecto es una disciplina muy específica, y ese es precisamente el problema SecureChain para PHP está diseñado para abordar, más que una capacidad que la mayoría de las organizaciones de ingeniería desean desarrollar y mantener internamente.
¿Qué ocurre con los parches de seguridad cuando el desarrollador original deja el proyecto?
En las fases iniciales, no ocurre nada. Esa es la parte que conviene dejar clara, porque muchos equipos dan por sentado, sin decirlo, que existe una red de seguridad en algún sitio.
Packagist no aplica parches a los paquetes. Las bases de datos de avisos registran las vulnerabilidades, lo cual es útil, pero no equivale a solucionarlas. Un aviso sobre un paquete de Composer abandonado puede quedar sin resolver indefinidamente, sin que haya una versión oficial con el parche a la que actualizarse, a menos que se reanude el mantenimiento o que una bifurcación incorpore la corrección.
A partir de ahí, las opciones son limitadas. Hacer una bifurcación y arreglarlo tú mismo, sustituir la dependencia, aceptar el riesgo con un control compensatorio documentado, o recurrir a alguien cuyo trabajo consista precisamente en adaptar las correcciones al código original que se ha quedado atrás.
Nota: Si aplicas un parche a una bifurcación, elige deliberadamente la estrategia de Composer. Para una aplicación, el procedimiento documentado consiste en utilizar un repositorio VCS que apunte a tu bifurcación, mantener sin cambios el nombre del paquete original y aplicar la restricción a tu rama «dev» . Si, en cambio, publicas la bifurcación con tu propio nombre, tendrás que sustituir, para que todo lo que requiera el original siga resolviéndose correctamente. Los alias en línea son una trampa. Son una característica exclusiva del usuario «root», lo que significa que el lado izquierdo del as se descarta para cualquiera que dependa de tu paquete, y el fallo suele salir a la luz meses más tarde en la CI de otra persona.
Decidir qué hacer con cada dependencia abandonada
Hay que sopesar el alcance del impacto junto con la gravedad. Una vulnerabilidad que afecte a la autenticación, los pagos, la subida de archivos o la deserialización merece un análisis más minucioso, incluso si se trata de un hallazgo de gravedad moderada. Sin embargo, esto tiene sus pros y sus contras. Un aviso de vulnerabilidad crítica y fácil de explotar en un ámbito menos destacado no debería pasarse por alto simplemente porque el alcance del impacto parezca menor.
A continuación, ve revisando la lista. Si existe una bifurcación mantenida y la API es compatible, cambia a ella, pruébala y sigue adelante. Esto cubre más casos de los que los equipos suelen esperar, aunque el esfuerzo depende de cuánto se haya desviado la API y de la cobertura de pruebas con la que cuentes. Si el paquete es pequeño y realmente lo entiendes, incorpóralo como dependencia y hazte cargo de su mantenimiento, pero deja por escrito quién es el responsable, porque el código incorporado como dependencia sin un responsable es precisamente la causa por la que este problema vuelve a surgir al cabo de tres años.
Si el paquete es grande, tiene implicaciones de seguridad y nadie se encarga de su mantenimiento, piénsatelo bien antes de incorporarlo como «vendor». Se trata de una obligación de corrección a largo plazo para la que tu equipo tendrá que destinar personal, y una biblioteca relevante para la seguridad que no tenga un responsable es peor que una dependencia externa evidente.
Si una dependencia obsoleta está impidiendo una actualización de PHP que ya te has comprometido a realizar, soluciona primero la dependencia y deja la actualización en tiempo de ejecución para más adelante. Intentar resolver ambas cosas a la vez convierte una migración en tiempo de ejecución de alcance limitado en un proyecto de corrección de dependencias mucho más amplio.
Y si las restricciones normativas o contractuales impiden seguir el calendario del proveedor principal, otra opción es recurrir a los parches proporcionados por el proveedor, tanto para el entorno de ejecución como para los paquetes afectados. De este modo, se siguen aplicando las correcciones de seguridad mientras la migración se lleva a cabo según un calendario que la empresa pueda realmente financiar.
El resultado variará mucho en función de la antigüedad de la aplicación y del marco de trabajo. Una aplicación de Laravel razonablemente actual, con dependencias que se mantienen activamente, suele tener por delante un proceso de actualización bastante sencillo. Una aplicación de hace diez años basada en un marco de trabajo propio y con cuarenta dependencias directas es un caso totalmente distinto, y cualquiera que asigne el mismo plazo a ambas opciones es que no ha utilizado «composer why-not» .
También puedes obtener más información sobre las mejores prácticas de seguridad de Laravel y la mitigación de amenazas del marco de trabajo en nuestra guía específica.
Garantizar la seguridad de la cadena de suministro de PHP
Los plazos de fin de vida útil de PHP se publican con años de antelación, y cualquier equipo que disponga de un calendario puede organizarse en función de ellos. El problema más complicado está en tu composer.lock en este mismo momento, sin previo aviso, sin haber sido programado y fuera del control de cualquiera en el momento en que un mantenedor abandona el proyecto.
Las propias herramientas de Composer te indicarán qué elementos están en desuso. No aplicará parches a ninguno de ellos. Ahí radica la carencia SecureChain para PHP , que reconstruye los paquetes a partir del código fuente y los analiza antes de que lleguen a tu compilación, para luego supervisarlos y aplicarles parches a medida que surgen vulnerabilidades. Cuando finaliza el mantenimiento de los paquetes por parte de los desarrolladores originales, TuxCare ELS amplía esa cobertura de parches, y hace lo mismo con las versiones de PHP en tiempo de ejecución que han llegado al final de su vida útil.
En lugar de crear una bifurcación de las bibliotecas en tu propio repositorio y heredar sin más sus CVE, dispones de una alternativa a Packagist, verificada y recompilada desde el código fuente, que se integra perfectamente en el mismo flujo de trabajo de Composer, por lo que el «abandono» deja de ser un riesgo que tu equipo tenga que asumir por sí solo.
PREGUNTAS FRECUENTES
¿Cuándo finaliza el ciclo de vida de PHP 8.1?
PHP 8.1 ya llegó al final de su ciclo de vida el 31 de diciembre de 2025, por lo que cualquier sistema que siga funcionando con esta versión ha dejado de recibir parches de seguridad del desarrollador original desde entonces, a menos que exista un acuerdo con un tercero para cubrir esa carencia.
¿Qué versiones de PHP siguen siendo compatibles?
PHP 8.2, 8.3, 8.4 y 8.5. De ellas, las versiones 8.2 y 8.3 se encuentran en fase de soporte exclusivo de seguridad, y la versión 8.2 dejará de contar incluso con ese soporte el 31 de diciembre de 2026. Consulta la página oficial de versiones compatibles de PHP para conocer el estado actual.
¿Cómo puedo encontrar los paquetes de Composer abandonados en mi proyecto?
Ejecutar composer audit, que por defecto falla con los paquetes abandonados en Composer 2.7 y versiones posteriores, o composer audit –abandoned=report si prefieres ver la lista sin interrumpir la compilación. A continuación, ejecuta composer show –outdated –direct para encontrar dependencias directas con versiones más recientes disponibles, y añade –sort-by-age para que las más antiguas aparezcan en primer lugar. Las marcas de «abandonado» de Packagist no son exhaustivas, así que comprueba la actividad del repositorio para detectar cualquier elemento que parezca obsoleto.
¿Qué ocurre con un paquete de Composer que tiene un CVE y no tiene responsable de mantenimiento?
El aviso se publica, pero es posible que un proyecto abandonado nunca lance una versión parcheada. Las opciones que tienes son crear una bifurcación y corregirlo tú mismo, sustituir la dependencia, documentar un control compensatorio o recurrir a un proveedor que adapte las correcciones a los paquetes abandonados.
¿Actualizar PHP soluciona el problema de las dependencias obsoletas de Composer?
No, y normalmente la relación es al revés. Un paquete abandonado con una restricción estricta de versión de PHP suele ser precisamente lo que impide la actualización en tiempo de ejecución, y por eso «composer why-not php 8.4» debe figurar al principio de cualquier conversación sobre el alcance de la actualización, y no al final.
¿Supone un problema de cumplimiento normativo utilizar PHP en fase de fin de vida útil?
Puede ser. Cuando un marco de trabajo exige la corrección oportuna de vulnerabilidades o el uso de software con soporte del proveedor, es difícil conciliar un entorno de ejecución en fin de vida útil con esos requisitos, ya que, una vez que dejan de publicarse correcciones por parte del desarrollador original, los equipos necesitan otra forma de demostrar que las vulnerabilidades recién reveladas siguen siendo corregidas. La ampliación del soporte de parches de seguridad, como el que ofrece TuxCare , puede ayudar a mantener intacta esa evidencia durante una migración, aunque lo que satisfaga a un auditor depende del marco específico y de cómo se implemente.



