AI 工程

Kiro IDE 1.3 實戰:用 Local Command Sandbox 關住 agent 的 shell 指令,再用 /workflow-run 一行啟動已存 Workflow

你讓 coding agent 跑 npm install、跑測試、跑一段它自己寫的 shell script,按下「允許」的那一刻,其實就把整台機器的網路和檔案權限交給了那串指令,以及它叫起來的每一個子程序。postinstall script 偷連外網、測試程式誤刪家目錄底下的檔案,這類事故都不需要 agent「變壞」,只要指令本身有問題就夠了。

AWS 的 Kiro 團隊在 10 月 13 日發布 Kiro IDE 1.3,主打兩件事:Local Command Sandbox(把 agent 跑的 shell 指令關進作業系統層的沙箱),以及從聊天直接啟動已存的 Workflow(/workflow-run)。這篇不談趨勢,直接講:這兩個功能的邊界在哪、設定檔怎麼寫、哪些坑要先知道,讓你今天就能把它開起來。

說明:以下內容依據 Kiro 官方 changelog 與文件(sandbox 文件 10/15 更新、workflows 文件 10/13 更新)整理,筆者沒有在每個平台上實測過,標示「值得實測」的地方建議自己驗證。

一、為什麼「逐條審核指令」不夠

多數 coding agent 的安全模型是權限規則(permission rules):哪些工具可以自動執行、哪些要問你、哪些永遠拒絕。問題在於,權限規則審核的是「指令字串」,管不到指令跑起來之後做了什麼。pytest 看起來無害,但測試裡的 fixture 可能打外部 API;make build 可能呼叫一個會上傳檔案的腳本。你同意的是表面那一行,實際執行的是一整棵程序樹。

Kiro 1.3 的思路是補上第二層:權限規則照樣決定「能不能跑」,沙箱則限制「跑起來之後碰得到什麼」。官方 changelog 的說法很直接:沙箱能降低風險,但不能保證完全隔離,所以還是要繼續看 agent 提出的指令。

二、運作原理:沙箱圈住誰、不圈住誰

Kiro 1.3 Local Command Sandbox 的邊界:哪些在沙箱內、哪些在沙箱外,以及三種網路模式

這是整篇最重要的一張圖,先把邊界搞清楚,後面的設定才不會誤會。

在沙箱裡面的:

  • agent 在終端機執行的指令,以及這些指令產生的所有子程序
  • 本機 stdio 型 MCP server 的程序(要另外打開 mcpSandboxing)

在沙箱外面的:

  • agent 本身(harness 與模型對話)
  • Kiro 內建的檔案讀寫工具:它們不經過沙箱,仍由 fs_read/fs_write 權限規則管
  • 遠端 HTTP/SSE 型 MCP server

這個切法的意思是:沙箱防的是「指令執行的副作用」,不是「agent 透過內建工具改檔」。如果你擔心 agent 直接用編輯工具改到 repo 外的檔案,該收緊的是權限規則,不是沙箱設定。

底層用什麼隔離? 依官方文件:

  • macOS:不用裝任何東西,Kiro 透過系統內建的 Seatbelt(sandbox-exec)。
  • Linux:需要 Bubblewrap(bwrap)在 PATH 上,Kiro 不會幫你裝。文件另外提到網路過濾類的模式(COMMON_DEPENDENCIES,以及 DEFAULT_BLOCKED 搭配允許清單)需要 socat。
  • Windows:COMMON_DEPENDENCIES 或 DEFAULT_ALLOWED 能用之前,要做一次管理員權限的設定,IDE 會提示你;DEFAULT_BLOCKED 不用先設定就能跑。

要特別注意的一點:如果後端不可用(例如 Linux 沒裝 bwrap),Kiro 會把沙箱標成 Unavailable,指令就在沒有作業系統隔離的情況下執行,除非當前模式要求一定要保護。換句話說,設定檔寫了 enabled: true 不代表真的有在隔離,一定要看狀態列。

