← Todos los checks
SeguridadSeveridad típica: Bajo

Manifiestos de dependencias expuestos

Detecta package.json o composer.json accesibles que revelan tus dependencias y versiones exactas.

Qué comprueba

Este escáner comprueba si archivos de manifiesto de dependencias como package.json o composer.json son accesibles públicamente en tu web. Detecta cuando quedan servidos y revelan la lista de librerías que usas y sus versiones exactas.

Por qué importa

Conocer tus dependencias y versiones exactas facilita a un atacante buscar vulnerabilidades públicas que afecten justo a lo que usas. Es un trabajo de reconocimiento que le ahorras y que acota mucho por dónde intentar atacar tu web.

Cómo se arregla

Asegúrate de que estos archivos de manifiesto no se sirvan desde la carpeta pública; normalmente deben quedar en la raíz del proyecto, no en la carpeta web. Bloquea su acceso en la configuración del servidor o la CDN si tu framework los expone por defecto.

Cómo funciona esta comprobación

Scanaris pide dos archivos en la raíz de tu dominio: /package.json, el manifiesto de un proyecto Node, y /composer.json, el de un proyecto PHP. Para cada uno, da el hallazgo por confirmado solo si responde 200, el cuerpo no es HTML, es JSON válido y contiene las claves propias del manifiesto: dependencies o devDependencies en el primero, require o require-dev en el segundo. Así no marca una aplicación de una sola página que devuelve su HTML para cualquier ruta, ni un JSON cualquiera que casualmente viva ahí. Cada archivo encontrado abre un hallazgo de severidad baja.

Por qué importa

Estos archivos no contienen secretos, pero contienen algo casi tan útil para un atacante: la lista exacta de librerías que usas y sus versiones. Con eso no tiene que adivinar nada: cruza tu lista con la base de datos de vulnerabilidades conocidas y sabe qué exploit probar y contra qué. También revelan el nombre interno del proyecto, los scripts de build y despliegue, a veces la URL del repositorio privado y los nombres de paquetes internos de tu organización, que son el punto de partida de los ataques de confusión de dependencias. Es severidad baja porque es información, no acceso; pero es información que regalas sin motivo.

Por qué pasa

Porque el servidor web sirve la carpeta del proyecto entera en lugar de la carpeta de salida. Un Vite, Nuxt o Next.js bien desplegados solo publican dist/, .output/public/ o .next/static/, y ahí no hay package.json. Aparece cuando se sube el repositorio completo por FTP a public_html, cuando el directorio raíz de un hosting estático apunta a la raíz del proyecto, o en proyectos PHP donde composer.json está en el mismo directorio que index.php, que es lo habitual en WordPress con Composer y en instalaciones hechas a mano.

Cómo arreglarlo

  • Sirve solo la carpeta pública. En Vercel y Netlify, revisa el "output directory" o "publish directory" del proyecto; debe ser la carpeta de build, no .. En nginx y Apache, el root o DocumentRoot apunta a public/ o dist/.
  • En PHP, mueve composer.json, composer.lock y vendor/ un nivel por encima del directorio público si tu framework lo permite (Laravel y Symfony ya lo hacen). Si no puedes moverlos, bloquéalos:
location ~* /(package|composer)(-lock)?\.json$ { return 404; }
location ~* /(yarn|pnpm-lock)\.(lock|yaml)$ { return 404; }
  • En Apache, un <FilesMatch "^(package|composer)(-lock)?\.json$"> Require all denied </FilesMatch> en la configuración o en el .htaccess.
  • Revisa qué más se subió. Donde hay un package.json público suele haber un .env, un .git/ o un composer.lock al lado; la comprobación de archivos sensibles busca los graves.

Comprueba que está arreglado

for p in package.json composer.json package-lock.json composer.lock yarn.lock; do
  printf "%-20s " "$p"; curl -s -o /dev/null -w "%{http_code} %{content_type}\n" "https://tudominio.com/$p"
done

Esperado: 404 o 403. Un 200 con text/html es el HTML genérico de una aplicación de una sola página y no es problema; un 200 con application/json es el archivo real.

Preguntas frecuentes

Mi repositorio es público en GitHub de todos modos.

Entonces el manifiesto ya es público y este hallazgo no añade exposición nueva; puedes darlo por aceptado. Aun así, corregir la raíz del servidor evita que el siguiente archivo que caiga en la carpeta del proyecto se publique sin querer.

¿Y los lockfiles?

Esta comprobación mira los dos manifiestos, pero package-lock.json, yarn.lock y composer.lock son peores: listan todas las dependencias transitivas con versión exacta. Si el manifiesto está expuesto, casi seguro que el lockfile también; la regla de bloqueo de arriba los cubre.

Si no sirvo el manifiesto, ¿nadie puede saber qué versiones uso?

Pueden deducirlo por otros medios, más lentos: cabeceras, rutas de los bundles, comportamiento. Lo que detecta librerías desactualizadas en tu JavaScript, por ejemplo, lo ve cualquiera. Ocultar el manifiesto quita el atajo; actualizar las dependencias quita el problema.

Compruébalo en tu web

Escanea tu web gratis y mira si este y otros 44 checks pasan, con un prompt de arreglo por cada fallo.

Escanear mi web gratis

Checks relacionados