Files
Arcrun/.agents/specs/data-exfil-warning/design.md
T
Leo 3e92d4acf6 feat(data-exfil-warning): 資料外流警示 — 暴露動作需人類明示同意
新 SDD .agents/specs/data-exfil-warning/(richblack review 過)。
觸發策略:只在「資料變成可被外部呼叫」時警示(webhook 部署 / recipe push),
不管出站打別人 API(高頻低風險)。

- C 同意憑證(exposure-consent.ts):ExposureConsent{confirmed_by_human, understood,
  confirmed_at, suppress_future};同意=法律憑證,存 record 可審
- A API 層:webhook 部署 + recipe push 首次需 consent,缺→403;首次問記住(server 端)
- B CLI(exposure-warning.ts):仿 GCP 刪 project,要打資源名確認(比 y/n 硬);
  --confirm-exposure(非互動)/ --suppress-warning(不再警示,本選擇也 log);
  非 TTY 無旗標→拒絕(AI 不替人類確認暴露);本機 config 記住已同意(不重問)
- H hook:pre-bash 偵測 acr push/recipe push 無旗標→exit 2(creds push/run 不誤擋)
- 警示是「保護措施入口」:提示 arcrun 可幫加認證/權限/限流(資安優勢)

驗收:非 TTY 拒絕未送出(exit1)、hook 精準擋放、tsc 雙邊綠。

⚠️ A+B 必須一起 deploy(API 層擋 + CLI 帶 consent),否則 push 中間狀態壞。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 14:45:43 +08:00

