# Supply chain-aanvallen op npm en PyPI en wat je ertegen doet

URL: https://brainpowergroup.eu/nl/blog/supply-chain-aanvallen-op-npm-en-pypi
Datum: 2026-09-03 (bijgewerkt 2026-09-23)
Door: Milos, Brainpower Group

Bij een supply chain-aanval op npm of PyPI draait besmette code vaak al tijdens de installatie. Lockfiles met hashes en een wachttijd beperken het risico.

Bij een supply chain-aanval op npm of PyPI neemt de aanvaller een package over dat je team al vertrouwt en publiceert hij een nieuwe versie met kwaadaardige code. Vaak draait die al tijdens de installatie, op de laptop van een developer of in je CI, waar precies de tokens en cloudkeys staan die hij zoekt. Je beschermt je vooral met afspraken: lockfiles met hashes, een wachttijd voor nieuwe versies, publiceren zonder langlevende tokens en een review van elke nieuwe dependency.

## Hoe deze aanvallen verlopen

De ingang verschilt per incident, en elke ingang vraagt om een andere maatregel.

| Incident | Wanneer | Hoe de aanvaller binnenkwam |
|---|---|---|
| event-stream (npm) | 2018 | Bood zich aan als maintainer, kreeg het beheer en voegde een dependency toe die het op de Copay-wallet had gemunt |
| ua-parser-js (npm) | oktober 2021 | Nam het npm-account van de maintainer over en publiceerde drie versies met een cryptominer en een wachtwoorddief |
| xz utils | maart 2024 | Werkte ruim twee jaar mee, kreeg commitrechten en verstopte een backdoor in 5.6.0 en 5.6.1 (CVE-2024-3094) |
| Shai-Hulud (npm) | september 2025 | Een zichzelf verspreidende worm via overgenomen maintaineraccounts; GitHub haalde meer dan 500 packages weg |
| LiteLLM en telnyx (PyPI) | maart 2026 | Een publicatietoken lekte via een gecompromitteerde Trivy-dependency in de build |
| ChainDrop (npm) | augustus 2026 | Gestolen inloggegevens van een maintainer, daarna meer dan 400 besmette packages |

xz utils staat niet op npm of PyPI, maar laat goed zien hoeveel geduld een aanvaller kan hebben.

## Wat de wormen van 2025 en 2026 anders maken

Shai-Hulud nam in september 2025 automatisch packages over. GitHub beschrijft hem als een zichzelf verspreidende worm die binnenkwam via overgenomen maintaineraccounts, post-install scripts in populaire packages zette en meer soorten secrets kon stelen dan alleen npm-tokens.

ChainDrop werkte in augustus 2026 volgens Microsoft op een vergelijkbare manier. De malware haalde npm-, GitHub- en cloudcredentials van developerlaptops en CI-runners. Met gestolen publicatierechten bracht hij nieuwe patchreleases uit van andere packages van dezelfde maintainer. Een deel daarvan ging via de gewone GitHub Actions-workflow van het project naar npm en kreeg zo geldige provenance.

Provenance laat zien in welke pipeline een package is gebouwd, maar niet wie die pipeline op dat moment aanstuurde. Gebruik het als signaal en blijf zelf kijken wat je binnenhaalt.

## Lockfiles en een wachttijd voor nieuwe versies

Commit je lockfile en laat CI alleen installeren wat erin staat, met `npm ci` of `pnpm install --frozen-lockfile`. Gebruik bij Python een lockfile met hashes, bijvoorbeeld via `uv lock` of `pip-compile --generate-hashes`. `pip freeze` maakt volgens PyPI geen lockfile.

Een lockfile helpt alleen zolang niemand zonder te kijken een update accepteert, dus de diff van je lockfile hoort in de code review.

Een wachttijd helpt daarnaast. De besmette versies van LiteLLM stonden volgens PyPI 2 uur en 32 minuten online en werden in die tijd meer dan 119.000 keer gedownload. Bij telnyx was dat 3 uur en 42 minuten. Wie alleen versies installeerde die een paar dagen oud waren, had ze nooit binnengehaald.

npm heeft daarvoor de instelling `min-release-age`, en uv en pip kunnen hetzelfde met een relatieve datum. Mijn advies is drie tot zeven dagen, met een afgesproken snelle route voor beveiligingsupdates.

## Install scripts en de laptop van je developer

Bij ua-parser-js, Shai-Hulud en LiteLLM draaide de kwaadaardige code al tijdens de installatie, en op een developerlaptop staan GitHub-tokens, cloudcredentials en SSH-keys. Zet install scripts van dependencies daarom standaard uit waar je package manager dat toestaat, en sta ze alleen toe voor packages die ze nodig hebben.

