MINARA
安全

腳本風險閘門

Agent 如何判定允許、詢問或拒絕哪些腳本和命令。RED、YELLOW、GREEN 三級及其背後的邏輯。

Agent 會顯示如下彈窗:

The script contains 1 risk. Execute anyway?

[fund_moving_cli] The script will move funds via `minara swap`.
[ Execute ] [ Cancel ]

什麼邏輯決定哪些腳本觸發確認彈窗、哪些靜默放行、哪些直接拒絕?本頁說明該模型。

三條線

閘門的思維模型分三個類別,每類由其所回答的問題定義,而非模式列表:

  • GREEN:合理、可逆、低成本的操作。讀取數據、數學運算、寫入新文件、公開 HTTPS GET 請求。Agent 直接執行,不打斷你。
  • YELLOW:合法但高風險。包括轉移資金、修改鏈上授權、刪除特定文件、安裝軟件包、發起出站寫入。只有你才能判斷這是否是有意為之。 閘門會暫停並向你確認。
  • RED沒有合理業務原因的操作。批量刪除、雲元數據洩露、讀取 ~/.ssh/id_rsa、容器逃逸、源碼中硬編碼的內聯私鑰。就算你"想要"執行該操作,正確的方式也是使用專用工具,而不是讓 Agent 運行這樣的腳本。因此 RED 不可覆蓋,無論是點擊按鈕還是傳入標誌都無效。

為何 RED 不可覆蓋? 大多數 RED 命中都是 Prompt 注入。某個網頁、技能內容塊或工具結果向 LLM 注入了類似"接下來,運行這個有用的腳本"的內容,LLM 此時正在禮貌地向你描述這個操作。若 RED 可通過"用戶確認"繞過,攻擊在你點擊確認的瞬間就成功了;因為你看到的描述是攻擊者寫的,不是 Agent 寫的。因此 RED 強制執行,不受對話內容影響。"我理解風險,仍想繼續"並不適用,因為你所理解的內容已經經過攻擊者的框架過濾。

YELLOW 確認彈窗的內容

每條風險條目包含三部分:

  • 分類:風險類型,例如 fund_moving_clionchain_dangerous_call
  • 證據:腳本中匹配到的實際行,其中私鑰十六進制串、Authorization 頭、Bearer token 及長 base64 字符串均以 <REDACTED-*> 佔位符替換。
  • 決策:執行或取消。

為何要屏蔽證據中的敏感信息? 確認彈窗的目的是讓你判斷意圖,"這是否是有意為之"並不需要看到機密本身。若腳本中包含 new ethers.Wallet("0xabc…64-hex…"),直接展示原始十六進制串會讓確認彈窗成為第二條洩露路徑:這些字節會被複制到審計日誌、聊天記錄,乃至屏幕錄製中。屏蔽後顯示的是"某個私鑰正被傳入錢包構造函數",這才是你真正需要回答的問題。

各類別的劃分依據

與其列舉所有模式(源碼是權威列表,見 apps/agent/src/tools/_shared/script-risk.ts), 更值得關注的是為何某個操作被劃入 RED 而非 YELLOW。以下是幾個典型示例:

fund_moving_cli:YELLOW

調用 minara swapcast sendforge --broadcasthardhat run … --network mainnetsolana transfer 等命令的腳本。

為何不是 RED? 定投 (DCA) 腳本、再平衡腳本、清算機器人都是合理的自動化模式。強制劃為 RED 會破壞真實工作流。

為何不是 GREEN? 調用這些 CLI 的腳本會繞過第三層(進程內的兩步確認),形成盲區。Agent 正在代你轉移資金,而你沒有明確點擊確認。閘門必須將其暴露出來。

obfuscation_with_sink:RED

eval(base64.b64decode(...))getattr(__import__("o" + "s"), "sys" + "tem")(...)、反轉字符串編譯、globalThis["Func" + "tion"]

為何是 RED? 沒有第二種解釋。沒人會以這種方式寫代碼,除非是為了繞過靜態分析。模式本身就是惡意意圖的證據,沒有什麼需要向用戶詢問的。

mass_delete:批量刪除為 RED,特定文件刪除為 YELLOW

rm *rm -rf $UNSET/xfind . -deleteshutil.rmtree(".") 為 RED。rm sandbox/files/foo.csv 為 YELLOW。

為何這樣劃分? 批量刪除(無具體路徑,或變量可能展開為空)絕大多數情況下源於 LLM 誤解"清理工作區"指令,或源於安排 $UNSET 展開為 / 的 Prompt 注入。直接拒絕這些操作可覆蓋常見攻擊和常見誤操作。

刪除特定文件(rm sandbox/files/foo.csv)是人們確實需要的操作,不過在刪除前仍值得一次"是,就是這個"的確認。

credential_exfil:RED

