Uppgradera transitiva beroenden med PNPM: Åtgärda säkerhetsbrister utan att bryta saker
Att åtgärda säkerhetsbrister kan vara en frustrerande uppgift, särskilt när det handlar om transitiva beroenden. Lär dig hur du uppgraderar dem utan att påverka dina direkta beroenden.
Nuförtiden är säkerhetsbrister ett vanligt problem inom mjukvaruutveckling. Lyckligtvis har vi verktyg som GitHub Dependabot för att hjälpa oss hålla våra beroenden uppdaterade med automatiserad detektering och pull-begäranden.
Dock, det fungerar inte alltid som förväntat. Eftersom vissa beroenden är transitiva, kan det vara en svår uppgift för dessa verktyg att uppgradera dem eftersom de inte vet vilken påverkan förändringarna har och vad de ska besluta i konfliktsituationer. Vi behöver hantera dessa fall manuellt.
Metoder som inte fungerar
- Officiella kommandon som
pnpm up
kommer att röra till dinpnpm-lock.yaml
-fil. Det finns ett problem om detta som fortfarande är öppet vid tidpunkten för skrivandet. - Att installera den senaste versionen av det direkta beroendet som har det önskade transitiva beroendet kanske inte fungerar. Om det direkta beroendet inte uppgraderade versionsdefinitionerna kommer det transitiva beroendet inte att uppgraderas eftersom det har blivit löst och låst i
pnpm-lock.yaml
-filen.
Lösningen
Fältet overrides
är en kraftfull funktion i PNPM som låter dig åsidosätta vissa versionslösningar. Vi kommer att använda den här funktionen för att uppgradera transitiva beroenden och göra förändringen så minimal som möjligt.
Låt oss använda ovanstående Dependabot-varning som ett exempel. Den berättar att paketet follow-redirects
har en säkerhetsbrist och den åtgärdade versionen är 1.15.6
. Men det direkta beroendet gatsby
använder axios
som beror på [email protected]
.
Steg 1: Hitta det transitiva beroendet
Det finns många sätt att hitta det transitiva beroendet, men jag skulle rekommendera det mest enkla sättet: sök i pnpm-lock.yaml
-filen.
Hur är det med "pnpm why"?
Kommandot pnpm why <package>
är verkligen användbart. Dock, det kan förvirra dig i det här fallet. Till exempel, när jag kör pnpm why follow-redirects
, här är en del av utmatningen:
Egentligen finns det bara en lösning för follow-redirects
i pnpm-lock.yaml
. Kommandot pnpm why
kan visa dig flera vägar som beror på samma version av paketet.
Steg 2: Lägg till åsidosättningarna
Det lättaste fallet är att endast en lösning finns i pnpm-lock.yaml
-filen. Du kan lägga till åsidosättningen direkt till package.json
-filen:
Om du är i en arbetsyta, bör du lägga till åsidosättningen till arbetsytans rot package.json
-fil.
Steg 3: Tillämpa ändringarna
Kör pnpm install
för att tillämpa ändringarna. Vi kan se att paketet follow-redirects
är uppgraderat till 1.15.6
i pnpm-lock.yaml
-filen med minimala ändringar.
Nu kan du ta bort overrides
-fältet från package.json
-filen för att hålla det rent. Kör sedan pnpm install
igen för att validera att ändringarna kan tillämpas utan overrides
-fältet.
Felsökning
Ovanstående steg är det ideala fallet. Saker kanske inte alltid går som förväntat. Här är några tips för felsökning:
Versionen återställs efter att "overrides"-fältet har tagits bort
Detta kan hända när det beroende paketet har en fast version eller ett intervall som inte inkluderar den önskade versionen. Kontrollera package.json
-filen för det beroende paketet, i det här fallet axios
, för att se om detta gäller.
Om så är fallet, behöver du behålla overrides
-fältet i package.json
-filen tills det beroende paketet uppgraderar versionsdefinitionerna.
Det finns flera lösningar för det transitiva beroendet
När projektet växer, kan pnpm-lock.yaml
-filen flöda med flera lösningar för samma paket. Till exempel kan det finnas två stora versioner av samma paket foo
:
Rapporten om säkerhetsbrister visar att [email protected]
har ett säkerhetsproblem som är åtgärdat i 1.0.1
, och [email protected]
är inte påverkad. Vi kunde inte bara lägga till en åsidosättning till foo
:
- Om vi lägger till en åsidosättning
"foo": "^1.0.1"
, kommer[email protected]
att nedgraderas till1.0.1
. Detta kan förstöra projektet eftersom[email protected]
kan ha några nya funktioner som används i de beroende paketen. - Om vi lägger till en åsidosättning
"foo": "^2.0.0"
, kommer[email protected]
att uppgraderas till2.0.0
. Detta kan förstöra projektet eftersom[email protected]
kan ha några brytande förändringar.
Förutsatt att foo
följer Semantic Versioning, kan vi lägga till en åsidosättning så här:
Detta kommer endast uppgradera [email protected]
till 1.0.1
och hålla [email protected]
oförändrad.
Slutsats
Innan PNPM stödjer uppgradering av transitiva beroenden direkt, är overrides
-fältet en bra lösning för att åtgärda säkerhetsbrister utan att bryta saker. Jag hoppas att den här artikeln hjälper dig att hantera dessa fall mer effektivt. På Logto använder vi denna metod för att hålla våra beroenden uppdaterade och säkra.