Hacker blokkeert verwijderen van packages uit npm-registry met memepackage

Door een grap van een npm-contributor konden ontwikkelaars dagenlang hun npm-packages niet uit de centrale registry verwijderen. Een hacker publiceerde een package waarin alle andere npm-packages werden opgenomen, wat tot onverwachte problemen leidde.

Op 29 december publiceerde npm-gebruiker gdi2290 een package in de npm-registry met daarin vijf dependency's die samen automatisch iedere andere gepubliceerde npm-package opnemen. Die package heet everything en bevat volgens onderzoekers een readme waarin de makers oproepen de package niet te installeren. Het zou een memepackage zijn en niet serieus zijn bedoeld, maar ondanks de slechts 224 installaties bleek de repo grote gevolgen te hebben voor andere ontwikkelaars.

In de eerste plaats kan de package een denial-of-service veroorzaken doordat er bij een installatie meer dan drieduizend npm-chunks met miljoenen packages uit de centrale registry worden gedownload. Maar het grootste probleem zit in het beleid van npm om packages automatisch te kunnen verwijderen uit de registry. Een van de criteria van dat beleid is dat packages alleen kunnen worden gedepubliceerd als geen enkele andere package die in een dependency heeft opgenomen.

Omdat de everythingpackage dat wel deed, bleek het niet mogelijk te zijn om nog langer zelf packages te verwijderen. Ook kon de originele uploader de package daardoor niet langer verwijderen. Die moest daarvoor aankloppen bij npm en bij moederbedrijf GitHub, dat zegt het pakket te verwijderen.

Door Tijs Hofmans

Nieuwscoördinator

05-01-2024 • 11:44

76

Reacties (76)

76
76
68
2
0
2
Wijzig sortering
Ik begrijp het, het is naar. Het is geautomatiseerde chaos. Toch wil ik wel een anekdote delen gebaseerd op dit fenomeen:

https://qz.com/646467/how...ting-a-tiny-piece-of-code

left-pad, een infamous javascript package met welgeteld 1 functie die letterlijk OVERAL gebruikt wordt. Dus als die in een zwart gat verdwijnt, dan heeft dat idiote gevolgen. Het zou me niets verbazen als dit incident de reden is waarom we nu dit nieuwsbericht lezen :)

Waarom zou je een package gebruiken met 1 kleine functie erin (met code waar je ogen van verstuiken) om enkel wat padding toe te voegen aan een string!? - kun je jezelf afvragen. Dat is exact wat "theprimeagen" ook dacht en ging zijn eigen clean code versie maken.

https://www.youtube.com/watch?v=PHvbLmLPX6s

... die uiteindelijk factoren langzamer bleek te zijn. Het blijft Javascript he... iemand anders kan het waarschijnlijk daadwerkelijk beter want ze nemen de moeite om zelfs de meeste nietige functies javascript-onlogisch te maken zodat we met zijn allen kunnen blijven geloven dat Javascript net zo snel is als andere talen en platformen. Ja dat kan. Maar niet zonder pijn.
Er zijn al een tijdje `padStart()` en `padEnd()` methods in de standard library die dit oplossen. Maar voor de langste tijd was de standard library van JavaScript/browsers zo klein dat je voor heel veel zaken niet anders kon dan een NPM library erbij pakken.
Mwah, leftPad was een aardig simpele functie die zo'n beetje elke programmeur toch wel zelf had moeten kunnen schrijven, en het is niet alsof er enige speciale compatibiliteit of snelheid werd behaald met speciale implementatie hier. Dat geldt ook wel voor meer projecten (isEven/isOdd zie je ook veel voorbij komen bijvoorbeeld).

Ik denk eerder dat dit het resultaat is van een mindset die een een paar jaar terug heel populair was in de Javascriptwereld, namelijk de voorkeur geven aan vele kleine pakketten boven zelfgeschreven functies die je moet gaan bijhouden. Dat heeft voordelen (als een browser wat geks doet wordt dit centraal opgelost) maar ook veel nadelen (security, gigantische dependency chains die tree shaking moeilijker maken, je bedrijf afhankelijk maken van een stel hobbyprogrammeurs). Ik denk alleen dat voor leftPad weinig projecten die nadelen doorhadden of erkenden.
Een tegenpool daarvan is de Go programmeertaal, die heeft aan de ene kant een zeer complete standard library (met ook left pad), aan de andere kant een cultuur en een gezegde: "A little copying is better than a little dependency".

Daar zijn natuurlijk veel voors- en tegens bij; voor is dat je minder imports en externe afhankelijkheden hebt van repositories van derde partijen (zoals left-pad), wat goed is want Go is bedoeld voor lange-termijnprojecten. Een ander ding om in de gaten te houden zijn de licenties; nu is het bij JS projecten vaak MIT, maar niet altijd.

