GitHub Actions cache 怎麼設才安全:restore-keys 不是可信來源
GitHub Actions 的 cache 很適合存 package manager 已下載的依賴;它不適合存 token、.env、部署憑證或任何一旦被讀到就有風險的內容。原因不是 cache 一定會外洩,而是能還原 cache 的 workflow 必須把它當成外部輸入,而不是你剛剛在同一個 job 寫入的私有檔案。
直接答案是:cache 只存可重新下載或重新產生的資料;key 以 lockfile 等輸入決定;restore-keys 只當效能 fallback,不能成為信任邊界。
先理解命中順序
actions/cache 先找完整的 key,再找 key 的部分匹配;若仍找不到,才依序搜尋 restore-keys。部分匹配有多筆時,會使用最近建立的一筆。
- uses: actions/cache@v4 with: path: ~/.cache/pnpm key: pnpm-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | pnpm-${{ runner.os }}-這段設定的目標是「lockfile 不變時拿到精確 cache;變了時可暫時還原同平台的較舊依賴下載快取」。它不是「永遠拿到正確的 node_modules」。安裝步驟仍要根據 lockfile 驗證依賴,例如使用你專案既有的 frozen lockfile 安裝方式。
不要把 cache 當成 artifact 或 secret store
cache 與 artifact 的使用目的不同:cache 用於可重建、但重新取得成本高的資料;artifact 則是用於保存 workflow 產物、供後續 job 或人工查看。兩者都不適合裝 secrets。
GitHub 文件也明確警告:能讀取 cache 的人可能透過 pull request 存取其內容。因此以下資料不應放進 cache path:
.npmrc、.pypirc、.netrc或含 token 的設定檔。.env、雲端憑證、SSH key 與暫存 deployment credential。- 有可能在下一個高權限 job 被直接執行的產物。
即使低信任 workflow 對 default branch cache 是 read-only,還原後的檔案仍應當成不可信資料。快取隔離能降低寫入風險,不會把快取內容變成可直接執行的安全輸入。
低信任事件採 restore-only 更清楚
fork PR 或其他低信任觸發來源如果只需要加速安裝,使用 restore-only 操作能把意圖寫明:
- name: Restore dependency cache uses: actions/cache/restore@v4 with: path: ~/.cache/pnpm key: pnpm-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | pnpm-${{ runner.os }}-這避免 job 嘗試儲存但因權限被拒時留下令人誤解的 warning。真正負責更新 cache 的 trusted workflow,則可以放在預設分支的 push CI。
快取設定檢查表
- path 只包含 package manager cache,沒有 secrets 或 build deploy output。
- 完整 key 包含 OS 與 lockfile hash;有 matrix 時也加入會改變二進位相容性的版本。
- restore key 由最具體到最寬鬆排序,並接受它只改善速度、不保證內容正確。
- 還原後仍執行依賴安裝與測試;不要跳過 integrity 驗證。
- 不可信 PR 與有 secrets 的寫入/部署 workflow 分離。
快取風險和 pull_request_target 的風險都來自信任邊界被混在同一個工作流程;若 workflow 還會 checkout PR 程式碼,請再看 GitHub Actions 的 fork PR checkout 保護。
參考資料:
回報錯字、失效連結,或告訴我你想看的延伸主題。