Du har sikkert sett det før: “101 vulnerabilities” etter installering av pakker med npm.
Du sukker stille for deg selv og tenker ikke noe mer over det. Tross alt så er det vel lite du kan gjøre med saken. Dependabot har allerede laget et PR i repoene til de rammede pakkene som npm advarer mot og de har blitt ignorert i flere måneder. Og hvor ille kan det da egentlig være?
Så du fortsetter med utviklingen din og glemmer advarselen...
Men hva om jeg fortalte deg at det finnes håp for pakker-som-igjen-bruker-utdaterte-pakker? 👀
npm audit 👮
Kilden til advarselen du ser øverst er npm audit som kjøres etter hver pakkeinstallasjon.
Denne funksjonaliteten i npm sjekker pakkeversjonene du installerer mot Github sin oversikt over kjente sikkerhetsfeil i pakker og advarer deg deretter. En relativt nyttig feature når man installerer pakker som er avhengig av pakker igjen, og avhengighetene dine vokser fort.
Dersom npm audit finner potensielle sårbarheter så får du forslag om å kjøre kommandoen npm audit fix. Da vil npm forsøke å oppgradere pakker som ikke berører eksisterende funksjonalitet ved å se på versjonering etter semantisk versjonering-spesifikasjonen 🔖.
Sånn hacker du uten å bryte loven: - Ikke lett å forstå for verken hacker eller bedrift
npm vil altså oppgradere alle pakker som kan oppgradere minor- eller patch-versions, det vil si pakker som ikke vil brekke eksisterende funksjonalitet du er avhengig av eller som vil gjøre at prosjektet ditt stopper å fungere som forventet. Har du derimot uflaks kreves det kanskje en major-versjon og det tør ikke npm audit fikse for deg automatisk.
“Men hva med npm audit fix --force? Da går jo masse advarsler bort?” 🤔
Dersom npm audit fix ikke løste advarselene dine, kan du forsøke deg på å slenge på flagget --force. Da vil npm installere påkrevde major-versjoner også for å løse sårbarhetene. Etter å ha kjørt en fiks med --force er det derfor nødvendig å sjekke hvorvidt applikasjonen din faktisk fortsatt fungerer. 🔬
Den store ulempen med --force er at da gjør npm alt den kan for å få bort sårbarheten, og installerer siste kjente pakkeversjon som den definerer som trygg. Ikke bare kan koden din brekke fordi du har fått ny funksjonalitet i pakker som ikke er bakoverkompatibel, men du kan også ha mistet masse funksjonalitet. Hvis du bruker force-flagget åpner du nemlig for at npm også kan nedgradere pakker dersom det er eneste måte å unngå sårbarheten. 😬
Hvor krise er det egentlig? 🤷
Dan Abramov har skrevet en god bloggpost om hvordan npm audit er “broken by design”.
Hovedpoenget han løfter frem er at npm audit ikke har noe forståelse av hvordan pakken faktisk brukes i ditt prosjekt. Dermed vil den melde fra om sikkerhetsfeil som ikke faktisk er noe man trenger å bruke tid på å fikse, ettersom det bare er false-positives.
Et eksempel er byggverktøy som create-react-app, hvor det rapporteres om sårbarheter tilknyttet usanitert brukerinput. Dette høres jo svært alvorlig ut. Det eneste er at sårbarheten ligger i en pakke som kun blir brukt til bundling av kode, og aldri er eksponert for brukere.
Likevel trenger vi å varsles om potensielle sårbarheter. Et prosjekt med 19 avhengigheter definert i package.json kan fort ha 900 (!) avhengigheter i node_modules på grunn av nøstede avhengigheter.
Å manuelt sjekke 900 avhengigheter for sikkerhetsfeil er ikke saklig å forvente. Dette fremhever kanskje et større problem med hvordan vi ukritisk bruker pakker, men det er en annen diskusjon. Hva kan vi gjøre med verktøyene vi har her og nå? 💡
- Jeg tar open source-utviklerne for gitt. Og jeg må skjerpe meg
Redningen 🎉
Hvis det finnes versjoner av pakker som dine avhengigheter igjen er avhengig av er det håp, selv om npm audit fix --force brakk hele applikasjonen.
9. desember 2021 ble det i nogenlunde stillhet releaset en ny minor versjon av npm; v8.3.0. Her lå det så fint under "features": "introduces overrides, og under "documentation": "documents overrides".
Overrides er en ny funksjonalitet i npm som leser seksjonen av din package.json ved navn “overrides”. Her kan du låse minimumsversjoner av pakker uansett hvor de skulle befinne seg i dependency-treet ditt. 🔐
Overrides gir oss dermed muligheten til å luke ut hvilke alle sårbarheter vi kan oppgradere uten å brekke alt! 💪
Trikset er så enkelt som å kjøre npm audit, følge lenken til sårbarheten på Github hvor det står hvilken versjon som har en fiks og legge til denne versjonen i “overrides”-feltet. Gjerne med en "≥" foran, slik at du fremdeles vil kunne få bakoverkompatible oppdateringer. Deretter kan du kjøre en npm install og forsøke starte applikasjonen din.
Slik kan du luke ut én etter én rapportert feil til du har tettet alle du kan. Dette er fortsatt en manuell prosess, og kan ikke tette alle de potensielle sårbarhetene (da hadde det jo vært løst med --fix), men med dette er man ikke lenger dømt til å akseptere perioder med sikkerhetsfeil i en pakkes avhengigheter, hvis pakken ikke oppdateres fort nok.
Kos deg med færre advarsler fremover!