# 安全模型

## Localhost 綁定

HTTP server 僅綁定 `127.0.0.1:17989` — 區網 client 無法連到 daemon。Web 儀表板內嵌於執行檔，由同一個 daemon 在 `/` 提供，因此一般情況下瀏覽器來源就是你自己的機器。CORS middleware 只接受 loopback 來源（`localhost`、`127.0.0.1`、`::1`），並以 `Access-Control-Allow-Private-Network` 回應 Chrome Private Network Access。原本另外接受的兩個託管來源 `https://web.agenvoy.com` 與 `https://agenvoy-board.pardn.workers.dev` 已於 v1.0.17 移除 —— 請使用 daemon 在 `/` 提供的儀表板。

碰到憑證、設定檔或行程狀態的端點，在綁定之外另有 `localhostOnly()` 守門。它檢查的是連線的 remote address（`127.0.0.1` / `::1`），不是 `Origin` header。

## 沒有提權模式

不存在 `/sudo` 指令，也沒有 session 層級的提權。`/dangerous` 指令已移除；請改用下述的逐次確認或 TUI 的直接操作。兩者皆由逐請求授權取代：越過安全邊界的呼叫只為那一次呼叫升起確認，授權範圍限於該 session 加上該特定路徑。

`$HOME` 一律可寫，無需設定。兩種情況落在其外：

| 情況 | 行為 |
|---|---|
| `$HOME` 之外的路徑，或 `$HOME` 內的敏感路徑 | `boundary.Restricted` 收集後升起確認，且要求作業系統密碼。核准後該路徑授權給該 session |
| 需要寫到 `$HOME` 之外的指令 | Agent 在該次 `run_command` 附上 `write_paths`；這些路徑要等同一道密碼確認通過後才綁進 sandbox |

密碼檢查集中在 `internal/sudo`：`sudo -n -v` 探測 sudo ticket 是否仍在快取（上限 3 秒），`sudo -S -v` 驗證輸入的密碼（上限 30 秒）。sudo ticket 是唯一的計時器——沒有第二層 TTL。ticket 仍在快取時，提示不會要求輸入密碼；以 root 執行的 daemon 則直接略過檢查。

TUI 與本機 web 儀表板可以收集密碼；web 確認端點只接受來自 loopback 連線的密碼。無法收集密碼的通道——Telegram、Discord、遠端 HTTP 呼叫端——會拿回 **skipped**，不會被提權。通道可以核准提示，但缺少驗證的受限呼叫不會執行。

`sudo` 本身無法在 `run_command` 內執行，不論直接呼叫或放在 `sh -c` 內：呼叫會被拒絕，並指引改用 `write_paths` 與密碼確認。

讀取不受路徑限制。Sandbox 約束的是寫入而非讀取，因此指令只有在作業系統本身拒絕時才會在某路徑失敗。

## 永久拒絕

`config.json` 的 `denied_path` 是硬性拒絕清單：這些路徑讀寫皆不可，任何提示都無法核准，重試同一路徑會以相同方式失敗。項目必須是絕對路徑或以 `~/` 開頭；檔案系統根目錄會被拒收。`denied_command` 是其指令側的對應——清單上的 binary 一律拒絕，`sh -c` 內亦然。

## 敏感檔案防護

符合敏感集合的檔案——SSH keys、`.pem`、`.key`、`.env` 與憑證檔——比照 `$HOME` 之外的路徑處理：`read_files`、`edit_file`、`open_file`、`find_files`、`file_history`，以及帶 `save_to` 的 `fetch_page`，在碰觸前都會升起需密碼驗證的確認。該集合為 `sensitive_path`（`dirs` / `files` / `prefixes` / `extensions`），編譯進執行檔並與 `config.json` 中的使用者項目合併。此防護由 Go 強制，非基於 prompt。