118 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Design: 資料外流警示(Data Exfiltration Warning
> 2026-05-30。實作 requirements.md。**本 design 需 richblack review 後才動 code。**
> 觸發策略(richblack 定):**只在「資料變成可被外部呼叫」時問**(暴露面),不管「我去打別人 API」(出站,高頻低風險)。
---
## 0. 核心定義:什麼是「資料變成可被外部呼叫」
警示的觸發點 = 一個動作**讓某份資料 / 能力變成「別人能呼叫得到」**。這是真正的裸奔動作。
**不觸發**:「我自己的 workflow 去打別人的 API」(出站)——那是我主動用別人服務,不是把我的東西開放出去。
### 哪些動作屬於「變成可被外部呼叫」(要警示)
| 動作 | 為何是暴露 |
|---|---|
| 部署 webhook trigger`acr push` workflow → 可被 POST 觸發) | workflow 變成一個對外可呼叫的 endpoint。誰打它就能跑它、拿它的輸出 |
| recipe 貢獻到公共庫(未來飛輪項) | recipe(含 endpoint 設定)變成全生態可見可用 |
| 把 workflow / recipe 的可見性改為 public(若未來有此欄位) | 同上 |
### 哪些動作**不**觸發(避免盲目按 yes)
- `acr run`(本機跑,不暴露)
- `acr recipe push`(存私人 KV,綁 api_key,只有自己 + 自己的 workflow 用——**不是**對外暴露)
- ⚠️ 待 design review 確認:recipe push 現況是私人的,**不暴露**。除非未來加「公共」旗標才觸發。
- workflow 裡「打別人 API」的 http 節點(出站,不暴露我的資料給別人呼叫)
- 查詢類、creds push(上傳加密 credential 是保護不是暴露)
### 灰色地帶(design review 要定)
- **webhook trigger 現況**:要 `X-Arcrun-API-Key`(owner 的 key)才能打 → 嚴格說「只有我能打」,不算對全世界暴露。
但:(a) key 一旦外流就全開;(b) 用戶可能不知道「部署 webhook = 開了一個 endpoint」。
**是否警示 webhook 部署?** 傾向「是」,因為用戶可能不知情它變成 endpoint,且這是「把 workflow 變 API」的那一步(richblack 最早的風險點)。
## 1. 兩道防線
### 1a. hook(防在前,AI 動手當下)
AI 在本機寫「會變成可被外部呼叫的東西」前,hook 警告 + 要人類確認。可偵測的訊號:
- 寫 workflow YAML 含 webhook trigger / 對外觸發設定。
-`acr push`(部署 webhook)、未來的 recipe 公共貢獻指令。
- pre-bash / pre-write hook 偵測這些 → 輸出警示「這會把 X 變成可被外部呼叫,需人類確認」。
- **誠實限制**:hook 偵測的是「動作形態」(部署 webhook),不是「資料是否敏感」(機器判不準)。
### 1b. API 層(防在後,真的暴露前)
暴露動作打到 serverwebhook 部署 endpoint / 未來公共貢獻 endpoint)時,server 要求帶
「人類已確認暴露」的明示旗標,沒帶 → 拒絕 + 提示。與 component-gatekeeping 的 human_confirmation 同模式:
```ts
exposure_confirmation?: {
confirmed_by_human: true;
understood_exposure: string; // 人類說明「我知道這會把什麼開放給誰」
confirmed_at: string;
}
```
缺 → 拒絕,訊息:「部署 webhook = 開一個對外可呼叫的 endpoint。確認你知道這會暴露 [workflow 名]
的能力/輸出?用 `acr push --confirm-exposure` 並說明。」
### 為何兩道都要
- 只有 hookAI 可繞過 CLI 直接打 server API → API 層補。
- 只有 API 層:AI 已經寫好暴露的東西才在送出時被擋,浪費 + 用戶較晚看到 → hook 提前。
- 同 component-gatekeeping 的雙層精神。
## 2. 警示要讓人看得懂(R1
不是「確認嗎 Y/N」,是說清楚風險:
```
⚠️ 這個動作會把 workflow "contacts_lookup" 變成可被外部呼叫的 endpoint:
https://cypher.arcrun.dev/webhooks/named/contacts_lookup/trigger
任何持有觸發憑證的人都能呼叫它、取得它的輸出。
這個 workflow 讀取:[盤出 workflow 用到的資料源,若可得]
需要保護(要求呼叫者認證)嗎?目前的觸發認證是:[現況]
確認部署?(需人類明示)
```
- 「workflow 讀取什麼資料源」:盡力從 workflow 定義盤(用了哪些 recipe / endpoint),盤不出就標「無法自動判斷,請自行確認」。誠實。
## 3. known-destinations / 不重複問(R4 避免盲目按 yes)
觸發策略已經很窄(只暴露動作),但同一個 workflow 重複部署不該每次問。
- 首次部署某 workflow 為 webhook → 問。人類確認後記住(該 workflow 標記 exposure-confirmed)。
- 之後同 workflow 更新 → 不重問(除非暴露面變大,如新增對外觸發)。
- 記在哪:workflow metadataWEBHOOKS KV 的 record 加 `exposure_confirmed_at`)。
## 4. 與既有一致(R5
- 同 component-gatekeepingAI 不可替人類決定有外洩風險的動作;誠實限制(AI 能偽造 confirmed_by_human,靠軌跡可審 + mindset)。
- 同「arcrun 不做授權判斷」:不判斷「該不該暴露」,只「攔下來讓人類明示同意」。不禁止暴露,要明示同意。
## 5. 範圍邊界
- **動**webhook 部署路徑(webhooks-named.ts)的 exposure_confirmation + CLI `acr push --confirm-exposure` 互動 + hook。
- **不動**:用戶 API 入站保護機制(發 key/權限/限流,另列 BACKLOG);recipe 私人 push(不暴露,不擋);出站 http 節點(不擋)。
- recipe 公共貢獻路徑未實作 → 本系統只要求它**未來**內建 exposure 閘門(記進那條 BACKLOG 項)。
## 6. 決議(richblack 2026-05-30 design review
- **Q1 → recipe push 也警示,公私一視同仁。** 不是因為 recipe 本身暴露,而是統一原則「凡有資料去向/暴露面的動作都警示」。用戶可選「以後不要警示」(記偏好)。理由見 §7 同意 log。
- **Q2 → webhook 部署要警示,但角度是「提醒 + 提供保護」不是「擋」。** 用不用認證是用戶決定(如美國氣象 API 本就無 key 公開)。我們警示時**順便提醒「可用 arcrun 提供的保護措施」**(接「用戶 API 保護機制」資安優勢,BACKLOG 待決策)。首次問、記住(§3)。
- **Q3 → hook 偵測 `acr push` 指令**(簡單版,pre-bash 攔指令)。
## 7. 同意 = 法律憑證(richblack 2026-05-30,重要)
每次人類同意「暴露/送資料」的動作,**留 log(誰、何時、同意了什麼)**。這不只是「軌跡可審」,是**法律保護**:
- 真發生資料外洩 / 糾紛時,有「用戶在 [時間] 明示知情同意把 [什麼] 暴露給 [誰]」的證據 → 避免訴訟風險(責任在明示同意的用戶,不在 arcrun)。
- 「以後不要警示」這個選擇**本身也要 log**(用戶在 [時間] 選擇了不再對 [X] 警示 = 他知道風險並接受)。
- 同意 log 存放:與動作關聯(webhook record / recipe record 的 `exposure_consent: { confirmed_by, understood, confirmed_at, suppress_future }`)。
- 誠實限制同前:AI 能偽造 confirmed_by_human。但**法律意義上,憑證存在 + 可審 = 用戶有機會知情**,這道防線的價值是法律歸責不是技術防偽。
→ 這把 §1b 的 `exposure_confirmation` 升級為**帶法律意義的同意憑證**,所有暴露/送資料動作(recipe push / webhook 部署)共用此機制。
## 8. 警示是「保護措施的入口」(不只是攔)
警示訊息除了說明風險,**主動提供 arcrun 的保護措施**(產品價值,非只防呆):
```
⚠️ 這個動作會把 [X] 開放/送出。
arcrun 可以幫你保護它:
- 要求呼叫者帶 API Key(你發給特定對象)
- 設定權限 / 限流
一個動作就能加上。要加保護嗎?還是確認公開(如公開資料 API)?
```
(具體保護機制是 BACKLOG「用戶 API 保護機制」待決策項——本系統先在警示處**提示它存在**,實作後接上。)