Maar de tegens zijn dingen als: Not Invented Here, suboptimale implementaties, of wat als er een bug in zit? Er is wel een goed artikel van degene die een stukje code op Stackoverflow gepost heeft dat sindsdien duizenden keren overgenomen is, maar er zit een bug in: https://programming.guide/worlds-most-copied-so-snippet.html
Ik ben al jaren aan het strijden tegen het ruchtsichloss kopieren van code snippets van StackOverflow. Ik ben zelf vooral bezig met security, en het probleem is daar dat methodes uitstekend werken. Dat klinkt vreemd, maar het probleem is dat functionaliteit niet het doel is bij security. Iets kan volledig functioneel maar niet secure zijn. En hierbij heb ik ook posts gehad met 1000 upvotes die prima werken. Gelukkig heb ik de auteur toen zo ver gekregen om het antwoord aan te passen.

Zo waren er ook vragen en antwoorden die een random nummer generator gebruikten om een wachtwoord om te zetten naar een sleutel, om dat dan weer te gebruiken om data te versleutelen. Da's erg grappig als de werking van de random nummer generator niet is vastgelegd. Krijg je mensen die daadwerkelijk een random genereerde die niet alleen van het wachtwoord uitging maar ook van de secure random generator van het systeem. Voordeel is dat de het bericht nog steeds goed versleuteld is. Alleen jammer dat het nooit meer ontsleuteld kan worden...
> en het is niet alsof er enige speciale compatibiliteit of snelheid werd behaald met speciale implementatie hier.

Er zijn wel degelijk snellere en minder snelle implementaties van string manipulatie die eenvoudig performance issues zouden kunnen opleveren als het vaak genoeg aangeroepen wordt in een tight loop. Maar ja, ben het helemaal eens dat left-pad een beetje te ver gaat.
Zeker, en soms kan het nuttig zijn die te pakken (alhoewel je je afvraagt of het niet beter is die in je code op te nemen zodat je geen dependency hell hebt?), maar bij specifiek dit pakket, en eerlijk gezegd de meeste kleine pakketten uit die tijd, was de implementatie gewoon naïef.

Tegenwoordig zijn er vast pakketten als leftPad, maar dan in de vorm van polyfills voor oude browsers die geen padStart ondersteunen.
Libraries zijn inderdaad te vaak en veel gebruikt. Naar mijn mening levert dit nog grote potentiële beveiliging issues op ook omdat men gewoon geen idee heeft wat er in een black box zit.
Naast de bloat die het oplevert.

Wel makkelijk om snel een probleem op te lossen. Ff een libje ertegenaan gooien.

Edit log4j was een mooi voorbeeld.

Maar eerlijk is eerlijk, soms kunnen ze juist veiliger zijn omdat het weer beter onderhouden wordt dan een grote brei aan eigen code. Tja.

[Reactie gewijzigd door Triblade_8472 op 25 juli 2024 05:21]

Je hebt ook veel open-source libraries. Helaas is dat ook niet echt altijd fijn. Ik heb het vaak genoeg gezien dat ik dacht "hé, dat is een goede library voor mijn use-case, oh, laatste update was 6 jaar geleden..." Dat het geen updates heeft gehad hoeft niet perse slecht te zijn, maar het geeft wel aan dat (security) updates in de taal/framework niet meegenomen zijn.
Log4j en left-pad enzo waren ook open source; dat zijn geen garanties voor de toekomst helaas. Wat je aangeeft, libraries die niet meer onderhouden worden zijn echt erg. En in theorie kun je ze gewoon forken, of in theorie heeft iemand anders ze geforked, maar in de praktijk wil je het niet zelf omdat het een apart specialisme is (zoals logging, grafieken tekenen, strings padden etc), omdat het qua code style en dergelijke heel anders is dan wat je gewend bent, en die andere die het geforked heeft, doet vaak maar 1 wijziging, niet een overname / doorontwikkeling. Enkele uitzonderingen daargelaten, zoals de fork van node.js naar io.js dat vervolgens weer teruggebracht werd.
Wat ik nog het grappigst vind is dat kik uiteindelijk niks van de package heeft gedaan.
readme:
"This package contained malicious code and was removed from the registry by the npm security team"
Collaborators:kik
https://www.npmjs.com/package/kik
Een vraag als leek:
Hoe houd je als ontwikkelaar in godsnaam het overzicht met deze spaghetti aan dependency ketens? Ook als daar iets in wijzigt, maar de versies dan niet met elkaar compatibel zijn of 12 dependencies terug bijv een beveiligingslek ergens zit?
Bij ons team wordt dit automatisch bijgehouden door een bot die die hele keten checkt. Zodra er in die keten iets zit met wat niet meer wordt ondersteund of er een kritiek CVE-beveiligingsissue is, kunnen we de applicatie op een gegeven moment zelfs niet meer builden en moeten we dit oplossen.

Voor niet-kritieke zaken (zoals dat er wel een nieuwe major-versie is maar de oude nog wel ondersteund wordt) voeren we periodiek onderhoud uit waarbij we een commando doen zoals 'update alles' (wat ook grotendeels geautomatiseerd gaat) en kijken wat er dan reparatiewerk nodig heeft omdat sommige zaken niet meer werken. Daar heb je ook je automatische tests voor om te kijken of alles nog werkt zoals het oorspronkelijk bedoeld is.
Yup, die gaan wij dit jaar ook inbouwen: https://github.com/tinglesoftware/dependabot-azure-devops

