Node.js 24.20 的權限模型怎麼試:用 --permission-audit 找出需求,再用 permission.drop 收斂
Node.js 24.20.0 LTS 在 2026 年 8 月 26 日發布,其中包含 Permission Model 的兩個實用更新:--permission-audit 與 process.permission.drop()。前者可以先觀察應用程式會碰到哪些受限資源,後者則讓程式在初始化完成後主動收回權限。
直接答案是:先在 Node.js 24.20.0 使用 --permission-audit 跑完整的測試與啟動流程,記錄檔案、網路、子程序等需求;再用 --permission 加上最小 allow flags,最後在不再需要時呼叫 process.permission.drop()。不要把這套模型當成能阻止惡意程式的完整 sandbox。
24.20.0 到底新增了什麼
Node.js 的 Permission Model 本身早在 v20.0.0 加入,並在 v22.13.0、v23.5.0 起不再是 experimental。24.20.0 的 release note 列出:
| 功能 | 用途 | 會不會直接阻擋存取 |
|---|---|---|
--permission-audit | 觀察應用程式在權限模式下會觸發哪些 violation | 不會;程式繼續執行 |
process.permission.drop() | runtime 主動撤銷整個 scope 或明確資源的權限 | 會影響後續權限檢查 |
--permission 是 enforce mode:沒有被授權的操作會以 ERR_ACCESS_DENIED 失敗。--permission-audit 則把 violation 發布到 node:diagnostics_channel,用來協助你找出真正需要的 allow list。若同時傳入兩個 flag,--permission 優先,會進入 enforce mode,不能把它們當成「一邊記錄、一邊允許」的組合開關。
先用 audit mode 盤點應用程式
先確認執行環境真的有目標版本:
node --versionnode --permission-audit app.cjs在 app.cjs 入口盡早訂閱你關心的 diagnostics channel:
const diagnostics_channel = require('node:diagnostics_channel');
for (const scope of ['fs', 'net', 'child']) { diagnostics_channel .channel(`node:permission-model:${scope}`) .subscribe(({ permission, resource }) => { console.log(JSON.stringify({ permission, resource })); });}
// 載入你的正常 application entrypoint。require('./server.cjs');Audit mode 不會把這些操作直接變成錯誤;你會得到像 fs.read、net 或 child 的 scope 與資源資訊。請用代表性的啟動、測試、排程和錯誤處理流程跑一次,不要只啟動 server 就把產生的清單當成完整答案。動態載入、原生 addon、worker 和外部 CLI 往往只會在特定路徑出現。
在 CI 裡可以把 audit output 轉成不含秘密內容的報表,按「必要」「可移除」「只在初始化期間需要」分類。不要直接把完整環境變數、Authorization header 或讀取檔案的內容一起印到 log;Permission Model 只回報 scope 和 resource,不代表你的 logging 就自動安全。
再切到最小的 enforce mode
盤點完後,把權限寫成啟動命令或受控的 Node configuration。最小示例:
node \ --permission \ --allow-fs-read=./ \ --allow-fs-write=./tmp \ --allow-net \ --allow-child-process \ app.cjs這裡的 --allow-net 和 --allow-child-process 只是示意,正式環境應依應用程式實際需求收窄;如果只需要讀取某個設定目錄,就不要為了省事把整個檔案系統設成 *。檔案系統 allow flag 支援相對路徑、絕對路徑與 wildcard,但 wildcard 的範圍要在 code review 中明確說明。
切換時最容易遇到的不是 Node.js 本身,而是啟動器和工具:
npx需要先能讀取 package、cache 或 globalnode_modules,不能只加--permission就期待它照常載入。--env-file、某些 OpenSSL 設定與 V8 flags 可能在 Permission Model 初始化前讀取,不能把它們和 runtimefs操作視為同一層。- native module、network、child process、worker、WASI、FFI 和 inspector 都可能被限制;要逐一測試,而不是只看 HTTP health check。
用 permission.drop() 縮短權限生命週期
如果程式只在啟動時需要讀取某個目錄或建立 child process,可以在初始化完成後撤銷對應 scope:
const fs = require('node:fs');
const config = fs.readFileSync('/app/config.json', 'utf8');
// 後續程式不再需要讀取設定目錄時,撤銷相同的授權資源。process.permission.drop('fs.read', '/app');
// 若 child process 不應再被建立,可以撤銷整個 scope。process.permission.drop('child');
console.log(`loaded ${config.length} bytes of configuration`);這個操作是不可逆的,而且只影響未來的 permission checks。已經開啟的 file descriptor、network socket、child process 或 worker 不會因為 drop() 自動關閉;程式仍要自行完成 close、terminate 或 shutdown。傳入 reference 時也必須和原本 explicit grant 完全一致:如果用 wildcard 授權,就不能再假設可以 drop 單一檔案。
可以在重要邊界用 process.permission.has(scope, reference) 做診斷,但不要把 has() 當成所有安全判斷的替代品。它只回答目前的 Permission Model 狀態,不會驗證使用者是否有資格存取某筆資料,也不會改變資料庫或 API 的 authorization。
Permission Model 的安全邊界
Node.js 官方把這套功能描述成 seat belt:它主要防止受信任的程式碼意外碰到未授權資源,並不提供對抗惡意程式碼的安全保證。Node.js 會信任你要求它執行的 code;如果攻擊者已能任意改寫或執行程式,不能只靠 Permission Model 宣稱已完成隔離。
因此 production rollout 還是要保留:
- dependency lockfile、套件來源與第三方程式碼審查。
- process、container、host 和 cloud IAM 的多層權限限制。
- allow list 的變更審查,以及每次 Node.js 升級後的回歸測試。
- 對 secrets、logs 和既有 file descriptors 的另外保護。
結論是:24.20.0 的價值不在於一個神奇的 --permission 開關,而在於讓團隊可以先以 audit mode 取得證據,再用最小授權啟動,並在初始化後用 permission.drop() 收窄權限。把這個流程接進測試與部署紀錄,才比直接複製一組寬泛 flags 更可靠。
常見問題
--permission-audit 會讓未授權操作失敗嗎?
不會。Audit mode 會執行權限檢查並透過 diagnostics channel 發布 violation,但不會拋出 ERR_ACCESS_DENIED;它的用途是先盤點需求。真正阻擋要使用 --permission。
process.permission.drop() 會關閉已建立的連線嗎?
不會。它只影響未來的 permission checks,不會自動關閉已開啟的 file descriptor、network socket、child process 或 worker。資源生命週期仍要由應用程式管理。
Permission Model 能防止惡意 npm 套件嗎?
不能把它當成完整 sandbox。官方說明它主要防止受信任程式碼的意外存取,惡意程式碼可能繞過這些限制。因此仍需做 dependency、container、host 與 IAM 層級的防護。
參考資料:
Node.js Release:Node.js 24.20.0 (LTS)
回報錯字、失效連結,或告訴我你想看的延伸主題。