Onze developers werken op beheerde, versleutelde laptops met centraal beheerde accounts en SSO met tweestapsverificatie. Ook dan kan een token in een `.env`-bestand uitlekken, dus houd secrets kort geldig en weg van de laptop. Hoe je dat aanpakt, staat in [secrets en API-keys veilig beheren](/nl/blog/secrets-en-api-keys-veilig-beheren).

## Publiceren zonder langlevende tokens

Publiceer je interne packages, of schrijft je CI met een token naar een registry, dan is dat token precies wat deze wormen zoeken.

npm kondigde na Shai-Hulud aan dat klassieke tokens verdwijnen en dat publiceren alleen nog kan met tweestapsverificatie, kortlevende tokens of trusted publishing. Bij trusted publishing krijgt je CI-workflow per publicatie een kortlevend token en sla je nergens een secret op. PyPI raadt hetzelfde aan, met tweestapsverificatie op elk account en bij voorkeur een hardware key.

ChainDrop laat zien waar dat ophoudt: met het GitHub-account van een maintainer kan een aanvaller de officiële workflow gebruiken. Laat releases daarom goedkeuren door een tweede persoon, bijvoorbeeld met een protected environment. Pin GitHub Actions op een commit-SHA in plaats van een tag, want een tag kan iemand verplaatsen.

## Review nieuwe dependencies zoals je code reviewt

Beantwoord bij elke nieuwe dependency in de pull request een paar vragen. Waarom dit package? Wie onderhoudt het en hoe lang bestaat het al? Heeft het install scripts? Laat ook update-PR's van Dependabot of Renovate door een mens reviewen in plaats van ze automatisch te mergen.

Onze developers werken elke dag met Claude Code, en zo'n tool kan een package voorstellen dat niemand in het team kent. Controleer dan of het bestaat en of het echt het package is dat je bedoelt, voordat het in je lockfile komt. Meer afspraken rond deze tools staan in [AI-codeertools in een remote team](/nl/blog/ai-codeertools-in-een-remote-team).

## Als het toch misgaat

Behandel elke laptop of runner waarop een besmette versie is geïnstalleerd als gecompromitteerd. Microsoft adviseerde bij ChainDrop om credentials vanaf een schone machine in te trekken en te vervangen, lockfiles, caches en artifact-repositories na te lopen en images opnieuw te bouwen vanaf een bekende goede basis. Dat advies past bij elk incident in de tabel.

Schrijf vooraf op welke tokens er zijn en wie ze kan intrekken. Wat andere bekende incidenten ons leren, staat in [wat we leren van bekende hacks](/nl/blog/wat-we-leren-van-bekende-hacks).

## Bronnen

- [npm: Details about the event-stream incident](https://blog.npmjs.org/post/180565383195/details-about-the-event-stream-incident)
- [CERT-EU: Security Advisory 2021-057 over UA-Parser-JS](https://www.cert.europa.eu/publications/security-advisories/2021-057/)
- [Russ Cox: Timeline of the xz open source attack](https://research.swtch.com/xz-timeline)
- [GitHub: Our plan for a more secure npm supply chain](https://github.blog/security/supply-chain-security/our-plan-for-a-more-secure-npm-supply-chain/)
- [PyPI: Incident report LiteLLM/Telnyx supply-chain attacks](https://blog.pypi.org/posts/2026-04-02-incident-report-litellm-telnyx-supply-chain-attack/)
- [Microsoft: ChainDrop supply chain compromise](https://www.microsoft.com/en-us/security/blog/2026/08/04/chaindrop-supply-chain-compromise-anatomy-self-propagating-worm/)

## Veelgestelde vragen

**Wat is een supply chain-aanval op npm of PyPI?**

Een aanvaller zet kwaadaardige code in een package dat jij als dependency gebruikt, meestal via een overgenomen maintaineraccount of een gehackte build-pipeline. Die code draait vaak al bij de installatie, op de laptop van je developer of in je CI.

**Beschermt een lockfile tegen een besmet package?**

Deels. Een lockfile met hashes zorgt dat je precies de versie installeert die je eerder hebt gecontroleerd. Hij helpt niet als iemand een update zonder review accepteert, dus de diff van je lockfile hoort in de code review.

**Wat doe je als je team een besmette versie heeft geïnstalleerd?**

Behandel de laptop of runner als gecompromitteerd. Trek vanaf een schone machine alle tokens en keys in die erop stonden, haal de versie uit lockfiles en caches en bouw images opnieuw op vanaf een bekende goede basis.

---

Bron: https://brainpowergroup.eu/nl/blog/supply-chain-aanvallen-op-npm-en-pypi
Brainpower Group, contact: https://brainpowergroup.eu/nl/contact, hello@brainpowergroup.eu
