Saltar al contenido
Volver al blog
LaravelSeguridadBuenas prácticas

Laravel Vet revisa dependencias antes de actualizar Composer

Laravel Vet añade una revisión explícita de dependencias y convierte la confianza en un archivo versionado.

Ismael Catala6 min de lectura

El problema no está solo en el composer.lock

Cuando ejecuto composer update, no estoy cambiando únicamente números de versión. Estoy incorporando código de terceros a una aplicación, a menudo con cambios que nadie del equipo ha leído. El composer.lock hace que la instalación sea reproducible, pero no responde a una pregunta básica: quién revisó los archivos de esa dependencia y en qué versión.

Laravel Vet propone añadir esa comprobación al flujo normal de Composer. Guarda las decisiones de confianza en un archivo llamado vet.json, que debe vivir en la raíz del proyecto junto a composer.json. Así, la revisión deja de ser una conversación perdida en una pull request y pasa a formar parte del repositorio. (github.com)

Una barrera antes de escribir cambios en vendor

Vet se instala como dependencia de desarrollo y funciona como un plugin de Composer. Según su documentación, interviene después de composer install y antes de que composer update escriba los paquetes actualizados en vendor. La diferencia importa: en una actualización puede detener la entrada de código no confiado antes de que se instale; en una instalación valida el estado y hace fallar el proceso si encuentra paquetes sin registrar como confiables. (github.com)

La instalación es la habitual y requiere PHP 8.4 o superior. La primera vez Composer pedirá permiso para ejecutar el plugin, porque es un componente que participa en sus operaciones. No conviene aceptar ese permiso por inercia: aquí precisamente estamos dando acceso a una herramienta que inspecciona y condiciona la instalación de dependencias.

composer require laravel/vet --dev
 
./vendor/bin/vet --init

El comando --init crea el primer vet.json a partir de los paquetes que ya existen en vendor. Es un punto de partida útil para introducir la herramienta en un proyecto que ya está en marcha. También existe --fresh, que elimina el archivo de confianza actual y vuelve a inicializarlo desde cero. (github.com)

La confianza queda versionada

El contenido de vet.json no se limita al nombre del paquete. Vet registra la versión revisada y un hash del árbol de archivos del paquete. Si alguien publica bytes distintos bajo una versión que ya figuraba como confiable, el hash deja de coincidir y la herramienta vuelve a exigir revisión. (github.com)

Esto es lo que convierte la idea en algo más serio que una lista de paquetes permitidos. No se confía indefinidamente en un nombre de Packagist, sino en una versión concreta y en los archivos que se habían revisado. Mi recomendación es sencilla: añadir vet.json al control de versiones y revisarlo en las pull requests igual que se revisa composer.lock.

{
    "schema": 4,
    "require": {
        "carbonphp/carbon-doctrine-types": {
            "version": "3.2.1",
            "hash": "tree-v2:0f158f3b909fc01e691ed5f5121186056232b049031e7d3a914676d49881ece5"
        }
    }
}

No tomaría ese ejemplo como una plantilla para copiar hashes, claro. El archivo se genera y actualiza desde el propio proyecto, con las dependencias que realmente tienes instaladas. Lo importante es entender que cualquier cambio en él representa una nueva decisión de confianza que merece contexto y revisión humana.

Revisar a mano o pedir una segunda lectura

El comando principal es ./vendor/bin/vet. En una terminal muestra los paquetes que todavía no son confiables y permite seleccionar cuáles se aceptan después de revisar los cambios. Si queda alguno sin aprobar, termina con un código de salida distinto de cero, que es justo el comportamiento que interesa en automatización. (github.com)

También puede entregar los diffs a un agente de código disponible en la máquina, entre ellos Claude Code, Codex, Gemini u opencode. El agente devuelve estados como PASS, FAIL, WARN o SKIP, pero no toma la decisión por mí. Vet solo escribe en vet.json cuando yo selecciono explícitamente los paquetes que quiero confiar. (github.com)

Me parece una integración razonable de IA en seguridad: reducir el trabajo de lectura inicial sin convertir un modelo en una autoridad silenciosa. Un PASS sirve para priorizar, no para bajar la guardia. Un FAIL o un WARN obliga a mirar el contexto, y una actualización especialmente sensible merece revisión manual aunque el agente no detecte nada extraño.

Encaja en CI, pero no sustituye la revisión

En un CI sin terminal interactiva, Vet no formula preguntas: informa del problema y falla cuando encuentra paquetes no confiables. Eso permite usarlo como una política verificable en proyectos Laravel autoalojados, siempre que composer.lock y vet.json estén comprometidos en el repositorio. El objetivo no es que el servidor decida qué instalar, sino impedir que acepte dependencias nuevas o modificadas sin una decisión previa del equipo. (github.com)

Una comprobación mínima puede quedarse así:

composer install --no-interaction --prefer-dist
./vendor/bin/vet

En la práctica, el flujo más limpio es revisar las actualizaciones en local o en una pull request con una terminal disponible. Después se confirma el cambio de vet.json, y el CI se limita a comprobar que el estado instalado coincide con la confianza registrada. Eso separa bien el momento de analizar una dependencia del momento de desplegarla.

La letra pequeña

--init no audita retrospectivamente las dependencias que ya tienes. Confía en los bytes presentes en vendor en ese instante, así que no es una limpieza automática del historial ni una garantía de que la base inicial sea segura. Si quieres una adopción estricta, tendrás que decidir qué paquetes revisar desde cero antes de registrar esa línea base. (github.com)

Vet tampoco reemplaza los avisos de vulnerabilidades, la revisión de licencias, el mantenimiento de versiones o el análisis estático de tu aplicación. Su alcance es distinto: saber que alguien ha aceptado explícitamente el código de una dependencia y detectar que esos archivos cambian. Es una capa de proceso, no un antivirus para paquetes PHP.

Hay otra cuestión práctica si se usa con agentes: los cambios de dependencias pueden salir de tu máquina para ser analizados por el proveedor del agente. Vet muestra el número y tamaño de los prompts antes de enviarlos, pero la responsabilidad sobre datos, credenciales y políticas internas sigue siendo del equipo. Además, el proyecto se encuentra en beta, por lo que conviene probarlo en una rama o repositorio no crítico antes de convertirlo en un requisito de despliegue. (github.com)

Laravel Vet no elimina el riesgo de la cadena de suministro. Lo que hace es quitar una excusa habitual: que una actualización entró porque Composer la resolvió y nadie se paró a mirar. Para equipos que mantienen aplicaciones Laravel durante años, versionar esa decisión de confianza me parece una mejora concreta y fácil de explicar.


Fuente: Laravel News Documentación oficial: laravel/vet