[Reactie gewijzigd door Falcon op 25 juli 2024 05:21]

Als je niet op GitHub zit en je wil je dependencies up-to-date houden kan ik je Renovate aanraden, veel meer vendor agnostisch en ondersteunt ook meer package managers en is eenvoudiger te customizen.
Zal het meenemen! :)
Heb ik ook goede ervaringen mee. Zowel op GitHub als op Azure DevOps.

Dependabot is wat bekender, maar gaat (voor mijn gevoed) wel steeds meer achter lopen in ondersteunde ecosystemen...
Voor niet-kritieke zaken (zoals dat er wel een nieuwe major-versie is maar de oude nog wel ondersteund wordt) voeren we periodiek onderhoud uit waarbij we een commando doen zoals 'update alles' (wat ook grotendeels geautomatiseerd gaat) en kijken wat er dan reparatiewerk nodig heeft omdat sommige zaken niet meer werken. Daar heb je ook je automatische tests voor om te kijken of alles nog werkt zoals het oorspronkelijk bedoeld is.
Dit stukje, wordt door de meeste bedrijven niet gedaan en dat kan ik weten als ontwikkelaar. Die zeggen gewoon: fck it en hebben lak en schijt eraan, totdat alles misgaat of dingen kapot gaan en dan pas lossen ze dingen op en omdat er zoveel tech debt is ontstaan moeten ze dat ook nog pleisteren omdat ze hun framework of dergelijke nooit geupdate en geupgrade hebben lopen ze dan meerdere versies achter en moeten ze dan alles backporten ipv alles netjes te upgraden en er tijd en geld in te steken om het in 1 keer goed te doen maken ze een kaartenhuis en pleisteren ze alles bij elkaar 😂
In mijn werk als product owner vecht ik hier ook regelmatig tegen om hier tijd en ruimte voor te claimen in plaats van nieuwe projecten alsmaar voorrang te laten krijgen. Gelukkig heb ik dat mandaat, als ik maar iedereen zoveel mogelijk tevreden houd in het proces.
Dan werk je in een goed bedrijf of een software bedrijf. Mooi, en hopen maar dat dat nooit veranderd.
Dit herken ik wel, zelf heb ik ook een tijdje de rol van product owner op mij genomen. Ooit eens het gevaar van technical debt uitgelegd aan de hand van een jenga-toren.

De onderste blokjes van de toren representeerde allerlei "saaie" zaken als frameworks etc., de blokjes daarboven wat "leuke" nieuwe features.

Er was nogal wat technical debt, dus ik had er alvast wat blokjes uit getrokken aan de onderkant.

De collega die deze uitleg goed kon gebruiken mocht zelf nog wat "featureblokjes" uit de toren trekken.

Vrijwel onmogelijk, de toren stond op instorten. Nou, dat stond onze toren dus ook.

De boodschap kwam over. Eerst een solide basis opzetten en dan pas doorbouwen/aan andere blokjes trekken. (Oplossen van) technical debt werd prio 1 en daarna kwamen de features.

100% zuiver is de analogie niet. Maar met name bij collega's zonder technische achtergrond helpt 't wel bij de beeldvorming is mijn ervaring :).
En zo hoort het ook. Als je verantwoordelijk met het bouwen van je software omgaat.
Zodra je die discipline eenmaal hebt, is er eigenlijk weinig meer aan de hand.

Het grootste probleem is wanneer sales en management dwars gaan liggen omdat patches en version updates geen nieuwe features zijn en dus geen facturabele waarde representeren. Of wanneer ze zoveel werk aannemen en door de strot van een ontwikkelteam proberen te frotten dat je van feature deadline naar feature deadline moet rennen en effectief geen tijd meer hebt om zaken op orde te houden.

[Reactie gewijzigd door R4gnax op 25 juli 2024 05:21]

Daarom kan je beter op abonnementsvorm werken en een dienst aanbieden. Dit is veel beter dan versies en upgrades verkopen. Voor beide bedrijven trouwens en het is een eerlijkere relatie. Software is nooit af.
Door NPM niet te gebruiken. Het is duidelijk dat het te snel verzonnen is zonder na te denken over het ontwerp en de implementatie en vervolgens overal omheen te hacken ipv. te besluiten het een keer goed te doen. Het is niet alsof NPM de eerste uitvinder van een dergelijk dependency management systeem is. Alleen hoe NPM er mee omgegaan is heeft een vrij hoog hobby gehalte.
Het probleemstuk wat basdej schetst houd je natuurlijk net zo goed met een Composer, Maven, Gradle, Pip you name it. Feit is dat men steeds meer leunt op andermans lego-blokken, zonder die te kennen. Dat biedt een hoge ontwikkelsnelheid, maar komt inderdaad met risico's.
Het wissen van oude deps (wat gewoon een denkfout is) ligt hier aan ten grondslag. Maar een tweede probleem is inderdaad het grote copy-paste programmeren zonder te weten wat je precies doet. Dat was al een issue met stackoverflow code snippets, maar libraries worden ook blind toegevoegd. Vandaar ook: geen NPM gebruiken en zelf nadenken en specifieke libraries inzetten. Zeker als je iets maakt wat je over 2 jaar nog wil gebruiken.
Het concept op zichzelf is niet verkeerd, maar de implementaties schieten nog tekort en ook is er nooit nagedacht over wat te doen als de onderliggende technologie verandert. Javascript en Node stonden er ± 10 jaar geleden heel anders voor dan nu. Daar is echt veel in veranderd.

