題目背景
你維護一個執行於容器的 Node.js API,依賴數個第三方套件,需讀取設定、存取物件儲存並偶爾啟動影像處理子程序。安全團隊希望啟用 --permission,只授予必要的檔案、網路與子程序權限。請說明威脅模型、權限清單、相容性測試、監控與回退方案。
面試官考察點
- 是否知道 Permission Model 是降低受信程式碼誤用的 seat belt,不是惡意程式碼沙箱。
- 能否把檔案、網路、child process、worker、native addon 等能力拆成最小授權。
- 是否識別符號連結、既有檔案描述元、初始化順序與子程序/worker 繼承限制。
- 能否設計灰度、錯誤觀測與不影響業務的回退。
澄清問題
先列出執行時版本、入口腳本、依賴是否使用 native addon、是否需要 worker/FFI/WASI、存取哪些路徑與網域,以及子程序是否必須由應用程式啟動。確認容器與作業系統層已有的 seccomp、使用者身分和唯讀檔案系統策略,避免把 Node 層能力當成唯一防線。
30 秒回答
我會先把它當作受信程式碼的最小權限控制,而非防禦惡意依賴的完整沙箱。用生產依賴清單與執行時稽核產生 fs.read、fs.write、network、child、worker 等授權,先在影子環境與 1% 流量啟用,記錄 ERRACCESSDENIED 與延遲變化。對 native addon、符號連結和既有 fd 做專門測試,保留容器級隔離。若錯誤率或關鍵依賴受影響,移除啟動參數即可回退,並繼續修正權限清單。
分步推導
1. 定義安全邊界
Node 文件把 Permission Model 描述為限制程序存取資源的機制,並明確它不防惡意程式碼;Node 信任被要求執行的程式碼。它適合降低受信應用程式意外讀寫或啟動資源的風險,不能取代容器、OS 使用者、seccomp 或依賴供應鏈防護。
2. 建立權限清單
從預設拒絕開始,只為設定與靜態資源授予 --allow-fs-read,為暫存輸出授予窄路徑 --allow-fs-write,為物件儲存網域授予 --allow-net,僅在確有需要時啟用 --allow-child-process、--allow-worker 或 --allow-addons。把授權記錄成版本化設定並由程式碼負責人審查。
3. 驗證執行時行為
覆蓋啟動、健康檢查、上傳、影像處理、排程工作與錯誤路徑。驗證 process.permission.has() 結果,並確認 permission.drop() 不可逆且只影響後續存取;已開啟的 fd、socket 或 worker 不會自動關閉。測試符號連結、native addon、npx 與子程序邊界。
4. 灰度與回退
先在 staging 與單個無狀態執行個體開啟,收集被拒權限的資源、呼叫堆疊、版本與租戶,避免記錄敏感內容。擴大前設定錯誤率、P95、啟動成功率與業務工作完成率閘門。回退只需撤銷 --permission 或對應 --allow-* 參數;同時保留容器唯讀、非 root 與網路策略。
高品質示範回答
我會先把服務依賴畫成權限矩陣:設定目錄唯讀、暫存目錄寫入、物件儲存必要網域、影像轉換的 child process,以及沒有業務理由就禁止 worker 與 native addon。Permission Model 預設限制 fs,透過 --allow-* 逐項放行;我會把參數放進版本化啟動設定,在 CI 用最小映像檔執行整合情境,確認每個路由與背景工作都能完成。灰度階段只覆蓋一類無狀態執行個體,按錯誤碼聚合 ERRACCESSDENIED,並保留資源路徑雜湊而非原文。特別驗證符號連結、既有檔案描述元與子程序/worker 不繼承模型等限制;惡意程式碼風險繼續交給容器和 OS 隔離。達到啟動成功率、P95、拒絕事件與工作完成率門檻後再擴大。出現關鍵依賴拒絕或錯誤率上升時,撤銷啟動參數即可回到原行為,之後補齊權限清單再重試。
常見誤區
- 宣稱 Permission Model 能安全執行惡意第三方套件。
- 直接使用
--allow-fs-read=、--allow-fs-write=,失去最小權限價值。 - 忽略 native addon、worker、child process、WASI、FFI 與網路存取限制。
- 認為
permission.drop()會關閉已開啟的 fd、socket 或 worker。 - 只在本機啟動測試,不覆蓋 npx、符號連結與真實背景工作。
追問與應對
如果問「它能取代容器沙箱嗎?」
回答:不能。Node 文件明確它不防惡意程式碼,應與非 root、唯讀檔案系統、seccomp、網路策略及依賴供應鏈控制疊加。
如果問「為什麼服務啟動後仍然讀不到檔案?」
回答:檢查入口腳本、設定路徑是否在允許清單,路徑萬用字元是否符合預期,以及初始化讀取是否發生在權限模型建立之後;用 permission.has() 與拒絕事件定位。
如果問「如何允許影像處理?」
回答:單獨授予 --allow-child-process,限制可執行檔與輸入輸出目錄,並讓子程序在容器與 OS 層繼續受限;若能改成純函式庫呼叫,優先移除子程序權限。