三、手把手:五分鐘把沙箱開起來

Step 1:Linux 使用者先裝依賴

# Debian / Ubuntu
sudo apt install bubblewrap socat
# Fedora
sudo dnf install bubblewrap socat

which bwrap socat   # 兩個都要有輸出

macOS 跳過這步。Windows 等 IDE 提示時完成管理員設定。

Step 2:打開設定檔

點 IDE 狀態列的 Command sandbox。Kiro 會打開目前生效的設定檔:專案檔存在就開專案檔,不然開全域檔;兩個都沒有,就建立一個內容為 {"enabled": false} 的全域檔。也可以從命令面板執行 Open User Sandbox Config (JSON) 直接開全域檔。

兩個檔案位置:

範圍 路徑
全域 ~/.kiro/settings/sandbox.json
專案 <workspace-root>/.kiro/settings/sandbox.json

多根目錄(multi-root)的工作區只有第一個資料夾的專案檔會被讀,這點容易踩到。

Step 3:寫入設定

建議的起手式:

{
  "enabled": true,
  "networkAccess": "COMMON_DEPENDENCIES"
}

存檔後設定直接套用到正在跑的 session,狀態列會從 Applying 變成 Active。如果顯示 Error,代表 JSON 有問題,先前的設定會繼續生效,修好再存一次,必要時用 Reload Window。

三個鍵:

鍵 值 預設
enabled true/false(必填) 無
networkAccess DEFAULT_BLOCKED/COMMON_DEPENDENCIES/DEFAULT_ALLOWED DEFAULT_BLOCKED
mcpSandboxing true/false false

networkAccess 的值大小寫敏感,寫成 common_dependencies 不會生效;未知的鍵會被忽略,打錯字也不會報錯,所以存完一定要回頭確認狀態。

Step 4:選對網路模式

  • DEFAULT_BLOCKED(預設):全部擋,只放行 sandbox_network 規則允許的主機。適合處理不信任的 repo、或只需要本機跑測試的任務。
  • COMMON_DEPENDENCIES:常見的套件、原始碼、建置與容器服務可以連,其他主機照擋。日常開發最實用的折衷。要注意的是,官方文件沒有列出這個模式到底放行哪些主機,值得實測的點是:你公司的私有 registry、內部 Git 主機大概率不在裡面。
  • DEFAULT_ALLOWED:全開。文件明講在這個模式下不要依賴 sandbox_network 的 deny 規則。這時沙箱主要剩下檔案系統面的限制。

Step 5:用允許清單放行內部主機

主機規則不寫在 sandbox.json,而是寫在權限檔 ~/.kiro/settings/permissions.yaml(單一專案則是 ~/.kiro/workspace-roots/<hash>/permissions.yaml):

rules:
  - capability: sandbox_network
    match: ['packages.internal.example.com']
    effect: allow
  # 這條必須放在下面的萬用字元之前
  - capability: sandbox_network
    match: ['uploads.example-corp.net']
    effect: deny
  - capability: sandbox_network
    match: ['*.example-corp.net']
    effect: allow

這裡有兩個跟其他權限規則不一樣的地方,最容易寫錯:

  1. 先符合的規則勝出。一般權限能力是「deny 永遠贏」,但 sandbox_network 是照順序,第一條符合的規則決定結果。所以要擋的特定子網域必須寫在萬用字元 allow 之前,順序寫反就等於沒擋。
  2. sandbox_network 不屬於 all。就算你寫了 capability: all, effect: allow,也不會打開沙箱內的網路。這是刻意的設計,避免一條寬鬆規則順手把沙箱網路打穿。

比對規則不分大小寫,支援完整主機名和 *.suffix 萬用字元。

額外一步:把本機 MCP server 也關進去

{
  "enabled": true,
  "networkAccess": "DEFAULT_BLOCKED",
  "mcpSandboxing": true
}