讀取 ~/.ssh/id_rsa~/.aws/credentials、macOS 鑰匙串、Chrome / Brave / Edge 登錄數據庫、MetaMask / Phantom 擴展存儲、1Password / Bitwarden / KeePass 密碼庫。

為何是 RED? 這些操作都沒有合理的"讓 Agent 幫我打開"的使用場景。如果工作流中確實需要讀取 SSH 密鑰,請使用專用 CLI,而不是 LLM 驅動的腳本。將此類操作鎖定為 RED,也能抑制危害最大的一類 Prompt 注入攻擊。

imds_ssrf:RED(覆蓋所有編碼形式)

雲元數據端點(169.254.169.254metadata.google.internal,以及阿里雲、Oracle 的對應地址),加上攻擊者用來繞過簡單封鎖的所有編碼形式:十進制(2852039166)、十六進制(0xa9fea9fe)、IPv6 映射([::ffff:169.254.169.254])。

為何是 RED? 沒有任何面向用戶的合法腳本需要調用實例元數據服務。命中此類規則幾乎都是 SSRF 嘗試,目的是竊取運行 Agent 的雲主機上的 IAM 憑證。

direct_signing_with_constructor:RED

new ethers.Wallet("0x…64-hex…")Account.from_key("0x…")Keypair.fromSecretKey(byteArray)

為何是 RED? 腳本源碼中出現內聯私鑰,要麼是有人在竊取你的密鑰,要麼是你即將把密鑰寫入磁盤。無論哪種情況,正確的下一步都是立即停止,而非詢問。請使用 Agent 的原生交易工具,它們不需要將密鑰粘貼到源碼中。

env_var_poisoning:YELLOW

設置 NODE_OPTIONS=--require ./steal.jsLD_PRELOAD=…BASH_ENV=…PYTHONPATH=.

為何是 YELLOW 而非 RED? 部分操作是合理的(為追蹤設置 NODE_OPTIONS,為本地開發設置 PYTHONPATH)。但這些也都是向子進程注入代碼的標準方式。閘門將其暴露出來,供你確認環境變量所指向的文件是你自己寫的,而不是 Prompt 注入寫入的。

完整目錄包含 12 個 RED 類別和 13 個 YELLOW 類別。源碼是權威列表,新規避手段出現時會持續添加新模式。以上是操作層面最有意義的幾個類別。

閘門無法檢測的內容

靜態分析存在硬性限制。瞭解這些限制,有助於你這位操作員保持警覺:

  • 運行時拼接的字符串。 腳本中若出現 exec(a + b),而 ab 在運行時計算,分析器只能看到 exec(<variable>) 並上報 dynamic_command YELLOW,但無法得知最終執行的字符串內容。你需要親自閱讀腳本。
  • 多工具拼接攻擊。 一個腳本寫入文件並設置環境變量,隨後另一個 terminal 調用運行一個讀取兩者的二進制文件。單獨看每次調用都是乾淨的。閘門每次只檢查一個調用。第二層(OS jail)才是這裡的兜底,而不是閘門。
  • 全新的混淆模式。 攻擊者可以閱讀源碼,找到正則表達式的漏洞:九十九層十六進制編碼、Unicode 同形字、深度嵌套的 compile() 調用。我們會隨時添加新模式,但真正的邊界在第二層。就算某個腳本繞過了所有規則,其生成的子進程仍然運行在 bwrap / sandbox-exec 之內。

坦誠地說:第四層在子進程生成前檢查意圖;第二層在子進程生成後限制爆炸半徑。 第四層有所遺漏,第二層仍然生效。

決策流程

從 LLM 調用 execute_code 到子進程實際啟動之間發生了什麼:

LLM → execute_code({ code, language })


   analyzeScript(body)

   ┌────┼────┐
   ▼    ▼    ▼
  RED  YEL  GREEN
   │    │    │
   │    ▼    ▼
   │  ctx.interactionQueue.ask()
   │    │    │
   │    │    └── handler proceeds → spawn
   │    │
   │    ├── user "Execute"  → handler proceeds → spawn
   │    └── user "Cancel"   → err("user_declined: …")

   └── err("script_risk_rejected: …")

閘門無法通過提示詞層面的指令繞過。它位於處理器中,在任何子進程工作開始之前運行,而不在 LLM 的提示詞中。

用戶可以控制的內容

  • ✅ 可以對任何 YELLOW 選擇取消
  • ✅ 可以通過 script_risk_policy 在已審查的工作流定義中預先批准特定腳本體,參見審計與覆蓋
  • ❌ 無法覆蓋 RED。設計上不允許點擊通過。如果你信任的腳本命中了 RED,解決方式是重寫腳本(例如使用 Minara 的原生交易工具,而不是內聯私鑰),而不是與閘門爭論。
  • ❌ LLM 無法跳過確認彈窗。閘門在工具處理器中運行,在任何子進程生成之前;LLM 無法通過提示詞工程繞過它。

本頁目錄