Door vele API-wijzigingen en het wijzigingen van inladen van modules moest je de afgelopen jaren soms meerdere keren een project opnieuw opbouwen of blijven werken met verouderde modules en oude Node versie. Als ik kijk naar PHP+Composer gaat dat veel gelijkmatiger, maar dat komt ook doordat PHP al heel wat volwassener was 10 jaar geleden dan Node toen was, terwijl Node vanaf het begin wel direct door velen gebruikt werd (en NPM onmisbaar werd).

De implementaties laten ook wel vaak te wensen over. Zo zijn er diverse packages die slechts enkele kleine functies bevatten, maar voor sommige van die kleine functies ook weer een ander package nodig hebben. Een UUIDv4 genereren zonder poespas kan in een regel of 20, maar velen gebruiken toch liever een ander package daarvoor. Dat veroorzaakt al snel een Dependency hell. Heb hier net een vrij simpel project voor m'n neus waar we 13 packages willen gebruiken, maar waarbij uiteindelijk 1103 packages in de package-lock.json staan, dat is > 84 packages per requirement. Ter vergelijking, composer gaat in datzelfde project van ook 13 requirement naar 38 packages.
10 jaar geleden bestond ook composer nog maar net en zat heel PHP nog gewoon scripts over te kopiëren en die dan met include in te laden. Ik sluit niet uit dat dat nog steeds op veel plekken op die manier wordt gedaan. NPM kwam relatief snel nadat serverside JavaScript geïntroduceerd werd, terwijl bij PHP er heel lang wat losse initiatieven waren (zoals PEAR) en nu na een tijd Composer wel de default is geworden.
npm i tooltje

INCOMING !
Automated tooling en een database aan vulnerabilities.
De NPM client heeft hiervoor een audit commando ingebouwd zitten.
Klinkt goed, maar is voor echt security wel dweilen met de kraan open.

Die aanpak kan maar werken als ten eerste iemand de vulnerabililty opmerkt en gerapporteerd krijgt. Voor grote open source projecten zoals een belangrijke Linux distro, lukt dat wel omdat er veel mensen naar kijken. Maar voor een typische npm dependency tree kom je in zoveel packages terecht waar zelfden een mens nog naar kijkt.

En dan moet men ook nog de procedures hebben om constant elke dag te gaan checken of er een kwetsbaarheid gevonden is en die te gaan aanpakken. Voor dingen als besturingssystemen en grote applicaties zoals browsers enzo is dat nog goed geregeld met patches en vaak auto updates.

Maar voor een typische Angular webapp is het in de praktijk meestal bouwen voor een klant en na oplevering is er niemand die er naar zou kunnen kijken. En dan heb je binnen het wereldje ook nog eens de neiging om altijd iets nieuws te willen proberen waardoor er nog meer random packages met exotische trees erbij gezwierd worden.
Maar voor een typische Angular webapp is het in de praktijk meestal bouwen voor een klant en na oplevering is er niemand die er naar zou kunnen kijken.
Het build-once;maintain-never probleem heb je net zo goed met traditionele applicaties die maar van een paar third-party dependencies gebruik maken. Dat is een non-argument en is meer een issue met bedrijfsprocessen dan een issue met de techniek.

Dat heb je zelfs met websites die nog actief in maintenance zijn. Zelfs met hele grote partijen die beter zouden moeten weten.

Ga bijv. maar eens naar https://store.steampowered.com , open daar de F12 dev tools en tik in de console in jQuery.fn.jquery. Versie 1.8.3 - stokoud en minstens 6 bekende vulnerabilities, zie bijv. https://security.snyk.io/package/npm/jquery/1.8.3

[Reactie gewijzigd door R4gnax op 25 juli 2024 05:21]

Het pakketje heeft vulnerabilities, maar die komen alleen een probleem als je het pakketje op een zéér specifieke manier aanstuurt.

Daaromheen kan je nog wat extra maatregelen treffen, zoals de content-security-policy header instellen. Op het moment dat je het pakketje dan toch op de verkeerde manier gebruikt, houdt de csp-header de geinjecteerde scripts tegen.

Dat gezegd hebbende, deprecated en vulnerable packages kan je maar beter gewoon updaten.
Het pakketje heeft vulnerabilities, maar die komen alleen een probleem als je het pakketje op een zéér specifieke manier aanstuurt.
Enkele maanden geleden nog was er in de Steam beta forums iemand die een post geschreven had dat ze privaat met Valve contact op hadden genomen omdat het mogelijk bleek JavaScript te injecteren op gebruikersprofielpagina's van Steam. (Iets wat meermalen in het verleden ook al mogelijk is gebleken.)