切換這個選項會重啟本機 MCP server,文件說大約要一分鐘。如果某個 server 包不進沙箱,指令沙箱照樣有效,Kiro 會告訴你哪個 server 沒有被涵蓋。第三方 stdio MCP server 本質上就是你在本機跑一支別人寫的程式,這個選項值得打開。

四、團隊設定的關鍵:專案檔只能收緊、不能放寬

這是 1.3 設計上最聰明的一點,對團隊特別重要。官方規則:

  • 全域政策生效時,專案檔只能收緊:不能把 enabled 改成 false、不能選更開放的網路模式、不能關掉全域開啟的 MCP 包裝。
  • 全域檔不存在或 enabled: false 時,專案檔寫 enabled: true 可以為該專案開啟沙箱。

實際意義是:你 clone 下來的 repo,沒辦法透過它自帶的 .kiro/settings/sandbox.json 打開網路或關掉你的沙箱。這直接擋掉了「惡意 repo 在設定檔裡放寬權限」這條攻擊路徑。

可照做的團隊配置建議:

  1. 每位工程師的全域檔設 {"enabled": true, "networkAccess": "COMMON_DEPENDENCIES"},當作底線。
  2. 處理敏感程式碼的 repo,在專案檔放 {"enabled": true, "networkAccess": "DEFAULT_BLOCKED", "mcpSandboxing": true} 並 commit 進去。因為只能收緊,這份檔案對所有人都只會更安全。
  3. 內部主機用 permissions.yaml 的 sandbox_network 規則放行,而不是退到 DEFAULT_ALLOWED。
  4. 永遠不能跑的操作(例如 git push --force、刪除雲端資源)繼續用 deny 權限規則擋,官方文件也是這樣建議:沙箱不是取代權限規則。

五、第二個功能:從聊天直接啟動已存的 Workflow

從 /workflow-run 啟動已存 Workflow 的流程:選 recipe、填 inputs、驗證、背景執行

Kiro 的 Workflow 是一張由 agent 步驟組成的圖,可以有序列、迴圈、平行分支,每一步都在獨立 session、用全新 context 執行,並在背景跑。內建的 recipe 有 investigate、feature-pipeline、publish-pr。1.3 之前要去 Workflows 面板啟動,現在在聊天框打指令就能跑。

先確認 Workflows 有開

Workflows 是 opt-in:在 IDE 打開專案的 Workspace Configuration → Workflows → 啟用,然後開一個新的 chat session(對應設定是 kiroAgent.workflows.enabled)。官方文件也說,如果看不到 Workflows 選項,代表你的帳號還沒開放。沒啟用時 /workflow-run 不會啟動任何 run。

兩種啟動方式

互動式:輸入 /workflow-run → 從清單選 recipe → 在內嵌表單填 inputs → OK → 送出。

一行帶參數(適合存成你的常用指令):

/workflow-run investigate brief="Trace timeout settings" report_path=".kiro/reports/timeouts.md"

Kiro 會驗證 recipe 和 inputs,不經過模型回合就直接啟動,然後打開 Workflows 面板顯示這次 run。「不經過模型」很關鍵:啟動這件事本身不會被模型改寫或誤解,你給的參數就是送進 recipe 的參數。CLI 對應的是 /workflow 指令家族,例如 /workflow run plan-and-implement --task "Describe the change"。

寫一個自己的 recipe

專案層的 recipe 放 .kiro/workflows/,副檔名 *.workflow.json、*.workflow.yaml 或 *.workflow.yml;跨專案的放 ~/.kiro/workflows/。官方文件的範例:

{
  "name": "plan-and-implement",
  "description": "Plan a change, then implement it",
  "inputs": { "task": "prompt" },
  "steps": [
    { "type": "step", "id": "plan", "agent": "wf-planner",
      "prompt": "Create an implementation plan for: {{task}}. Do not edit files." },
    { "type": "step", "id": "implement", "agent": "wf-coder",
      "prompt": "Implement this plan, then run relevant tests:\n\n{{previous.output}}" }
  ]
}

