主題: Cloudflare

Cloudflare OS 真正值得抄的不是 UI,而是把 Agent 權限歸零

Cloudflare OS 提供了一個實用的 agent app 安全模式:隔離生成程式碼、移除 ambient authority、只授予窄能力,side effect 另行審核。

動態迷因(展開/收合)
Sandbox 把程式碼鎖在房間裡;capability design 決定哪些鑰匙能進入房間。 · 來源:GIPHY

「把 AI 生成的程式碼放進 sandbox」聽起來很負責任。這確實必要,但只回答了一個問題:程式碼能不能逃離執行環境?

它沒有回答另一個更常出事的問題:放進環境裡的 API、credentials、storage 與 tools,程式碼原本就有權做什麼?

Cloudflare 最近開源了 Cloudflare OS,這套內部 AI workspace 能讓 agent 建立稱為 Gadget 的小型應用。近期 Reddit 討論主要注意到 isolated runtime、real-time state 與 agent-generated apps。這些都很有趣,但真正能帶回自己系統的觀念更安靜:

生成程式碼預設不該擁有任何 ambient authority。每次只給它完成任務所需、無法偽造的窄 capability;secrets 與最終授權留在 sandbox 外。

這比把一把強力 API key 放進 container,然後因為 container「有隔離」就放心,多了一層真正有用的安全邊界。

Cloudflare OS 是 reference architecture,不是新桌面 OS

Repo 把 Cloudflare OS 定義成 AI productivity environment,不是傳統作業系統。它組合了 agent chat、sandboxed personal apps,以及名為 Gatekeepers 的安全層。

每個 Gadget 的 server component 跑在 Dynamic Worker,client code 放在 sandboxed iframe;Durable Objects 保存各 Gadget 的 state 與多人協作;Cap’n Web RPC 串起各部分,並暴露 client 與 agent 都能呼叫的 API。

這是目前可執行的程式碼,但 repo 同時把 2026 年 8 月的 v2 標示為 early access,明說仍有 rough edges 與未完成的部署細節。把它當成值得研究的設計,不要當成已替你解完所有難題的 production platform。

這套設計把四件事拆開:

邊界 工作 限制的失敗
Sandbox 隔離生成程式碼與 resource usage Runtime escape 與 host damage
Capability 只暴露指定 resource 與 operation Excessive permissions 與 data access
Gatekeeper 授權、稽核並暫存 side effect Excessive autonomy
Durable state 保存 app state 與 pending work 中斷後遺失或重複工作

如果全部縮成一個「agent 可以用 tools」的開關,就會產生 ambient authority:當前任務明明不需要,所有 tool 與 credential 卻一直默默待命。

Sandbox 限制程式碼,不定義權限

Dynamic Workers 能把 runtime 提供的程式碼載入獨立 V8 isolate。Loader 控制 bindings、network access、observability 與 resource limits。對短小 TypeScript automation 而言,它比啟動 Linux container 輕很多。

Cloudflare 的 egress-control 文件直接給出安全預設:把 globalOutbound 設成 null,再逐一加入 workload 真正需要的 capabilities。

簡化後的 loader 大致是:

const worker = env.LOADER.load({
  mainModule: "agent.js",
  modules: { "agent.js": generatedCode },
  globalOutbound: null,
  env: {
    REPOSITORY: readOnlyRepository,
  },
  limits: {
    cpuMs: 20,
    subRequests: 10,
  },
});

生成程式碼不能任意連網。它只拿到一個 repository capability,不會拿到 GitHub token、generic shell,也不會自動繼承 parent application 設定過的所有 integrations。

Sandbox 仍然重要:正常 runtime API 無法碰觸 process memory、host file system 或其他無關資源。但如果 REPOSITORY 對每個任務都暴露 deleteRepository(),再好的 isolation 也救不了 repository。那是 authorization bug,不是 sandbox escape。

綁定 method,不要交出 secret

Cloudflare 的 Dynamic Workers bindings採用 capability model。Parent Worker 把 RPC stub 傳進 sandbox;沒有拿到 stub 的 Dynamic Worker,既找不到也無法偽造那個 object 的存取權。

這會直接改變 API design。不要把這個交給生成程式碼:

GITHUB_TOKEN=token_with_repo_scope

應該給它一個只符合任務形狀的 interface:

interface RepositoryReader {
  listFiles(path: string): Promise<string[]>;
  readFile(path: string): Promise<string>;
}

Implementation 留在 sandbox 外,負責附加 credentials、限制 repository 與 path、驗證當前使用者、rate limit,並記錄 audit event。Model 看得到 methods,看不到 secret。

這不只是把 environment variable 藏好。Broad token 一旦外洩,在撤銷前能從任何地方 replay;narrow RPC stub 沒有 global identifier、無法偽造,而且每次呼叫都會回到你控制的 policy code。

若既有 library 必須走 HTTP,Cloudflare 的 egress gateway 也能採用相同模式:攔截 outbound request、只允許指定 destination,並等 request 離開 sandbox 後才注入 credential。生成程式碼提出資源請求,永遠不經手用來授權的秘密。