Dat zou dus zomaar gerelateerd kunnen zijn.

[Reactie gewijzigd door R4gnax op 25 juli 2024 05:21]

De reden dat ik niet zomaar allerlei packages toevoeg aan mijn projecten.

Kan je het makkelijk zelf schrijven is dat gewoon veel makkelijker dan met dependency hell omgaan. Zeker met een ecosysteem zoals npm.

Helaas genoeg projecten gezien waar men van alles toevoegd zonder te kijken naar de echte meerwaarde. Vaak bleek het uiteindelijk om een enkel klein stukje functionaliteit te gaan wat je makkelijk zelf kon maken.
Ja, en dan krijgen mensen zoals jij en ik het verwijt het wiel opnieuw uit te vinden. Voor een Object.keys() heb ik geen lowdash nodig :+
Het simpele antwoord is natuurlijk _niet_.
Dat is ook het grote probleem van NPM, als je ziet hoe het een ander is georganiseerd dan vraag je je af hoe ze een dergelijk systeem zo hadden kunnen bedenken. Van packages die bij niets doen, tot packages zoals als deze die zeer veel importeren.

Elke package heeft weer zijn eigen dependencies en en ga zo maar door..

Een simpele 'Hello World' met een paar devDepenencies + wat frameworks... boom 225MB. Warrom we in hemelaas naam packages nodig hebben zoals:
- Tiny millisecond conversion utility
- Recursively mkdir, like `mkdir -p
- Run a function exactly one time
- Run multiple promise-returning & async functions with limited concurrency

en ga zo maar door... gaat mij helemaal voorbij, NPM is en zal altijd een zooitje blijven....

Een van de vele redenen waarom javascript zoveel haters als 'lovers' heeft. Het is ook niet zo zeer javascript zelf, die vol met raarheden zit, maar meer de build tools en frameworks die niet volwassen zijn.
Extra leuk als je zoals ik in de cryptografie zit. Allemaal libs die een vreselijke slecht beschreven API hebben en vanalles onder water doen. Veel 1 persoonsprojecten enzo. En dan moet ik kijken of het secuur is. Nou, nee dus, of in ieder geval is dat onwaarschijnlijk. Het werkt vaak wel maar een security review ofzo kan je wel vergeten. En "it works" zegt helemaal niets over de veiligheid.

Dat geld overigens ook voor andere talen, maar de scripting talen maken er wel echt een zootje van.
Ook als daar iets in wijzigt, maar de versies dan niet met elkaar compatibel zijn
Dit wordt opgelost door een afwijkende versie van een dependency dichter bij de package te plaatsen die deze versie opvraagt. Dankzij de manier waarop Node.js modules resolved kan deze dan eerder gevonden worden waardoor je twee verschillende versies van een dependency kan hebben.

Stel je voor dat ik een project heb met een dependency op package 'a', daar wil ik versie 2.0.0 van, ik heb ook een dependency op 'b' (de versie van 'b' is hier even niet belangrijk).
{
"name": "my-app",
"dependencies": {
"a": "2.0.0",
"b": "*"
}
}
Maar hier komt de crux, 'b' heeft zelf ook een dependency op 'a', maar een oudere versie:
{
"name": "b",
"dependencies": {
"a": "1.0.0"
}
}
De dependency chain is dus:
- my-app ➡️ 'a' (v2.0.0)
- my-app ➡️ 'b' ➡️ 'a' (v1.0.0)

Als je 'npm install' draait, zal deze de volgende structuur opbouwen in de 'node_modules' directory:
node_modules
├─ a (v2.0.0)
├─ b
│ ├─ node_modules
│ │ ├─ a (v1.0.0)
Hier is te zien dat 'b' zijn eigen 'node_modules' directory heeft, met de oudere versie van 'a', waardoor deze beide naast elkaar gebruikt kunnen worden.
of 12 dependencies terug bijv een beveiligingslek ergens zit?
Hier is npm audit voor, en dit draait standaard op elke npm install.
Hier is npm audit voor, en dit draait standaard op elke npm install.
Waarbij wel even de kanttekening geplaatst moet worden dat `npm audit` enkel werkt als je een registry gebruikt die deze danwel door kan lussen (zoals ProGet met een uitgaande internetverbinding, of Verdaccio met de juiste plugins), danwel zelf ondersteund (direct lijntje naar NPM); en dat is niet in alle omgevingen mogelijk.

Er is (nog) geen mogelijkheid om de audit database offline te gebruiken, of te laten clonen/cachen door bijv. ProGet of Verdaccio, wat deze functionaliteit onbruikbaar maakt als je in een afgeschermde of offline omgeving werkt.
Eigenlijk... niet. Bij je eigen project kun je nog bijhouden dat je bijvoorbeeld niet twee libraries gebruikt die hetzelfde probleem oplossen, maar daarbuiten gaat heel veel op goed vertrouwen. En NPM packages updaten is vaak een drama, precies vanwege die compatibiliteit met elkaar; in theorie houden alle packages netjes semantic versioning aan zodat een 1.x versie altijd backwards compatible blijft, maar in de praktijk valt er regelmatig veel om. In mijn huidige project gebruiken we NX en wat voorgebouwde project-setups; in plaats van zelf NPM dependencies bij te werken vragen we aan NX om het te doen, die zal dan zelf de dependencies die de mensen erachter gecontroleerd hebben op onderlinge compatibiliteit bijwerken en eventuele code- of configuratiewijzigingen doorvoeren.

Qua security en beveiligingslekken, het is niet te doen om dat zelf bij te houden. in Node land heb je tegenwoordig npm audit, een commando die al je dependencies (en hun dependencies) vergelijkt met een lijst van bekende security issues. Je hebt ook 3e partijen zoals Snyk, en Github doet ook aan het scannen van je dependencies.
Snyk is behoorlijk waardeloos als betaalde dienst. Ondersteunt niet eens alle populaire package managers voor Node.js
Volgens mij niet.
Het is daarnaast een nachtmerrie om te bepalen welke license je software onder valt.
Zit gewoon een 'license' veld in bijna elk pakket op NPM hoor.
Ja, maar die wordt niet altijd gebruikt ipv. hebben ze soms een LICENSE/LICENCE bestand. Daarom heb je soms ook die 'unknown's in license scanners
Ja, dan kan je er voor kiezen om die dependencies niet te gebruiken. Of je schiet even een PR in om dat te fixen :)
Tot nu toe was het makkelijker om PR te maken voor de license scanner :)
Het is daarnaast een nachtmerrie om te bepalen welke license je software onder valt.
Eigenlijk niet echt.

Vuistregel is dat als ieder package zich correct aan licentievoorwaarden van haar dependencies houdt, jij alleen je te houden aan de licentievoorwaarden voor de packages die je direct als top-level dependency opneemt. Diepere dependencies hebben licentievoorwaarden waar jouw top-level dependencies zich dan weer aan moet houden; etc.

Zo kun je bijv. niet te maken hebben met een package dat een 'do whatever' licentie heeft zoals het MIT license, wat een dependency met een copy-left licentie heeft zoals de GPL licenses. Dat zou alleen kunnen in situaties waar zulke copy-left licenties bijv. een clausule hebben die zulk gebruik toestaan waar het gelicenseerde werk niet statisch maar dynamic gelinkt wordt. Dat laatste is binnen Node.js altijd het geval, maar dan zit automatisch transitief jouw top-level eigen software project ook goed. Want dynamisch gelinkt.

Alleen als je te maken hebt met een partij ergens in die boom die licentie-technisch haar zaakjes niet op orde is, zou je problemen kunnen krijgen. Vraag is dan wel wie er op zo'n moment schuldig geacht wordt aan licentie-overtredingen.

[Reactie gewijzigd door R4gnax op 25 juli 2024 05:21]

Het is daarnaast een nachtmerrie om te bepalen welke license je software onder valt.
Daar heb je weer een package voor ;)

https://www.npmjs.com/package/license-report
Ik wilde net gaan schrijven dat ik er eigenlijk wel klaar mee ben met dit werk vanwege precies deze ellende (tijd voor een andere baan). Maar het is een beetje een baan op zich aan het worden. Er zijn wel tools die inzicht geven in CVE's in je dependency tree. Het oplossen is in veel gevallen een bump naar een hogere versie, die github soms zelf automatisch kan oplossen voor je. In andere gevallen dien je een goede set aan testen te hebben die automatisch de regressie bewijzen.

edit: in onze worflow draait er een dagelijkse check op CVE's voor al onze dependencies (maven) en lossen we dagelijks (in de ochtend) deze issues op.

zie ook bijv. https://docs.github.com/e...t/working-with-dependabot

[Reactie gewijzigd door Keyb op 25 juli 2024 05:21]

Sbom zijn een oplossing. Maar feitelijk, je zou moeten limiteren tot zo min mogelijk packages, en zeker heel goed moeten nadenken over dependencies die zelf ook weer dependencies bevatten.
Immers, volgens de NIS2 en CRA wetgeving die er aan komt bij jij uiteindelijk als bestuurder aansprakelijk voor als er ergens iets mis gaat.
Niet echt, als je wilt kan je wel een overzicht krijgen maar niemand die dat gaat fixen denk ik. Dus wordt het zo verscheept. :) Ik ben net begonnen met beetje van het web development te proeven en ik schrok me een ongeluk wat dependencies en frameworks betreft. Ik vind het zo backwards allemaal als je het vergelijkt met de oudere talen en oude manier van desktop development etc.
Mits het uitkomt met licenties kan je de door jou geteste versie ook in je eigen software integreren als soort van module.

Binnen packagemanagers kan je ook een specifieke versie laten installeren, het hoeft niet automatisch de meest nieuwe te zijn.

Beveiligingslekken zijn wel altijd een risico en een goede reden om niet zomaar overal dependencies te hebben.
Realistisch gezien alleen maar door externe dependencies zo veel mogelijk te beperken en alleen gebruik te maken van packages van zeer betrouwbare partijen.
Tools die het voor je automatiseren, zoals dependabot of renovatebot.

Daarnaast statische analyse van je code, zodat die bijvoorbeeld een error geeft als een van je bots een dependency probeert te updaten die veranderd is waardoor de manier zoals jij het nu gebruikt niet meer werkt. Stel dat jij een dependency gebruikt om getallen op te tellen en die functie heet 'add(..)' maar de dependency veranderd die functie naar 'addition(..)', dan kun je met statische analyse al zien dat jouw code niet meer gaat werken en je het dus moet aanpassen of op een andere manier moet oplossen.

Vervolgens unit/integration/e2e/fuzzy testing zodat je zeker weet dat jouw code met die nieuwe dependency nog werkt.

Als alles slaagt dan kun je die dependency updaten. Maar er kan in de hele keten ook nog een beveiligingslek zitten waar nog geen update voor beschikbaar is, daar heb je dan weer tools voor zoals Snyk die je daarop kunnen wijzen. En dan kun je een afweging maken om die dependency te vervangen of dat lek te negeren (bijvoorbeeld omdat je de lekke code niet gebruikt) of er omheen te werken.
Een goede ontwikkelaar zou niet zomaar packages toevoegen die niet echt nodig zijn. Wees kritisch in je verbruik, en hou het goed bij in je versiebeheer. Zo was er laatst toch een probleem met een of andere package voor de meest simpele functie (lowercase of zo?) die in frameworks zat en voor allerlei problemen veroorzaakte. Gebruik alleen belangrijke en essentiële packages en maak hierin goed overwogen keuzes.
Zo wil je niet je eigen encryptie code schrijven bijvoorbeeld :+
Als je gewoon alles maar gebruikt is dat lastig. Eerste regel is dus om selectief te zijn in wat je gebruikt. Wanneer je gebruik maakt van open source moet je ook putten uit de krachten van open source.

Voorbeelden gerelateerd aan jouw vraag zijn:
- Check dat een package actief maintained is.
- Check het aantal maintainers (als het er maar 1 is, en die stopt…..)
- Check de populariteit van de package
- check eventueel betrouwbare namen die eraan zijn verbonden

Als je een actief maintained package gebruikt waarvan ook veel mensen gebruik maken dan is er dus ook een grotere kans dat deze package veilig blijft. (Afgaand op statistiek, uitzonderingen daargelaten).

Verder kan je wat best practices toepassen zoals:
- zorgen dat je altijd op recente versies van derde partij code zit
- een security scanner in je CI inbouwen die een library met vulnerable packages vergelijkt met de door jou gebruikte packages en versies
- een license scanner die checkt dat er alleen licenses die jij toestaat gebruikt kunnen worden

Een hele belangrijke in de open source wereld is ook het principe van geven en nemen.
Als je iets gebruikt, doe dan ook de moeite om iets terug te doen dmv contributions op die packages (ja, binnen werktijd, looking at you werkgevers). Ofwel: zie je een vulnerability? Fix het zelf en deel het!

Kortom: je kan niet alles zelf doen, dat is het hele punt van open source. Dat geldt net zo voor de controle op open source…

[Reactie gewijzigd door Jaatoo op 25 juli 2024 05:21]

Niet.... Persoonlijk leid ik aan FOEF (Fear Of Every Framework) en ik doe ook niet aan always-online development.

Ik ben misschien van de oude stempel maar mijn meeste common libraries zijn zelf ontwikkeld en die groeien mee naarmate je meer ontwikkeld. I know... het warm water opnieuw uitvinden maar je bespaart heel wat miserie door afhankelijk te zijn van de kuren van andere dev's of erger nog bedrijven.

Als er toch iets is waar ik niet zelf aan begin (zoals een PDF en Excel generator) dan kies ik er het beste open source project uit, en kopieer ik die source lokaal in een apart gelinkt project zonder enig package management. Kan je ook meteen zonder gedoe step-into debuggen in de code van die library en eventueel aanpassen/uitbereiden naar je noden.

Het lijkt misschien een heel gedoe maar ik kan op elk moment met 100% zekerheid mijn projecten compileren zonder onzekerheden of internet-afhankelijkheid. Volledige controle over eigen code.

[Reactie gewijzigd door Jim80 op 25 juli 2024 05:21]

De term hacker lijkt me hier totaal niet op z'n plaats.
Als deze persoon dat bewust had gedaan wel.
Maar volgens mij word je niet automatisch een hacker omdat een geintje als een "hack" uitpakt.
Wel interessant om te zien dat er zo'n weeffout in het systeem zit dat nog nooit bewust is misbruikt.

[Reactie gewijzigd door rajackar op 25 juli 2024 05:21]

er zijn regels in het NPM syseem, iemand heeft ze gebruikt op een manier die niet de bedoeling was. Dat is zo ongeveer de kern van 'hacker' zijn.
Heb het even verduidelijkt. Het ging me meer om het feit dat het als een geintje werd gedaan en niet bewust om het systeem te ondermijnen.
De term hacker lijkt me hier totaal niet op z'n plaats.
De term 'hacker' refereert origineel aan iedereen die een stuk software op zo'n manier verhakselt dat het effectief voor iets anders ingezet kan worden dan origineel de bedoeling was.
Beveiligingen doorbreken of inbreken op computersystemen was origineel het domein van een 'cracker' - maar in de mainstream media zijn die twee hetzelfde gaan betekenen en wordt 'hacker' nu misbruikt waar er 'cracker' bedoeld wordt.

De originele betekenis van de term zie je o.a. nog terug in afgeleidde termen, zoals in 'life-hacks' - slimme tijd of ergenis besparende trucjes met alledaagse voorwerpen.
De term 'hacker' refereert origineel aan iedereen die een stuk software op zo'n manier verhakselt dat het effectief voor iets anders ingezet kan worden dan origineel de bedoeling was.
Het criterium daarvoor is wel dat het bewust gedaan moet worden. Iemand die per ongeluk een DoS doet omdat hij letterlijk per ongeluk iets op zijn F5-knop heeft laten liggen is nog geen hacker...
Totaal niet zelfs? Deze persoon maakt een stukje software om een fout in een systeem aan te tonen. Dat lijkt mij toch vrijwel perfect in de definitie "hacker" passen
Misschien moeten ze alles maar eens gaan verifiëren. Oh wacht, dat is nu een beetje onbegonnen werk met de hoeveelheid packages die ze hebben opgebouwd.
Ja want secure, want alles is opensource. Ik kan alles nalopen.
De community in general yes
Ja maar ik ook....
Do you ?
Soms

(dnf install thing .... 350mb deps)

Bro...

(Gesprek dat ik met een Junior had gisteren :)
Die naïviteit zie je overal. “Het is open source dus veilig want iedereen kan het auditen.” De realiteit is dat niemand (met voldoende verstand van zaken) die audits doet want goede ontwikkelaars steken die moeite liever in hun eigen projecten dan in het fixen van andermans code.
OpenSSL blijft voor mij hét voorbeeld hoe dat fout kan gaan. Het is één van de bekendste, belangrijkste en gevoeligste stukken OSS software, en je zou verwachten dat het audited-to-death was, maar die audits zijn pas gekomen nadat het kalf al verdronken was. Dan weet je wel hoe het zit met audits van andere complexe software.
Je zou natuurlijk kunnen beginnen met verifiëren van de populairste packages en vanaf daar verder werken. Dan kan iemand die iets bouwt aan tooling meegeven dat die enkel geverifieerde packages wilt gebruiken, en zo inzicht krijgen in waar die de kantjes ervan afloopt als die dat niet zou doen.
Omdat de everythingpackage dat wel deed, bleek het niet mogelijk te zijn om nog langer zelf packages te verwijderen. Ook kon de originele uploader de package daardoor niet langer verwijderen. Die moest daarvoor aankloppen bij npm en bij moederbedrijf GitHub, dat zegt het pakket te verwijderen.
Ik begrijp deze alinea niet. Wat deed de everything-package precies? Als ik het bronartikel begrijp, dan hadden de makers van deze package duizenden sub-packages, die op hun beurt weer alle dependencies includen. Betekent dit dan dat de auteurs van die laatste dependencies hun spul niet meer konden verwijderen, omdat er iemand was die van hun package gebruikmaakte, of lees ik het verkeerd? Voor zover ik begrijp, hebben de auteurs van de everything-package zichzelf niet gedepubliceerd (wat alleen kan als er niemand is die afhankelijk is van je package).
Op NPM kun je geen pakketten verwijderen als andere pakketten afhankelijk van je zijn.

Everything bevatte een boom van everything-subpakketten, en al die subpakketten hadden afhankelijkheden op echte pakketten.

Zoals de naam doet suggereren, was het zo opgezet dat als je everything in je dependencies zette, je ieder pakket op NPM in je dependency chain had staan.

Doordat nu ieder pakket op NPM een dependency had (namelijk zo'n subpakket van everything), kon niemand hun pakketten meer van NPM verwijderen.
Ik zie het wel voor me: een billboard in San Francisco met een zwarte achtergrond en witte text met “npm install everything”
Ik weet niet of het probleem vooraf al bekend was maar ik vind 't een mooie (amper) niet destructieve manier om een probleem aan te tonen.

Het zou nog grappiger zijn als vele mensen deze gaan gebruiken waardoor juist deze niet verwijderd kan worden.

Is het niet logischer om zaken 'verplicht' te clonen voor een verwijdering? Kan de ontwikkelaar het spul blijven gebruiken met een waarschuwing dat het origineel weg is en niet meer onderhouden word.
Zelf poog ik hierom node.js en consoorten te vermijden. Het is ietsje te slordig en te veel hocus-pocus en hopen dat 't werkt. Ik lees liever dat er meer aandacht gaat naar discipline een gehaat woord.
Goede actie. Altijd rete irritant als een npm package wordt verwijderd door de maker zodat je npm ci commando niet meer werkt.
Hmm, beetje ingewikkeld verhaal als ik dat zo lees want het was mij eerst niet duidelijk dat die hacker niet direct het probleem veroorzaakt heeft. Voor wat ik begrijp uit het artikel was het meer door een grap dan van een npm-contributor.

Op dit item kan niet meer gereageerd worden.