繁體中文(台灣)
  • pnpm
  • security
  • dependencies
  • npm
  • yarn

使用 PNPM 升級傳遞依賴項:修復安全漏洞而不破壞其他功能

修復安全漏洞可能是一項令人十分煩惱的工作,尤其當涉及到傳遞依賴項時。學習如何在不影響直接依賴項的情況下進行升級。

Gao
Gao
Founder

當今,安全漏洞已成為軟體開發中的常見問題。幸運的是,我們有像 GitHub Dependabot 這樣的工具幫助我們通過自動檢測和拉取請求來保持依賴項的最新。

Dependabot

然而,它並不總是能如預期運作。由於某些依賴項是傳遞性的,升級這些依賴項可能對這些工具來說是一項困難的任務,因為它們不知道更改的影響以及發生衝突時應做什麼決策。我們需要手動處理這些情況。

不起作用的方法

  • pnpm up 這樣的官方命令會搞亂你的 pnpm-lock.yaml 文件。在撰寫本文時,這個 問題 仍然存在。
  • 安裝具有目標傳遞依賴項的最新版本直接依賴項可能無效。如果直接依賴項沒有升級版本定義,傳遞依賴項將不會被升級,因為它已在 pnpm-lock.yaml 文件中解析和鎖定。

解決方案

overrides 欄位 是 PNPM 中的一個強大功能,允許你覆蓋某些版本解析。我們將使用此功能來升級傳遞依賴項,並使更改儘可能最小化。

讓我們以上面的 Dependabot 警報為例。它告訴我們 follow-redirects 套件有一個安全漏洞,修補版本是 1.15.6。然而,直接依賴項 gatsby 使用 axios,而它依賴於 [email protected]

步驟 1:查找傳遞依賴項

有很多方法可以定位傳遞依賴項,但我會推薦最直接的方法:搜尋 pnpm-lock.yaml 文件。

那麼 "pnpm why" 呢?

pnpm why <package> 命令確實有用。然而,在這種情況下,它可能會讓你感到困惑。例如,當我運行 pnpm why follow-redirects 時,這是輸出的一部分:

實際上,在 pnpm-lock.yaml 文件中 follow-redirects 只有一個解析。pnpm why 命令可能會向你顯示依賴於該包同一版本的多條路徑。

步驟 2:添加覆蓋

最簡單的情況是,在 pnpm-lock.yaml 文件中只有一個解析。你可以直接將覆蓋添加到 package.json 文件:

如果你在一個工作區中,你應該將覆蓋添加到工作區的根 package.json 文件。

步驟 3:應用更改

運行 pnpm install 來應用更改。我們可以看到 follow-redirects 套件升級到了 1.15.6,並且在 pnpm-lock.yaml 文件中僅有最小的更改。

現在你可以從 package.json 文件中移除 overrides 欄位以保持其整潔。然後再次運行 pnpm install 驗證沒有 overrides 欄位也能應用更改。

疑難排解

上述步驟是理想情況。事情可能並不總是如預期進行。這裡有一些疑難排解的建議:

移除 "overrides" 欄位後版本被還原

這可能發生在依賴包有固定版本或一個不包括目標版本的範圍。檢查依賴包的 package.json 文件,在此情況下,即 axios,看看是否適用。

如果適用,你需要將 overrides 欄位保留在 package.json 文件中,直到依賴包升級版本定義。

傳遞依賴項有多個解析

隨著專案的增長,pnpm-lock.yaml 文件可能會有多個相同套件的解析。例如,可能有同一套件 foo 的兩個主要版本:

漏洞報告顯示 [email protected] 有一個安全問題,已在 1.0.1 中修復,而 [email protected] 不受影響。我們不能簡單地添加 foo 的覆蓋:

  • 如果我們添加覆蓋 "foo": "^1.0.1"[email protected] 將被降級到 1.0.1。這可能會破壞專案,因為 [email protected] 可能有一些在依賴包中使用的新功能。
  • 如果我們添加覆蓋 "foo": "^2.0.0"[email protected] 將被升級到 2.0.0。這可能會破壞專案,因為 [email protected] 可能有一些重大更改。

假設 foo 遵循 語義版本控制,我們可以像這樣添加覆蓋:

這將只升級 [email protected]1.0.1,並保持 [email protected] 不變。

結論

在 PNPM 支援直接升級傳遞依賴項之前,overrides 欄位是解決安全漏洞而不破壞其他功能的一個不錯的變通方法。我希望本文能幫助你更有效地處理這些情況。在 Logto,我們使用這種方法來保持依賴項的最新和安全。