Resource introduction 比全域 tools 更安全

Cloudflare OS 不會把已設定的每個 external account 自動交給每個 Gadget。使用者必須把一份指定資源,例如某一個 repository,介紹給某個 agent 或 app。

這正好修正常見 MCP setup 的盲點。把十個 servers 全域設定好很方便,卻會默默把巨大 capability surface 交給每段 conversation。Tool search 能讓 model context 少看到一些 schemas,不會移除底層 authority。

一份夠強的 grant 應回答五個問題:

  1. Agent 正代表執行?
  2. 能存取哪一份資源
  3. 允許哪些 operations
  4. Grant 多久後失效
  5. 哪些 calls 必須另外批准?

「可以用 GitHub」不是有用答案;「這個 task 結束以前,只能讀 repository X 的 /docs」才是。

這與 OWASP Excessive Agency guidance一致:縮小 tool functionality、permissions 與 autonomy;用目前使用者的 context 執行;high-impact action 要有人類批准。Model 再聰明也不會消滅這項需求,因為惡意指令仍可能來自 email、web page 或 tool result。

Approval 應該是一筆 proposed transaction

Cloudflare OS Gatekeepers 包裝 external service、處理授權、縮小 resource 範圍、記錄 calls,並要求 side effect 先核准。它較實驗性的設計是 asynchronous approval:先模擬 write,讓 agent 用模擬結果繼續跑,最後再讓使用者審核 queued actions。

這比喝完咖啡回來,發現 agent 卡在第一步 approval 實用。它也遠比多一顆「Approve all」按鈕複雜。

動態迷因(展開/收合)
好的 approval 會寫清楚 resource 與 action,不會要求永久存取所有東西。 · 來源:GIPHY

把 simulated side effect 當成 proposed transaction,不是完成的事實。一個可靠 queue 至少需要:

  • 精確 operation、arguments、actor、resource 與 policy version。
  • 不受不可信內容控制的 preview。
  • Proposals 之間的 dependency,拒絕第一步時,依賴它的後續步驟一起失效。
  • 執行前 expiration 與 revalidation。
  • Idempotency key 或其他防止重複執行的方法。
  • 清楚分開 simulated state 與 committed external state。

不要讓 agent 自己畫 approval summary。OWASP 已把 approval-dialog forging列為真實 attack surface:惡意內容可能把危險操作包裝得很無害。Policy layer 應從 validated structured data 產生給人看的 diff。

一組 coherent、reversible 的 batch 適合 bulk approval。寄信、發布內容、移動金錢、修改 IAM 或刪資料則需要更窄的 review,因為真實世界不一定能隨 local simulation 一鍵 rollback。

Isolation 還需要 budgets 與 evidence

Agent loop 即使不傷資料,也可能很貴、很吵。Cloudflare 允許 loader 套用 per-invocation CPU 與 subrequest limits。這些 controls 應和 capability grants 放在一起:

authority budget  = methods + resources + time
compute budget    = CPU + subrequests + retries
evidence trail    = inputs + capability calls + approvals + results

Dynamic Worker logs 不會自動變成 durable audit trail。官方 observability guidance使用 Tail Workers,在 execution 後接收 logs、exceptions 與 request metadata。只保存需要的 security events、遮蔽 secrets 與 private content,並附上穩定的 task 或 proposal ID。

Logs 本身不是 authorization;它只負責在 policy 決定是否允許後,解釋發生了什麼。

實際導入順序

不必部署 Cloudflare OS,也能借走它最強的模式。

  1. 盤點 agent 現在能碰到的所有 tool、credential、network destination 與 storage binding。
  2. 移除 ambient access;每個 task 從沒有 external capability 開始。
  3. 把 resource 包成綁定當前 user 與 object 的 narrow interface。
  4. Credentials 留在 generated code 外,只由 audited gateway 注入。
  5. 把 reads、reversible writes 與 irreversible actions 分成不同 policy class。
  6. 替 CPU、subrequests、retries 與 task lifetime 設 explicit budgets。
  7. 記錄 structured capability calls 與 approval decisions,但不記錄 secrets。
  8. 分別測試來自 user input、retrieved document、web page 與 tool result 的 prompt injection。

需要完整 Linux toolchain 或 native binary 時,使用 hardened container 或 microVM。Workload 只是呼叫 narrow typed API 的短 script 時,Dynamic Worker isolate 可能更快、更便宜。不論哪種 runtime,capability boundary 都應保留。

結論:先移除權限,再增加智慧

Cloudflare OS 最有意思的地方,不是 agent 又能生成一個小 app;這類 demo 已經很多了。

真正值得抄的是把 generated software 當成 untrusted tenant code:隔離執行、預設禁止連網、只給 object-specific capability、secrets 留在外面、限制工作 budget,危險 side effect 則交給獨立 review。

Sandbox 回答「這段程式碼能在哪裡跑」;capability design 回答「它有權做什麼」。Agent system 兩個都需要,而第二個問題通常才決定真正的 blast radius。


外部參考資料