對象:用 Next.js(或類似的 JS 框架)開發並公開應用程式的人,尤其是「靠 AI 幫忙做出來、維運憑感覺」的人。這是從真實事故(→ 放任 CVSS 10.0 的經歷)中整理出來的做法。
本站的看法:重要的不是速度,而是不漏看的機制
個人開發者在安全上做得不夠,大多不是知識不足,而是無法讓維運持續下去。比誰都早讀到 CVE 新聞並沒有價值(速度交給廠商和新聞即可)。真正有效的是讓與自己相關的 CVE 不被漏看的機制。所以本文著重於建立這樣的機制,而不是多知道一些知識。
1. 以實際執行的版本判定
「是否在用危險的版本」,要用實際執行的版本來衡量,而不是清單裡的下限。因為清單上的數字與實際執行的版本常常不一致。
✗ 按 package.json 的下限計算
"next": "^16.0.0" →「16.0.0 有漏洞,所以我們也有」,被高估為 「8 個有漏洞」。
✓ 按實際執行的版本計算
npm ls next 顯示實際解析出的版本 → 已自動升級的是安全的,只有固定版本的會落後。實際是 2 個。
# see the versions actually resolved
npm ls next react react-dom
# inside a running container
docker exec <container> npm ls next脫字號範圍(^16.0.0)會在重新建置時自動升級,固定版本的相依套件則會落後。請以這裡顯示的版本來判定。
如何檢查自己的環境
以下步驟能確認你的應用程式實際在執行哪個版本,以及是否受已知 CVE 影響。每一步都只檢查你自己的環境。
確認本機的版本
在專案資料夾執行 npx next info。它會顯示 next、react、react-dom 的實際版本,以及距離最新版落後多少。npx next -v 只顯示 Next.js 的版本。
查出為什麼是這個版本
npm ls next(或 pnpm why next)會顯示安裝了哪個版本、經由哪個套件引入。如果鎖定檔(package-lock.json 或 pnpm-lock.yaml)沒有 commit,每次建置的版本都可能改變,所以先把它 commit。
確認正式環境實際執行的版本
在本機更新,不會改變仍在執行舊映像檔的伺服器。若是容器,讀取執行中容器內 next 的 package.json 的 version 欄位(指令見下)。使用 output: 'standalone' 時也同樣適用。
比對已知的 CVE
npm audit --omit=dev 只檢查會部署到正式環境的相依套件。加上 --audit-level=high,發現 High 以上時就會以非零值結束,CI 可以因此停下。用 osv-scanner 掃描鎖定檔也能達到同樣目的。
閱讀符合你環境的官方公告
Next.js 的安全公告有時會分 App Router 和 Pages Router,或分自架與託管平台。把公告列出的修復版本,與步驟 1 到 3 查到的版本對照。
# local: actual versions and distance from latest
npx next info
# the version running inside the production container
docker exec <container> node -p "require('next/package.json').version"
# check only production dependencies; fail on High or above
npm audit --omit=dev --audit-level=high執行方式不同,影響也不同
同一個 CVE,會因你執行 Next.js 的方式而影響或不影響你。以下按部署類型整理兩個過去的案例:
| 執行方式 | Middleware 授權繞過(CVE-2025-29927) | RSC RCE(CVE-2025-55182) | 誰負責更新 |
|---|---|---|---|
| 託管平台(Vercel、Netlify 等) | 不受影響(路由在另一個系統中執行) | 使用 App Router 就受影響;有阻擋規則,但仍必須更新 | 你(下一個版本由你的鎖定檔決定) |
| 自架(next start / standalone,含 Docker) | 受影響 | 使用 App Router 就受影響 | 你(透過重新建置映像檔並重新啟動) |
| 靜態匯出(output: 'export') | 不受影響(沒有伺服器在執行) | 沒有伺服器接收請求,一般不會影響你 | 你(建置時的相依套件仍需更新) |
所以即使使用託管平台,提升 Next.js 版本仍是你的工作。把平台的保護措施當作在升級到修補版本之前爭取時間。
也要確認支援期限。依官方支援政策,截至 2026 年 10 月:
| 版本系列 | 狀態(2026 年 10 月) | 安全修正 |
|---|---|---|
| 16.x | Active LTS(功能、修正、安全修補) | 有 |
| 15.x | Maintenance LTS(首次發布後兩年) | 僅限重大問題 |
| 14.x 及更舊 | 不受支援 | 嚴重問題時偶爾提供,沒有保證 |
2. 自動監控相依套件
靠人工追蹤 CVE 撐不下去,而那種遺漏就會變成事故。用工具自動監控。
免費的相依套件監控
osv-scanner scan -L pnpm-lock.yaml若用 GitHub,就啟用 Dependabot(儲存庫的「Settings」→「Advanced Security」→「Dependabot alerts」)。只有與你的相依套件相符的 CVE 才會以 PR 通知你。
關鍵在於優先順序。本站的立場是:以「是否正被利用(KEV)」乘上「CVSS 有多高」來排序。CVSS 再高,沒用到的元件影響也小;分數中等但正被利用的,則要最優先處理。這種優先順序判斷就是工作的核心。
3. 更新:改用修復版,而不是繞過處理
發現漏洞時,把框架升級到修補版本,修復漏洞本身。
表面處理(不充分)
- 只在反向代理擋掉看起來像攻擊的請求
- 停掉扣費或症狀,就當作「處理完畢」
- RCE 漏洞本身仍然存在
根本修復(正確)
- 把框架升級到修補版本
- 升級後,在記錄中確認攻擊特徵已消失
- 把止住損害與修復根本原因當作兩項獨立的工作,兩者都做
常見的失敗
「停掉了扣費或症狀」≠「處理完畢」。止住損害和修復漏洞是不同的工作。兩者都要做。
實際案例:2025 年 12 月的 React Server Components 漏洞
以下用 2025 年 12 月公開的 React Server Components(RSC)漏洞,說明處理一個已公開的 CVE 實際上是什麼樣子。內容全部來自 React 和 Next.js 的官方公告以及 CISA 的公開資料。
2025 年 12 月 3 日
React 公開了 CVE-2025-55182(CVSS 10.0),可能在未經驗證的情況下於伺服器上執行程式碼。在 Next.js 中,15.x、16.x 及部分 canary 版的 App Router 應用程式受影響(CVE-2025-66478);Pages Router 和 Edge Runtime 不受影響。沒有繞過方法,必須升級到修復版本(15.0.5、15.1.9、15.2.6、15.3.6、15.4.8、15.5.7、16.0.7 等)。2025 年 12 月 5 日
CISA 將它加入已確認遭實際利用的漏洞目錄(KEV)。2025 年 12 月 6 日
Next.js 補充說明:截至太平洋時間 12 月 4 日下午 1 點仍在線上且未修補的應用程式,應輪換其使用的機密(API 金鑰等)。2025 年 12 月 11 日
在檢視修補程式的過程中,又在同一機制中發現兩個問題(阻斷服務與原始碼外洩)並修補。之後阻斷服務的修正被證實不完整,因此發布了 CVE-2025-67779,已經升級的人被要求再次升級。
由此得到三點維運上的教訓:
- 更新一次不代表結束。對同一段程式碼的後續修正,可能相隔幾天就出現
- 平台的阻擋規則只是補充;官方說明升級是唯一完整的修復方法
- 如果在修補前就已上線,除了更新之外也要輪換機密
本站的看法:完成的標準是正式環境的版本已修補,而不是執行過更新
像這次一樣後續修正接連出現時,「上週已經升級了」就不再可靠。判斷是否完成,要看正式環境實際執行的版本是否達到最新公告中的修復版本以上,而不是憑對作業的記憶。本站也是在確認容器已重新建立、並檢查容器內執行的版本之後,才把更新標記為完成。
常見錯誤與修正
- 以 package.json 裡的數字判斷:安裝的版本可能不同。用
npx next info或npm ls next確認。 - 更新完鎖定檔就停下:在正式環境的映像檔重新建置並重新啟動之前,舊版本會繼續執行。確認正式環境內的版本。
- 更新一次就覺得安全:可能還會有後續公告。保持 Dependabot 等通知開啟,並在幾天內持續關注公告。
- 交給平台的阻擋規則:它們不一定能擋下所有形式的攻擊。請升級。
- 停留在不受支援的版本系列:14.x 及更舊版本的修正沒有保證。規劃升級到 16.x。
- 在只用於開發的雜訊中漏看與正式環境相關的警告:先執行
npm audit --omit=dev,看會部署出去的部分。 - 忽略修補之前的那段期間:機密可能在那段時間被取走。輪換 API 金鑰和資料庫密碼(→ .env 和 API 金鑰的基礎)。
4. 用最小權限限制損害
設計成即使應用程式被利用,損害也能被限制住。
以非特權使用者執行
USER 設為 root。這樣即使被入侵,影響也只限於該使用者被允許做的事。DB/Redis 只綁定內部網路
按服務隔離
這些決定了入侵最後是止於「竊取容器內的 env」,還是一路到「主機被接管」。
本站自己也這樣做
本站也按本文所寫,監控自己相依套件的 CVE,讓當初那種遺漏(放任已公開的 CVSS 10.0)不再只靠人的注意力。我們之所以寫「按優先順序(KEV+CVSS)來看」,是因為我們實際上就是這樣維運的。
延伸閱讀
- 事故:放任已公開的 RCE 而被惡意刷費的經歷
- 術語:CVE · CVSS · RCE
- 歷史:Log4Shell — 經由相依套件的 RCE
- 依框架:Next.js 資安對策(邊界、環境變數、相依套件 CVE)
- 排定優先順序:用 CVSS、EPSS、KEV 為 CVE 排序
- 監控:osv-scanner 的設定方式
- 整體狀況:Next.js 和 React 的漏洞很多嗎?(英文,CVE 資料實際顯示了什麼)
出處
- Next.js「Security Advisory: CVE-2025-66478」(2025 年 12 月 3 日;12 月 6 日更新):nextjs.org
- Next.js「Security Update: December 11, 2025」(CVE-2025-55183 / 55184 / 67779):nextjs.org
- NVD「CVE-2025-55182」:nvd.nist.gov / CISA「Known Exploited Vulnerabilities Catalog」:cisa.gov
- Vercel「React2Shell Security Bulletin」:vercel.com
- Vercel「Postmortem on Next.js Middleware bypass」(CVE-2025-29927):vercel.com
- Next.js「Support Policy」:nextjs.org / 「next CLI」:nextjs.org / 「Static Exports」:nextjs.org
- npm Docs「npm audit」:docs.npmjs.com / OSV-Scanner「Usage」:google.github.io / GitHub Docs「Configuring Dependabot alerts」:docs.github.com