← Alle checks
BeveiligingTypische ernst: Laag

Blootgestelde dependency-manifesten

Detecteert toegankelijke package.json- of composer.json-bestanden die je exacte dependencies en versies onthullen.

Wat het checkt

Deze scanner controleert of manifestbestanden van afhankelijkheden zoals package.json of composer.json openbaar toegankelijk zijn op je site. Hij detecteert wanneer ze worden geserveerd en de lijst van bibliotheken die je gebruikt samen met hun exacte versies onthullen.

Waarom het belangrijk is

Je exacte afhankelijkheden en versies kennen maakt het voor een aanvaller makkelijk om publieke kwetsbaarheden op te zoeken die precies dat treffen wat jij gebruikt. Het is verkenningswerk dat je hem bespaart en het beperkt sterk waar hij je site probeert aan te vallen.

Hoe je het oplost

Zorg dat deze manifestbestanden niet vanuit de publieke map worden geserveerd; ze horen normaal in de projectroot thuis, niet in de webmap. Blokkeer de toegang ertoe in de configuratie van je server of CDN als je framework ze standaard blootstelt.

Hoe deze controle werkt

Scanaris vraagt twee bestanden op in de root van je domein: /package.json, het manifest van een Node-project, en /composer.json, dat van een PHP-project. Voor elk bevestigt hij de bevinding alleen als het 200 antwoordt, de body geen HTML is, het geldige JSON is en het de sleutels bevat die bij dat manifest horen: dependencies of devDependencies bij het eerste, require of require-dev bij het tweede. Zo meldt hij geen single-page app die voor elk pad zijn HTML teruggeeft, en geen willekeurige JSON die daar toevallig staat. Elk gevonden bestand opent een bevinding met lage ernst.

Waarom dit belangrijk is

Deze bestanden bevatten geen geheimen, maar wel iets dat voor een aanvaller bijna even nuttig is: de exacte lijst van bibliotheken die je gebruikt en hun versies. Daarmee hoeft hij niets te raden: hij legt je lijst naast de database van bekende kwetsbaarheden en weet welke exploit hij tegen wat moet proberen. Ze onthullen ook de interne projectnaam, de build- en deployscripts, soms de URL van de privérepository en de namen van interne pakketten van je organisatie, die het startpunt zijn van dependency-confusion-aanvallen. Het is lage ernst omdat het informatie is, geen toegang; maar het is informatie die je zonder reden weggeeft.

Waarom het gebeurt

Omdat de webserver de hele projectmap serveert in plaats van de uitvoermap. Een goed gedeployde Vite, Nuxt of Next.js publiceert alleen dist/, .output/public/ of .next/static/, en daar staat geen package.json. Het duikt op wanneer de volledige repository via FTP naar public_html wordt geüpload, wanneer de rootmap van een statische host naar de projectroot wijst, of in PHP-projecten waar composer.json in dezelfde map staat als index.php, wat gebruikelijk is bij WordPress met Composer en bij handmatige installaties.

Hoe je het oplost

  • Serveer alleen de openbare map. Controleer op Vercel en Netlify de "output directory" of "publish directory" van het project; dat moet de buildmap zijn, niet .. In nginx en Apache wijst root of DocumentRoot naar public/ of dist/.
  • In PHP verplaats je composer.json, composer.lock en vendor/ één niveau boven de openbare map als je framework dat toelaat (Laravel en Symfony doen dat al). Kun je ze niet verplaatsen, blokkeer ze dan:
location ~* /(package|composer)(-lock)?\.json$ { return 404; }
location ~* /(yarn|pnpm-lock)\.(lock|yaml)$ { return 404; }
  • In Apache een <FilesMatch "^(package|composer)(-lock)?\.json$"> Require all denied </FilesMatch> in de configuratie of in de .htaccess.
  • Controleer wat er nog meer is geüpload. Waar een openbare package.json staat, staat meestal een .env, een .git/ of een composer.lock ernaast; de controle gevoelige bestanden zoekt de ernstige gevallen.

Controleer of het opgelost is

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://jouwdomein.nl/$p"
done

Verwacht: 404 of 403. Een 200 met text/html is de generieke HTML van een single-page app en is geen probleem; een 200 met application/json is het echte bestand.

Veelgestelde vragen

Mijn repository is toch al openbaar op GitHub.

Dan is het manifest al openbaar en voegt deze bevinding geen nieuwe blootstelling toe; je kunt hem als geaccepteerd markeren. Toch voorkomt het herstellen van de serverroot dat het volgende bestand dat in de projectmap belandt per ongeluk wordt gepubliceerd.

En lockfiles?

Deze controle kijkt naar de twee manifesten, maar package-lock.json, yarn.lock en composer.lock zijn erger: ze noemen elke transitieve afhankelijkheid met exacte versie. Is het manifest blootgesteld, dan is het lockfile dat vrijwel zeker ook; de blokkeerregel hierboven dekt ze.

Als ik het manifest niet serveer, kan dan niemand weten welke versies ik gebruik?

Ze kunnen het via andere, tragere wegen afleiden: headers, bundelpaden, gedrag. Wat verouderde bibliotheken in je JavaScript detecteert, ziet bijvoorbeeld iedereen. Het manifest verbergen haalt de sluiproute weg; de afhankelijkheden bijwerken haalt het probleem weg.

Check het op je site

Scan je site gratis en zie of deze en 44 andere checks slagen, met een fixprompt voor elk probleem.

Mijn site gratis scannen

Gerelateerde checks