寫 recipe 的實戰要點:

  • 規劃步驟明講「Do not edit files」。官方範例特意這樣寫,把「想」和「改」拆成兩個 session,planner 的輸出用 {{previous.output}} 交給 coder,每一步 context 都乾淨。
  • 每個 {{name}} 都要在 inputs 宣告,而且啟動時要提供。inputs 裡的型別(prompt、file、string)只是提示啟動介面要收什麼值,執行時不會強制檢查,值一律以文字進到 recipe。
  • step 的 agent 要用 workflow 專用 agent,例如 wf-planner、wf-coder、wf-design-reviewer、wf-pr-submitter;內建的 sub-agent 不能拿來當 step agent。
  • 上限:最多 50 個 step 節點、巢狀深度 8。迴圈用 repeat 搭配 maxIterations,平行用 parallel 搭配 joinPolicy(all/allSettled/any)。
  • 啟動前先驗證:請 Kiro 對檔案跑 validate_workflow。文件提醒,驗證通過不代表 run 一定能啟動。
  • 同名衝突:同一個檔名同時有 JSON 和 YAML,JSON 勝出,另一個回報為衝突。優先序是專案、使用者、帳號同步、內建;高優先的 recipe 無效時,不會蓋掉低優先的有效版本。

六、兩個功能放在一起看:限制與 trade-off

沙箱的限制(照官方講法):

  • 它降低風險,不保證隔離。內建檔案工具和遠端 MCP 都不在裡面。
  • 沒有獨立的檔案系統允許清單;沙箱內指令能看到、能寫哪些路徑,由你的 fs_read/fs_write 規則決定。
  • 後端不可用時會退回無隔離執行,所以 Linux 機器、CI runner、dev container 都要確認 bwrap 在不在。在已經是容器的環境裡 bubblewrap 能不能正常建 namespace,是值得實測的點。
  • COMMON_DEPENDENCIES 的主機清單沒公開,私有 registry 要自己加規則。

Workflow 的限制:

  • 官方明講 Workflow 比單一 session 耗更多 token,每一步都是新 session、新 context。
  • 適合「步驟固定、重複出現」的任務:調查問題寫報告、規劃後實作、開 PR。一次性的小修改直接在聊天裡做就好,用 Workflow 反而慢又貴。

什麼時候該開什麼:

情境 建議
剛 clone 的陌生 repo 沙箱 DEFAULT_BLOCKED + mcpSandboxing: true
日常開發,要裝套件 沙箱 COMMON_DEPENDENCIES + 內部主機 allow 規則
需要打任意外部 API 的整合測試 暫時 DEFAULT_ALLOWED,但保留 deny 權限規則,結束後改回
每週重複的調查/PR 流程 寫成 recipe,用 /workflow-run 一行啟動
一次性小改 直接聊天,不用 Workflow

七、今天就能做的四件事

  1. Linux 使用者先 which bwrap socat,缺什麼裝什麼。
  2. 全域 sandbox.json 開 COMMON_DEPENDENCIES,確認狀態列顯示 Active,不是 Unavailable。
  3. 把內部 registry、Git 主機寫成 sandbox_network allow 規則,要擋的特定子網域放在萬用字元前面。
  4. 挑一個你每週都在重複的流程(例如「查 bug → 寫報告」),用官方的 plan-and-implement 範例改成自己的 recipe,存進 .kiro/workflows/,之後用 /workflow-run 一行跑。

沙箱解決的是「agent 指令跑起來之後碰到什麼」,Workflow 解決的是「重複流程每次都要重講一遍」。兩個功能都不花俏,但都是把 coding agent 從「每步盯著」推向「放心交辦」的實際一步。

來源

整理:DataAgent · Coding Agent 實戰教學

發表迴響

%d 位部落客按了讚: