Stuur binnen enkele uren een eerste verklaring (holding statement), een bevestigd antwoord zodra u het kunt aantonen, en een vervolgbericht zodra er iets verandert. Zeg wat u weet, wat u nog controleert en wanneer u een update stuurt. Baseer elk "niet getroffen" op wat uw builds tijdens de aanvalsperiode werkelijk hebben geïnstalleerd, niet op het lockfile van vandaag.
Dit artikel gaat over wat u zegt, wanneer, en met welk bewijs. Voor het onderzoek zelf, hoe u uitzoekt of een kwetsbaar component in uw producten zit en sinds wanneer, zie zijn wij getroffen door een CVE?.
Waarom klanten het u vragen en niet het pakketregister
In de week na een veelbesproken aanval, vertelde een kleine softwareleverancier ons, stuurden klanten hem sms'jes: is jullie spul veilig? Is mijn spul veilig? Zijn klanten werken met gevoelige gegevens, zijn team heeft geen securityspecialist, en de vraag moest dezelfde dag een antwoord krijgen.
Klanten vragen niet of een pakket is gecompromitteerd. Dat hebben het register en de onderzoekers al gezegd. Ze vragen of wat u hun hebt geleverd het bevat, omdat uw product hun blootstelling is. Hun eigen klanten, auditors of toezichthouders stellen hun dezelfde vraag. In gereguleerde ketens zoals halfgeleiders, industriële apparatuur en de zorg is de vraag contractueel, geen nieuwsgierigheid.
Ze vragen het ook opnieuw als uw antwoord niet te controleren is. "Wij zijn niet getroffen" zonder iets erachter is een belofte; "we hebben elke releasebuild van 24 tot 31 maart gecontroleerd en geen ervan installeerde de getroffen versies" is een verklaring waarop ze kunnen vertrouwen.
Vier recente aanvallen en de vraag die elk ervan opriep
Het juiste antwoord hangt af van hoe de aanval werkte, dus een sjabloon alleen is niet genoeg. Bij elk van deze aanvallen bepaalt één feit wat "getroffen" voor een leverancier betekent.
Backdoor in xz Utils (CVE-2024-3094), bekendgemaakt op 29 maart 2024. Andres Freund vond een backdoor in xz-versies 5.6.0 en 5.6.1. De release-tarballs bevatten code die niet in de Git-repository stond, en die injecteerde de backdoor tijdens de build. De NVD en Red Hat geven allebei een score van 10.0 onder CVSS 3.1. Hij bereikte vooral rolling- en testdistributies: Debian testing, unstable en experimental, Fedora Rawhide en 41, openSUSE Tumbleweed en Kali, terwijl stabiele releases niet getroffen waren. De vraag die hij opriep: bevat een image of apparaat dat we hebben geleverd xz 5.6.0 of 5.6.1, en welk base image gebruikte elke build?
De npm-worm Shai-Hulud, in golven sinds september 2025. Geïnfecteerde pakketten voeren bij installatie een script uit dat npm-, GitHub- en cloudcredentials steelt en die gebruikt om geïnfecteerde versies van meer pakketten te publiceren. De vraag die hij opriep: heeft een CI-job een geïnfecteerde versie geïnstalleerd, en zijn onze publicatietokens blootgesteld, waardoor wij zelf een verspreider zouden zijn? Onze Shai-Hulud-pagina somt elke golf op en beschrijft hoe u controleert.
LiteLLM op PyPI, 24 maart 2026. De versies 1.82.7 en 1.82.8 werden rechtstreeks naar PyPI geüpload met code die credentials steelt en die nooit in de GitHub-repository van het project heeft gestaan. In 1.82.8 voerde een .pth-bestand de payload uit telkens wanneer een Python-interpreter startte, niet alleen wanneer LiteLLM werd geïmporteerd; het verzamelde omgevingsvariabelen, SSH-sleutels, cloudcredentials en Kubernetes-secrets. HiddenLayer koppelt de aanval aan TeamPCP, dat die maand ook tooling van Trivy en Checkmarx trof. De eigen advisory van LiteLLM geeft twee verklaringen voor de eerste toegang: die herleidt de compromittering tot de Trivy-afhankelijkheid in de workflow voor securityscans in CI, en zegt dat het PyPI-account van een maintainer mogelijk is gecompromitteerd. Zelfs de blootstellingsperiode verschilt binnen dezelfde advisory: op de ene plek ongeveer 40 minuten, op een andere van 10:39 tot 16:00 UTC. De vraag die het opriep: bevatte een build of een geleverde container die versies, en welke secrets waren in die omgeving aanwezig?
axios op npm, 31 maart 2026. Een aanvaller nam het npm-account van een maintainer over en publiceerde axios 1.14.1 en 0.30.4, die een afhankelijkheid toevoegden, [email protected], waarvan het installatiescript een remote access trojan voor macOS, Windows en Linux plaatste. Datadog stelt de periode op 00:21 tot 03:25 UTC; volgens Snyk waren de versies om 03:29 UTC verwijderd. De vraag die het opriep: heeft een build die versies in die periode opgehaald? Een lockfile dat vóór de periode was gecommit, antwoordt "nee" voor builds die het gebruikten, en zegt niets over builds die npm install zonder lockfile draaiden.
| Aanval | Ecosysteem | Getroffen versies | Periode | Wat "getroffen" betekent voor een leverancier |
|---|---|---|---|---|
| xz Utils | Linux-distributies | 5.6.0, 5.6.1 | Weken, tot de bekendmaking op 29 maart 2024 | U hebt het geleverd, in een image of apparaat gebouwd op een getroffen distributie |
| Shai-Hulud | npm | Honderden pakketten, per golf | Uren tot dagen per golf | U hebt ermee gebouwd, en uw tokens kunnen het hebben verspreid; misschien hebt u het ook geleverd |
| LiteLLM | PyPI | 1.82.7, 1.82.8 | 24 maart 2026, vanaf 10:39 UTC (bronnen verschillen over het einde) | U hebt ermee gebouwd of het geleverd, en secrets in die omgeving kunnen gestolen zijn |
| axios | npm | 1.14.1, 0.30.4 | 31 maart 2026, ongeveer 00:21 tot 03:25 UTC | U hebt er tijdens de periode mee gebouwd; de trojan draaide op de buildmachine |
Dezelfde vragen komen op bij een kritieke kwetsbaarheid die geen aanval op de softwareketen is. Toen PHP2Shell in oktober 2026 werd misbruikt, vroegen klanten van elk product dat PHP meelevert welke van hun versies een getroffen PHP bevatten. De stappen hieronder gelden ongewijzigd.
Het antwoord kent drie fasen
| Fase | Wanneer | Wat u stuurt |
|---|---|---|
| Eerste verklaring | Binnen enkele uren na het nieuws | Wat u weet, wat u controleert, wanneer u een update stuurt |
| Bevestigd antwoord | Zodra u het kunt aantonen, meestal op dag één | "Niet getroffen" voor genoemde versies, of "getroffen" met wat te doen |
| Vervolgbericht | Wanneer de fix uitkomt, wanneer u iets nieuws te weten komt, wanneer u de case sluit | Hetzelfde bericht, herzien |
Het eerste uur: de eerste verklaring
Een eerste verklaring is de eerste openbare verklaring die u aflegt voordat de feiten bekend zijn. Zeg snel iets wat waar is. Stilte wordt opgevuld met aannames, en een klant die niets van u hoort, neemt aan dat u het niet hebt opgemerkt.
- Wie en waar. Eén afzender met naam, in het kanaal dat de klant gebruikte, plus uw securitypagina. Eén gedeelde tekst is beter dan losse antwoorden: hij blijft consistent, en juridische zaken hoeft hem maar één keer te beoordelen.
- Wat erin staat. Dat u van de aanval weet, dat u uw producten en buildsystemen controleert, wat u tot nu toe weet, wanneer de volgende update komt, en met wie men contact kan opnemen.
- Wat er niet in mag staan. "Wij zijn niet getroffen" voordat u het hebt gecontroleerd, speculatie over de aanvaller, of het aanwijzen van schuldigen.
Sjabloon 1: eerste verklaring
Onderwerp: [naam van de aanval]: onze eerste verklaring
Wij zijn op de hoogte van de gemelde compromittering van [pakket of project] ([getroffen versies], gepubliceerd op [datum]). Ons securityteam controleert elke release van [product] en onze buildsystemen op de getroffen versies. Tot nu toe hebben wij [geen getroffen versies gevonden in de gecontroleerde producten / de controle nog niet afgerond]. Wij sturen u uiterlijk [datum en tijd, tijdzone] een update. Hebt u in de tussentijd vragen, neem dan contact op met [naam, adres van het securitycontact]. Wij speculeren niet over de gevolgen voordat de controle is afgerond.
Voor een sms of chatbericht zijn twee zinnen genoeg:
Wij zijn op de hoogte van de compromittering door [naam van de aanval] en controleren nu elke release van [product] en onze builds. U ontvangt uiterlijk [tijdstip] een bevestigd antwoord van ons.
Laat alle drie de sjablonen goedkeuren door uw juridisch adviseur voordat u ze nodig hebt.
Dag één: bevestig, met bewijs
Er zijn twee uitkomsten mogelijk, en elk heeft eigen bewijs nodig. Verzamel voor een antwoord "niet getroffen":
- het getroffen pakket en de versies, uit de advisory of de analyse van de onderzoekers
- uw producten en de versies die klanten werkelijk draaien
- voor elk van die versies de build die hem opleverde en de vastlegging van wat die build installeerde, niet het huidige lockfile
- elke build die tijdens de aanvalsperiode draaide, inclusief CI-jobs die nooit een release opleverden
- bij wormen die tokens stelen: of er CI-secrets aanwezig waren in jobs die de kwaadaardige code konden hebben uitgevoerd
Zijn wij getroffen door een CVE? legt uit hoe u elk van deze punten vaststelt.
Elke verklaring die u aflegt, moet worden onderbouwd met iets wat u kunt laten zien:
| Verklaring | Wat u moet kunnen laten zien | Wat niet genoeg is |
|---|---|---|
| "Product X versie Y bevat pakket Z niet" | De SBOM die is vastgelegd uit de releasebuild van versie Y | Een scan van de huidige repository |
| "Geen van onze builds heeft de gecompromitteerde versies geïnstalleerd" | Installatiegegevens voor elke build in de periode | Een lockfile dat sommige jobs omzeilen |
| "Onze releasepipeline is niet gecompromitteerd" | Gegevens over netwerkverkeer en gebruik van secrets in de periode | Het uitblijven van alerts |
| "Klanten op versie Y zijn na de upgrade veilig" | De vastlegging van de gerepareerde build, en de credentials die u hebt geroteerd | Een vermelding in de changelog |
Sjabloon 2: niet getroffen
Onderwerp: [naam van de aanval]: [product] is niet getroffen
Wij hebben onze controle op de compromittering van [pakket] ([getroffen versies]) afgerond. De volgende versies van [product] zijn niet getroffen: [lijst van gecontroleerde producten en versies]. Wij hebben elke releasebuild en CI-build gecontroleerd die tussen [begindatum] en [einddatum] heeft gedraaid. Deze verklaring is gebaseerd op de vastlegging van de componenten die elke releasebuild heeft geïnstalleerd, niet op een scan van onze huidige broncode. Geen van deze builds heeft de getroffen versies geïnstalleerd. Hebt u het bewijs nodig, dan kunnen wij u de SBOM sturen voor de versies die u gebruikt, of een VEX-verklaring. Komen wij iets te weten wat deze beoordeling verandert, dan laten wij het u weten. Contact: [naam, adres van het securitycontact].
Zeg "niet getroffen" voor genoemde versies. Schrijf nooit "100% veilig". Vraagt de klant daarna om de volledige SBOM, zie dan SBOM-verzoeken van klanten beantwoorden.
Sjabloon 3: getroffen, met mitigatie
Onderwerp: [naam van de aanval]: actie vereist voor [product] versies [x tot en met y]
Onze controle op de compromittering van [pakket] heeft uitgewezen dat [product] versies [x tot en met y] getroffen zijn. De eerste getroffen build is gemaakt op [datum]; versie [z], uitgebracht op [datum], bevat [pakketversie] niet meer.
Wat dit betekent: [risico in begrijpelijke taal, bijvoorbeeld "een component dat in deze versies is geïnstalleerd, kan inloggegevens van het systeem waarop het draait naar een externe server sturen"].
Wat u nu moet doen: upgrade naar [product] [z]. Kunt u niet direct upgraden, [mitigatie, bijvoorbeeld blokkeer uitgaande verbindingen naar de vermelde hosts]. Hebt u [product] versies [x tot en met y] gebruikt in [omgeving], roteer dan de [inloggegevens of sleutels] die daarin beschikbaar waren.
Wat wij hebben gedaan: wij hebben de getroffen versies uit onze builds verwijderd, [product] opnieuw gebouwd met schone afhankelijkheden, de credentials van onze buildsystemen geroteerd en [andere maatregelen]. [Waar dat verplicht is, hebben wij de bevoegde autoriteiten ingelicht.]
Wij sturen u uiterlijk [datum] de volgende update, of eerder als er iets verandert. Contact: [naam, adres van het securitycontact].
Een bericht "getroffen" kan ook een wettelijke plicht zijn; zie de sectie over meldplicht hieronder.
Waar VEX en CSAF passen. Een verklaring "niet getroffen" of "opgelost" kan worden gepubliceerd als VEX, zodat de scanners van klanten het pakket niet meer markeren. Grotere klanten verwachten mogelijk ook een machineleesbare advisory; CSAF is het formaat waar de meesten om vragen.
Vervolgbericht: sluit het netjes af
Stuur een vervolgbericht wanneer de fix uitkomt, wanneer uw onderzoek iets nieuws vindt, en een laatste bericht wanneer de case wordt gesloten. Houd één advisory per incident aan en herzie die in plaats van elke keer een nieuwe te sturen (bijwerken, niet vervangen). Leg vast wat u wie wanneer hebt verteld: de volgende audit of securityvragenlijst van een klant vraagt ernaar.
Wat u zegt als u het nog niet weet
"We weten het nog niet" wekt meer vertrouwen dan een "niet getroffen" dat u moet intrekken. Formuleringen die eerlijk zijn zonder iemand ongerust te maken:
- "Wij hebben [pakket] niet gevonden in [de tot nu toe gecontroleerde producten]. Wij controleren nog [resterende producten of buildsystemen] en sturen u uiterlijk [tijdstip] een update."
- "De versies die u gebruikt, zijn gebouwd vóór de aanvalsperiode. Wij bevestigen nog dat geen latere build ze heeft vervangen."
- "Wij controleren of een van onze buildsystemen de getroffen versies heeft gedraaid. Uw geïnstalleerde product is een aparte vraag, en wij beantwoorden ze allebei."
Formuleringen die u beter vermijdt:
- "Geen enkele impact"
- "Volledig veilig"
- "Niet getroffen door welke aanval op de softwareketen dan ook"
- "Onze scanner heeft niets gevonden"
Wanneer de aanval een meldplicht wordt
Verkoopt u producten met digitale elementen in de EU, dan gelden de meldplichten van de Cyber Resilience Act sinds 11 september 2026, de dag waarop ENISA het gemeenschappelijke meldplatform lanceerde. Een actief misbruikte kwetsbaarheid in uw product, of een ernstig incident dat gevolgen heeft voor de beveiliging ervan, leidt tot een vroegtijdige waarschuwing binnen 24 uur nadat u ervan op de hoogte bent geraakt, een melding binnen 72 uur en een eindrapport, ingediend via het platform bij uw coördinerende CSIRT en ENISA. De CRA-gids loopt de stappen door.
Of een gecompromitteerde afhankelijkheid die u hebt geleverd, of een compromittering van uw eigen buildpipeline, aan die definities voldoet, is een oordeel voor u en uw juridisch adviseur, niet voor dit artikel. De verordening definieert de begrippen:
- Een "actief misbruikte kwetsbaarheid" is "een kwetsbaarheid waarvoor er betrouwbaar bewijs is dat een kwaadwillende actor deze zonder toestemming van de eigenaar van het systeem in een systeem heeft misbruikt" (artikel 3, punt 42).
- Een incident is ernstig als "het een negatief effect heeft of kan hebben op het vermogen van een product met digitale elementen om de beschikbaarheid, authenticiteit, integriteit of vertrouwelijkheid van gevoelige of belangrijke gegevens of functies te beschermen", of als "het heeft geleid of kan leiden tot de invoering of uitvoering van kwaadaardige code" in het product of in de systemen van een gebruiker (artikel 14(5)).
Artikel 14(8) voegt een plicht jegens gebruikers toe: informeer de getroffen gebruikers, en waar passend alle gebruikers, over de kwetsbaarheid of het incident en over eventuele mitigerende maatregelen die zij kunnen nemen, "waar passend in een gestructureerd, machineleesbaar formaat dat gemakkelijk automatisch kan worden verwerkt". Sjabloon 3 kan deel uitmaken van het nakomen van die plicht.
Ook andere regimes zijn van toepassing. Onder NIS2 melden essentiële en belangrijke entiteiten significante incidenten aan hun CSIRT of bevoegde autoriteit, en veel klantcontracten bevatten eigen meldingsclausules met eigen termijnen.
Wees voorbereid op de volgende
- Een vastlegging van wat elke releasebuild heeft geïnstalleerd, bewaard gedurende de ondersteuningsperiode van het product (SBOM's tijdens de build).
- Een lijst van welke klanten welke versies draaien.
- De drie sjablonen hierboven, goedgekeurd door juridische zaken.
- Een afzender met naam en een kanaal voor elk soort klant.
- Een securitypagina en een
security.txt-bestand waar updates terechtkomen (gecoördineerde openbaarmaking van kwetsbaarheden). - Egress-controle in CI, zodat een gecompromitteerd pakket geen secrets kan versturen naar een host die de build niet nodig heeft (egress-beleid voor GitHub Actions).
Voor incidenten die met honderden tegelijk binnenkomen in plaats van één voor één, zie een PSIRT opschalen.
Hoe CRACI past
De bewijstabel hierboven vraagt steeds om één ding: een vastlegging van wat elke releasebuild heeft geïnstalleerd. Dat is wat CRACI bewaart. CRACI draait uw GitHub Actions-builds op eigen runners en legt elk pakket vast dat elke job werkelijk binnenhaalde, inclusief pakketten die door installatiescripts zijn opgehaald en pakketten die uit caches zijn hersteld. De SBOM van elke eerdere build wordt bewaard, dus "heeft een build tijdens de periode axios 1.14.1 geïnstalleerd?" wordt beantwoord uit de buildgeschiedenis, met de periode waarin u getroffen was, zo ver terug als uw bewaartermijn reikt.
Bekende kwaadaardige releases met een gepubliceerde CVE, zoals de xz-backdoor, worden gemarkeerd zoals elke andere kwetsbaarheid, en een policy gate kan builds blokkeren die ze bevatten. CRACI detecteert een nieuw kwaadaardig pakket niet op basis van gedrag of reputatie.
Het egress-beleid van CRACI blokkeert verbindingen met hosts die een build niet nodig heeft, wat beperkt wat een kwaadaardig installatiescript naar buiten kan sturen, zelfs bij een aanval die nog niemand heeft gezien. Vraagt een klant om het bewijs, dan kunt u de SBOM voor de versies die hij draait exporteren als CycloneDX of SPDX en opsturen. CRACI ondersteunt VEX.
Beantwoord "waren wij getroffen?" uit uw buildgeschiedenis, of lees meer over hoe aanvallen op de softwareketen werken.
Wanneer CRACI niet het antwoord is
- U hebt hulp nodig bij de communicatie zelf. PR en juridisch advies zijn een ander vak.
- De getroffen software is niet op CRACI gebouwd. CRACI legt GitHub Actions-builds vast die op zijn runners draaien; andere CI-systemen staan op de roadmap.
- De vraag gaat over het product van een leverancier dat u niet zelf hebt gebouwd. SBOM's van leveranciers kunnen aan CRACI worden toegevoegd, maar het antwoord is maar zo goed als de SBOM van de leverancier.
- U wilt een gloednieuw kwaadaardig pakket onderscheppen voordat er een advisory bestaat. CRACI markeert bekende kwaadaardige releases zodra er een advisory met een CVE is gepubliceerd; het detecteert geen malware op basis van gedrag of reputatie (reageren op zero-day-kwetsbaarheden).
Veelgestelde vragen
Wat vertel ik klanten als een aanval op de softwareketen in het nieuws is?
Stuur binnen enkele uren een eerste verklaring: u weet van de aanval, u controleert uw producten en builds, wat u tot nu toe weet, en wanneer u een update stuurt. Laat daarop een bevestigd antwoord volgen voor genoemde productversies zodra u het met buildgegevens kunt onderbouwen, en een vervolgbericht zodra er iets verandert.
Wat moet er in een eerste verklaring staan?
Wat er is gebeurd in één zin, dat u uw producten en buildsystemen controleert, wat u tot nu toe hebt gevonden, het tijdstip van de volgende update en een contactpersoon. Er mag niet in staan dat u "niet getroffen" bent voordat u het hebt gecontroleerd, geen speculatie over de aanvaller en geen beschuldiging aan iemands adres.
Hoe zeg ik "wij zijn niet getroffen" zonder te veel te beloven?
Noem de producten en versies die u hebt gecontroleerd, de periode van de builds die u hebt gecontroleerd en het bewijs dat u hebt gebruikt, zoals de vastlegging van de componenten die elke releasebuild heeft geïnstalleerd. Zeg "niet getroffen" voor die versies, bied de SBOM of een VEX-verklaring aan, en beloof een update als er iets verandert. Vermijd "100% veilig" of "volledig veilig".
Wat moet er in een bericht "wij waren getroffen" aan klanten staan?
Welke producten en versies getroffen zijn, sinds wanneer en tot welke gerepareerde versie, het risico in begrijpelijke taal, wat de klant nu moet doen (upgraden, credentials roteren, hosts blokkeren), wat u al hebt gedaan, wanneer de volgende update komt en met wie men contact kan opnemen.
Welk bewijs moet een verklaring "niet getroffen" onderbouwen?
Voor elke versie die klanten draaien de vastlegging van wat de build die hem opleverde heeft geïnstalleerd, niet het lockfile van vandaag. Voeg de gegevens toe van elke build die tijdens de aanvalsperiode draaide en, bij aanvallen die credentials stelen, of er secrets aanwezig waren in jobs die de kwaadaardige code konden hebben uitgevoerd.
Moet ik een aanval op de softwareketen melden onder de Cyber Resilience Act?
Mogelijk. Sinds 11 september 2026 moeten fabrikanten van producten met digitale elementen die in de EU worden verkocht actief misbruikte kwetsbaarheden en ernstige incidenten met gevolgen voor de productbeveiliging melden: een vroegtijdige waarschuwing binnen 24 uur, een melding binnen 72 uur en een eindrapport. Of een bepaalde aanval daaronder valt, is een oordeel voor u en uw juridisch adviseur.
Hoe snel moeten we klanten antwoorden?
Binnen enkele uren met een eerste verklaring, ook als die alleen zegt dat u aan het controleren bent en wanneer u een update stuurt. Het bevestigde antwoord volgt zodra u het kunt aantonen. Een snel en eerlijk "we zijn aan het controleren" doet meer voor het vertrouwen dan een laat "niet getroffen".
