Aggiorna le dipendenze transitive con PNPM: Risolvi le vulnerabilità di sicurezza senza rompere nulla
Risolvere le vulnerabilità di sicurezza può essere un compito frustrante, soprattutto quando coinvolge dipendenze transitive. Scopri come aggiornarle senza impattare le tue dipendenze dirette.
Oggigiorno, le vulnerabilità di sicurezza sono un problema comune nello sviluppo software. Fortunatamente, abbiamo strumenti come GitHub Dependabot per aiutarci a mantenere le nostre dipendenze aggiornate con rilevamento automatico e pull request.
Tuttavia, non sempre funziona come previsto. Poiché alcune dipendenze sono transitive, aggiornarle può essere un compito difficile per questi strumenti poiché non sanno l'impatto degli aggiornamenti e quale decisione prendere in caso di conflitti. Dobbiamo gestire questi casi manualmente.
Metodi che non funzionano
- Comandi ufficiali come
pnpm up
incasineranno il filepnpm-lock.yaml
. C'è un problema a riguardo che è ancora aperto al momento della scrittura. - Installare l'ultima versione della dipendenza diretta che ha la dipendenza transitiva obiettivo potrebbe non funzionare. Se la dipendenza diretta non ha aggiornato le definizioni delle versioni, la dipendenza transitiva non verrà aggiornata poiché è stata risolta e bloccata nel file
pnpm-lock.yaml
.
La soluzione
Il campo overrides
è una funzionalità potente in PNPM che ti permette di sovrascrivere alcune risoluzioni di versione. Useremo questa funzionalità per aggiornare le dipendenze transitive e rendere la modifica minima possibile.
Utilizziamo l'avviso di Dependabot di cui sopra come esempio. Ci informa che il pacchetto follow-redirects
ha una vulnerabilità di sicurezza e la versione corretta è 1.15.6
. Tuttavia, la dipendenza diretta gatsby
utilizza axios
che dipende da [email protected]
.
Passo 1: Trova la dipendenza transitiva
Ci sono molti modi per individuare la dipendenza transitiva, ma consiglierei il modo più semplice: cercare nel file pnpm-lock.yaml
.
E "pnpm why"?
Il comando pnpm why <package>
è sicuramente utile. Tuttavia, potrebbe confonderti in questo caso. Ad esempio, quando eseguo pnpm why follow-redirects
, ecco una parte dell'output:
In realtà, c'è solo una risoluzione per follow-redirects
nel file pnpm-lock.yaml
. Il comando pnpm why
potrebbe mostrarti più percorsi che dipendono dalla stessa versione del pacchetto.
Passo 2: Aggiungi le overrides
Il caso più semplice è che esista solo una risoluzione nel file pnpm-lock.yaml
. Puoi aggiungere direttamente la sostituzione nel file package.json
:
Se sei in un workspace, dovresti aggiungere la sostituzione al file package.json
della root del workspace.
Passo 3: Applica le modifiche
Esegui pnpm install
per applicare le modifiche. Possiamo vedere che il pacchetto follow-redirects
viene aggiornato a 1.15.6
nel file pnpm-lock.yaml
con modifiche minime.
Ora puoi rimuovere il campo overrides
dal file package.json
per mantenerlo pulito. Quindi esegui nuovamente pnpm install
per convalidare che le modifiche possono essere applicate senza il campo overrides
.
Risoluzione dei problemi
I passaggi precedenti sono il caso ideale. Le cose potrebbero non andare sempre come previsto. Ecco alcuni suggerimenti per risolvere i problemi:
La versione viene ripristinata dopo aver rimosso il campo "overrides"
Ciò può accadere quando il pacchetto dipendente ha una versione fissa o un intervallo che non include la versione target. Controlla il file package.json
del pacchetto dipendente, in questo caso axios
, per vedere se è applicabile.
Se è così, devi mantenere il campo overrides
nel file package.json
fino a quando il pacchetto dipendente non aggiornerà le definizioni di versione.
Ci sono più risoluzioni per la dipendenza transitiva
Man mano che il progetto cresce, il file pnpm-lock.yaml
potrebbe gonfiarsi con più risoluzioni per lo stesso pacchetto. Ad esempio, potrebbero esserci due versioni principali dello stesso pacchetto foo
:
Il report di vulnerabilità mostra che [email protected]
ha un problema di sicurezza che è stato risolto in 1.0.1
, e [email protected]
non è interessato. Non possiamo semplicemente aggiungere una sostituzione a foo
:
- Se aggiungiamo una sovrascrittura
"foo": "^1.0.1"
, il[email protected]
verrà retrocesso a1.0.1
. Questo potrebbe interrompere il progetto poiché il[email protected]
potrebbe avere alcune nuove funzionalità utilizzate nei pacchetti dipendenti. - Se aggiungiamo una sovrascrittura
"foo": "^2.0.0"
, il[email protected]
verrà aggiornato a2.0.0
. Questo potrebbe interrompere il progetto poiché il[email protected]
potrebbe avere alcune modifiche non retrocompatibili.
Assumendo che foo
segua Semantic Versioning, possiamo aggiungere una sovrascrittura come questa:
Questo aggiornerà solo il [email protected]
a 1.0.1
e manterrà il [email protected]
invariato.
Conclusione
Prima che PNPM supporti l'aggiornamento diretto delle dipendenze transitive, il campo overrides
è una buona soluzione per risolvere le vulnerabilità di sicurezza senza rompere nulla. Spero che questo articolo ti aiuti a gestire questi casi in modo più efficiente. In Logto, utilizziamo questo metodo per mantenere le nostre dipendenze aggiornate e sicure.