Section: Using Hermes · URL: https://hermesbible.com/docs/user-guide/security
Hermes Agent 採用縱深防禦的安全模型。本頁涵蓋每一個安全邊界——從指令審核、容器隔離到訊息平台的使用者授權。
概覽
安全模型共有七個層級:
- 使用者授權 — 誰可以與 Agent 對話(白名單、DM 配對)
- 危險指令審核 — 破壞性操作需人工介入確認
- 容器隔離 — Docker / Singularity / Modal 沙箱並強化安全設定
- MCP 憑證過濾 — MCP 子程序的環境變數隔離
- 情境檔案掃描 — 專案檔案中的提示注入偵測
- 跨 Session 隔離 — Session 之間無法存取彼此的資料或狀態;排程任務的儲存路徑已強化以防路徑遍歷攻擊
- 輸入淨化 — 終端工具後端的工作目錄參數會通過白名單驗證,防止 Shell 注入
危險指令審核
執行任何指令之前,Hermes 會比對一份精心整理的危險模式清單。若偵測到相符的模式,使用者必須明確批准。
審核模式
審核系統支援三種模式,透過 ~/.hermes/config.yaml 中的 approvals.mode 設定:
approvals:
mode: manual # manual | smart | off
timeout: 60 # 等待使用者回覆的秒數(預設:60)
cron_mode: deny # deny | approve — 排程任務遇到危險指令時的行為
mcp_reload_confirm: true # /reload-mcp 在使 MCP 工具快取失效前先詢問
destructive_slash_confirm: true # /clear、/new、/reset、/undo 在捨棄狀態前先提示
完整的設定鍵值:
| 鍵值 | 預設值 | 控制項目 |
|---|---|---|
mode | manual | 危險 Shell 指令的審核策略 — 詳見下方表格。 |
timeout | 60 | Hermes 等待審核回覆的秒數,逾時即超時。 |
cron_mode | deny | 排程任務 在無人值守環境下觸發危險指令提示時的行為。deny 會阻止該指令(Agent 必須另尋出路);approve 則在排程情境中自動批准所有指令。 |
mcp_reload_confirm | true | 設為 true 時,/reload-mcp 會在重建 MCP 工具集前先詢問。重建會使供應商的提示快取失效(工具 schema 存在於系統提示中),因此下一則訊息會重新傳送完整的輸入 token。使用者點選 Always Approve 會將此鍵值翻轉為 false。 |
destructive_slash_confirm | true | 設為 true 時,破壞性的 Session 斜線指令(/clear、/new、/reset、/undo)會在捨棄對話狀態前先提示。三選一對話框(僅批准一次 / 總是批准 / 取消)在 Telegram、Discord 和 Slack 上透過原生是/否按鈕路由;其他平台則使用文字回退。使用者點選 Always Approve 會將此鍵值翻轉為 false。TUI 使用自己的模態覆蓋層(設定 HERMES_TUI_NO_CONFIRM=1 可在此處跳過確認)。 |
| 模式 | 行為 |
|---|---|
| manual(預設) | 危險指令一律提示使用者批准 |
| smart | 使用輔助 LLM 評估風險。低風險指令(例如 python -c "print('hello')")會自動批准。真正危險的指令會自動拒絕。不確定的情況會升級為手動提示。 |
| off | 停用所有審核檢查 — 相當於使用 --yolo 執行。所有指令不經提示即執行。 |
WARNING
設定
approvals.mode: off會停用所有安全提示。僅在受信任的環境(CI/CD、容器等)中使用。
YOLO 模式
YOLO 模式會繞過當前 Session 中所有危險指令審核提示。可透過三種方式啟用:
- CLI 旗標:使用
hermes --yolo或hermes chat --yolo啟動 Session - 斜線指令:在 Session 中輸入
/yolo來切換開/關 - 環境變數:設定
HERMES_YOLO_MODE=1
/yolo 指令是一個切換開關 — 每次使用都會翻轉模式的開或關:
> /yolo
⚡ YOLO mode ON — all commands auto-approved. Use with caution.
> /yolo
⚠ YOLO mode OFF — dangerous commands will require approval.
YOLO 模式在 CLI 和 Gateway Session 中皆可使用。內部運作是設定 HERMES_YOLO_MODE 環境變數,在每次指令執行前進行檢查。
當 YOLO 啟用時,Hermes 會顯示兩個持續性的視覺提醒,讓你很難忘記審核提示已被繞過:
- Session 開始時若 YOLO 已啟用,會出現紅色橫幅:
⚠ YOLO mode — all approval prompts bypassed。YOLO 關閉時隱藏,以保持預設橫幅的整潔。 - 在所有寬度層級的狀態列中顯示
⚠ YOLO片段,切換 YOLO 時即時更新(富文字渲染器和純文字回退)。
DANGER
YOLO 模式會在 Session 期間停用所有危險指令安全檢查——除了硬性封鎖清單(見下方說明)。僅在你完全信任所產生的指令時使用(例如在一次性環境中使用經過充分測試的自動化腳本)。
對於破壞性的 Session 斜線指令(/clear、/new / /reset、/undo、/quit --delete — /exit --delete 為別名),CLI 也會在執行前提示確認。詳見斜線指令 — 破壞性指令的確認提示。
硬性封鎖清單(始終啟用的底線)
某些指令造成的後果太過嚴重——不可逆的檔案系統擦除、fork bomb、直接寫入區塊裝置——因此 Hermes 會無論如何都拒絕執行它們:
--yolo//yolo已切換開啟approvals.mode: off- 排程任務以無人值守的
approve模式運行 - 使用者明確點選「永遠允許」
封鎖清單是 --yolo 之下的底線。它在審核層甚至看到指令之前就會觸發,且沒有可覆蓋的旗標。目前包含的模式(非詳盡清單;與 tools/approval.py::UNRECOVERABLE_BLOCKLIST 同步維護):
| 模式 | 為什麼被列為硬性封鎖 |
|---|---|
rm -rf / 及其明顯變體 | 擦除檔案系統根目錄 |
rm -rf --no-preserve-root / | 明確表示「我就是要刪除根目錄」的變體 |
:(){ :|:& };:(bash fork bomb) | 會使主機癱瘓直到重新開機 |
mkfs.* 作用於已掛載的根裝置 | 格式化正在執行的系統 |
dd if=/dev/zero of=/dev/sd* | 將實體磁碟歸零 |
將不受信任的 URL 透過管道傳給根檔案系統頂層的 sh | 遠端程式碼執行攻擊向範太廣,無法批准 |
如果觸及封鎖清單,工具呼叫會回傳解釋性的錯誤給 Agent,什麼都不會執行。如果合法的工作流程需要這些指令(例如你是擦除並重新安裝管線的營運人員),請在 Agent 之外執行。
審核逾時
當危險指令提示出現時,使用者有可配置的時間來回應。若逾時內未回應,指令預設會被拒絕(預設為安全失敗)。
在 ~/.hermes/config.yaml 中配置逾時:
approvals:
timeout: 60 # 秒(預設:60)
什麼會觸發審核
以下模式會觸發審核提示(定義於 tools/approval.py):
| 模式 | 說明 |
|---|---|
rm -r / rm --recursive | 遞迴刪除 |
rm ... / | 在根路徑中刪除 |
chmod 777/666 / o+w / a+w | 全域/其他人可寫權限 |
chmod --recursive 搭配不安全權限 | 遞迴全域/其他人可寫(長旗標形式) |
chown -R root / chown --recursive root | 遞迴 chown 至 root |
mkfs | 格式化檔案系統 |
dd if= | 磁碟複製 |
> /dev/sd | 寫入區塊裝置 |
DROP TABLE/DATABASE | SQL DROP |
DELETE FROM(無 WHERE) | 無 WHERE 的 SQL DELETE |
TRUNCATE TABLE | SQL TRUNCATE |
> /etc/ | 覆寫系統設定 |
systemctl stop/restart/disable/mask | 停止/重啟/停用系統服務 |
kill -9 -1 | 終止所有行程 |
pkill -9 | 強制終止行程 |
| Fork bomb 模式 | Fork bomb |
bash -c / sh -c / zsh -c / ksh -c | 透過 -c 旗標執行 Shell 指令(包括 -lc 等組合旗標) |
python -e / perl -e / ruby -e / node -c | 透過 -e/-c 旗標執行腳本 |
curl ... | sh / wget ... | sh | 將遠端內容透過管道傳給 Shell |
bash <(curl ...) / sh <(wget ...) | 透過程序替換執行遠端腳本 |
tee 寫入 /etc/、~/.ssh/、~/.hermes/.env | 透過 tee 覆寫敏感檔案 |
> / >> 寫入 /etc/、~/.ssh/、~/.hermes/.env | 透過重新導向覆寫敏感檔案 |
xargs rm | xargs 搭配 rm |
find -exec rm / find -delete | find 搭配破壞性操作 |
cp/mv/install 到 /etc/ | 複製/移動檔案到系統設定目錄 |
sed -i / sed --in-place 作用於 /etc/ | 就地編輯系統設定 |
pkill/killall hermes/gateway | 自我終止防護 |
gateway run 搭配 &/disown/nohup/setsid | 防止在服務管理器外啟動 Gateway |
INFO
容器繞過:在
docker、singularity、modal或daytona後端運行時,危險指令檢查會被跳過,因為容器本身就是安全邊界。容器內的破壞性指令無法傷害主機。
審核流程(CLI)
在互動式 CLI 中,危險指令會顯示行內審核提示:
⚠️ DANGEROUS COMMAND: recursive delete
rm -rf /tmp/old-project
[o]nce | [s]ession | [a]lways | [d]eny
Choice [o/s/a/D]:
四個選項:
- once — 僅允許這次執行
- session — 在本次 Session 剩餘時間內允許此模式
- always — 加入永久白名單(儲存至
config.yaml) - deny(預設) — 阻止該指令
審核流程(Gateway/訊息平台)
在訊息平台上,Agent 會將危險指令的詳細資訊傳送到聊天中,並等待使用者回覆:
- 回覆 yes、y、approve、ok 或 go 以批准
- 回覆 no、n、deny 或 cancel 以拒絕
執行 Gateway 時,HERMES_EXEC_ASK=1 環境變數會自動設定。
永久白名單
以「always」批准的指令會儲存至 ~/.hermes/config.yaml:
# 永久允許的危險指令模式
command_allowlist:
- rm
- systemctl
這些模式在啟動時載入,並在未來所有 Session 中靜默批准。
TIP
使用
hermes config edit來檢視或從永久白名單中移除模式。
使用者授權(Gateway)
運行訊息 Gateway 時,Hermes 透過多層授權系統控制誰可以與機器人互動。
授權檢查順序
_is_user_authorized() 方法依以下順序檢查:
- 各平台全域允許旗標(例如
DISCORD_ALLOW_ALL_USERS=true) - DM 配對已核准清單(透過配對碼核准的使用者)
- 平台特定白名單(例如
TELEGRAM_ALLOWED_USERS=12345,67890) - 全域白名單(
GATEWAY_ALLOWED_USERS=12345,67890) - 全域允許全部(
GATEWAY_ALLOW_ALL_USERS=true) - 預設:拒絕
平台白名單
在 ~/.hermes/.env 中以逗號分隔設定允許的使用者 ID:
# 平台特定白名單
TELEGRAM_ALLOWED_USERS=123456789,987654321
DISCORD_ALLOWED_USERS=111222333444555666
WHATSAPP_ALLOWED_USERS=15551234567
SLACK_ALLOWED_USERS=U01ABC123
# 跨平台白名單(所有平台皆會檢查)
GATEWAY_ALLOWED_USERS=123456789
# 各平台全域允許(謹慎使用)
DISCORD_ALLOW_ALL_USERS=true
# 全域允許全部(極度謹慎使用)
GATEWAY_ALLOW_ALL_USERS=true
WARNING
若未配置任何白名單且未設定
GATEWAY_ALLOW_ALL_USERS,所有使用者都會被拒絕。Gateway 在啟動時會記錄一條警告:No user allowlists configured. All unauthorized users will be denied. Set GATEWAY_ALLOW_ALL_USERS=true in ~/.hermes/.env to allow open access, or configure platform allowlists (e.g., TELEGRAM_ALLOWED_USERS=your_id).
DM 配對系統
為了提供更靈活的授權,Hermes 內建了基於配對碼的系統。不需要事先取得使用者 ID,未知使用者會收到一組一次性的配對碼,由機器人擁有者透過 CLI 核准。
運作方式:
- 未知使用者向機器人發送私訊
- 機器人回覆一組 8 字元的配對碼
- 機器人擁有者在 CLI 上執行
hermes pairing approve <platform> <code> - 該使用者在該平台上被永久核准
在 ~/.hermes/config.yaml 中控制未授權私訊的處理方式:
unauthorized_dm_behavior: pair
whatsapp:
unauthorized_dm_behavior: ignore
pair為預設值。未授權的私訊會收到配對碼回覆。ignore會靜默忽略未授權的私訊。- 各平台區段可覆寫全域預設值,因此你可以在 Telegram 上保持配對功能,同時讓 WhatsApp 保持靜默。
安全功能(基於 OWASP + NIST SP 800-63-4 指導):
| 功能 | 詳細說明 |
|---|---|
| 碼格式 | 8 字元,取自 32 字元的明確字母表(不含 0/O/1/I) |
| 隨機性 | 密碼學級別(secrets.choice()) |
| 碼有效期 | 1 小時過期 |
| 速率限制 | 每位使用者每 10 分鐘 1 次請求 |
| 待處理限制 | 每個平台最多 3 個待處理配對碼 |
| 鎖定 | 5 次核准失敗 → 鎖定 1 小時 |
| 檔案安全 | 所有配對資料檔案設定 chmod 0600 |
| 紀錄 | 配對碼不會被記錄到標準輸出 |
配對 CLI 指令:
# 列出待處理和已核准的使用者
hermes pairing list
# 核准一組配對碼
hermes pairing approve telegram ABC12DEF
# 撤銷使用者的存取權限
hermes pairing revoke telegram 123456789
# 清除所有待處理配對碼
hermes pairing clear-pending
儲存位置: 配對資料儲存在 ~/.hermes/pairing/,每個平台一個 JSON 檔案:
{platform}-pending.json— 待處理的配對請求{platform}-approved.json— 已核准的使用者_rate_limits.json— 速率限制和鎖定追蹤
容器隔離
使用 docker 終端後端時,Hermes 會對每個容器套用嚴格的安全強化。
Docker 安全旗標
每個容器都使用以下旗標運行(定義於 tools/environments/docker.py):
_BASE_SECURITY_ARGS = [
"--cap-drop", "ALL", # 移除所有 Linux 能力
"--cap-add", "DAC_OVERRIDE", # 允許 root 寫入 bind 掛載目錄
"--cap-add", "CHOWN", # 套件管理員需要檔案所有權操作
"--cap-add", "FOWNER", # 套件管理員需要檔案所有權操作
"--security-opt", "no-new-privileges", # 阻止權限提升
"--pids-limit", "256", # 限制行程數量
"--tmpfs", "/tmp:rw,nosuid,size=512m", # 有大小限制的 /tmp
"--tmpfs", "/var/tmp:rw,noexec,nosuid,size=256m", # 不可執行的 /var/tmp
]
SETUID/SETGID 不在基本清單中——它們僅在容器以 root 啟動且 init/entrypoint 需要降權時才會條件式加入(s6 降權路徑)。當容器已透過 --user 以非 root 身分運行時則會跳過。/run tmpfs 也從基本清單中拆出,依映像掛載(預設強化為 noexec,僅對從 /run 執行的 s6-overlay 映像才使用 exec)。
資源限制
容器資源可在 ~/.hermes/config.yaml 中配置:
terminal:
backend: docker
docker_image: "nikolaik/python-nodejs:python3.11-nodejs20"
docker_forward_env: [] # 僅允許明確列出的變數;空白可防止密鑰洩入容器
container_cpu: 1 # CPU 核心數
container_memory: 5120 # MB(預設 5GB)
container_disk: 51200 # MB(預設 50GB,需在 XFS 上使用 overlay2)
container_persistent: true # 跨 Session 持久化檔案系統
檔案系統持久化
- 持久模式(
container_persistent: true):從~/.hermes/sandboxes/docker/<task_id>/bind 掛載/workspace和/root - 臨時模式(
container_persistent: false):使用 tmpfs 作為工作區——清理時所有內容都會遺失
TIP
對於生產環境的 Gateway 部署,使用
docker、modal或daytona後端將 Agent 指令與主機系統隔離。這完全消除了對危險指令審核的需求。
WARNING
若你在
terminal.docker_forward_env中加入名稱,這些變數會被有意注入到容器中供終端指令使用。這對於GITHUB_TOKEN等任務特定憑證很有用,但也代表容器中執行的程式碼可以讀取並外洩這些變數。
終端後端安全比較
| 後端 | 隔離方式 | 危險指令檢查 | 最適用場景 |
|---|---|---|---|
| local | 無——在主機上運行 | ✅ 是 | 開發、受信任的使用者 |
| ssh | 遠端機器 | ✅ 是 | 在獨立伺服器上運行 |
| docker | 容器 | ❌ 跳過(容器即邊界) | 生產環境 Gateway |
| singularity | 容器 | ❌ 跳過 | HPC 環境 |
| modal | 雲端沙箱 | ❌ 跳過 | 可擴展的雲端隔離 |
| daytona | 雲端沙箱 | ❌ 跳過 | 持久化雲端工作區 |
環境變數透傳 {#environment-variable-passthrough}
execute_code 和 terminal 都會從子程序中移除敏感環境變數,以防止 LLM 產生的程式碼外洩憑證。然而,宣告了 required_environment_variables 的 Skill 則有正當需求需要存取這些變數。
運作方式
有兩種機制允許特定變數通過沙箱過濾器:
1. Skill 範圍的透傳(自動)
當 Skill 被載入(透過 skill_view 或 /skill 指令)且宣告了 required_environment_variables 時,實際存在於環境中的那些變數會自動註冊為透傳變數。未設定的變數(仍處於需設定狀態)不會被註冊。
# 在 Skill 的 SKILL.md frontmatter 中
required_environment_variables:
- name: TENOR_API_KEY
prompt: Tenor API key
help: Get a key from https://developers.google.com/tenor
載入此 Skill 後,TENOR_API_KEY 會透傳到 execute_code、terminal(本地)以及遠端後端(Docker、Modal)——無需手動配置。
INFO — Docker & Modal
v0.5.1 之前,Docker 的
forward_env是與 Skill 透傳分開的系統。它們現在已合併——Skill 宣告的環境變數會自動轉發到 Docker 容器和 Modal 沙箱中,無需手動加入docker_forward_env。
2. 基於配置的透傳(手動)
對於未被任何 Skill 宣告的環境變數,在 config.yaml 的 terminal.env_passthrough 中加入它們:
terminal:
env_passthrough:
- MY_CUSTOM_KEY
- ANOTHER_TOKEN
憑證檔案透傳(OAuth token 等) {#credential-file-passthrough}
某些 Skill 需要在沙箱中存取檔案(不僅是環境變數)——例如 Google Workspace 會在啟用設定檔的 HERMES_HOME 下將 OAuth token 儲存為 google_token.json。Skill 在 frontmatter 中宣告這些檔案:
required_credential_files:
- path: google_token.json
description: Google OAuth2 token (created by setup script)
- path: google_client_secret.json
description: Google OAuth2 client credentials
載入時,Hermes 會檢查這些檔案是否存在於啟用設定檔的 HERMES_HOME 中,並註冊以進行掛載:
- Docker:唯讀 bind 掛載(
-v host:container:ro) - Modal:在沙箱建立時掛載 + 每次指令前同步(處理 Session 中的 OAuth 設定)
- Local:無需操作(檔案已可存取)
你也可以在 config.yaml 中手動列出憑證檔案:
terminal:
credential_files:
- google_token.json
- my_custom_oauth_token.json
路徑相對於 ~/.hermes/。檔案會掛載到容器內的 /root/.hermes/。此清單由 tools/credential_files.py(terminal.credential_files)讀取——它位於 terminal: 區塊下,但由憑證檔案模組而非核心終端後端載入,因此不屬於內建的 DEFAULT_CONFIG 快照的一部分。
各沙箱的過濾行為
| 沙箱 | 預設過濾器 | 透傳覆寫 |
|---|---|---|
| execute_code | 阻止名稱中包含 KEY、TOKEN、SECRET、PASSWORD、CREDENTIAL、PASSWD、AUTH 的變數;僅允許安全前綴的變數通過 | ✅ 透傳變數繞過兩項檢查 |
| terminal(本地) | 阻止明確的 Hermes 基礎設施變數(供應商金鑰、Gateway token、工具 API 金鑰) | ✅ 透傳變數繞過封鎖清單 |
| terminal(Docker) | 預設不使用主機環境變數 | ✅ 透傳變數 + docker_forward_env 透過 -e 轉發 |
| terminal(Modal) | 預設不使用主機環境變數/檔案 | ✅ 憑證檔案掛載;環境變數透過同步透傳 |
| MCP | 除了安全的系統變數和明確配置的 env 外,全部阻止 | ❌ 不受透傳影響(改用 MCP env 配置) |
安全考量
- 透傳僅影響你或你的 Skill 明確宣告的變數——預設的安全態勢對任意 LLM 產生的程式碼保持不變
- 憑證檔案以唯讀方式掛載到 Docker 容器中
- Skills Guard 會在安裝前掃描 Skill 內容中的可疑環境變數存取模式
- 未設定/不存在的變數永遠不會被註冊(你無法洩漏不存在的東西)
- Hermes 基礎設施密鑰(供應商 API 金鑰、Gateway token)不應加入
env_passthrough——它們有專屬機制
MCP 憑證處理
MCP(Model Context Protocol)伺服器子程序會收到過濾後的環境,以防止意外的憑證洩漏。
安全環境變數
只有以下變數會從主機傳遞到 MCP stdio 子程序:
PATH, HOME, USER, LANG, LC_ALL, TERM, SHELL, TMPDIR
加上所有 XDG_* 變數。所有其他環境變數(API 金鑰、token、密鑰)都會被移除。
在 MCP 伺服器的 env 配置中明確定義的變數會被傳遞:
mcp_servers:
github:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_..." # 僅此變數被傳遞
憑證遮蔽
來自 MCP 工具的錯誤訊息在回傳給 LLM 前會被淨化。以下模式會被替換為 [REDACTED]:
- GitHub PAT(
ghp_...) - OpenAI 風格的金鑰(
sk-...) - Bearer token
token=、key=、API_KEY=、password=、secret=參數
網站存取策略
你可以限制 Agent 透過其 web 和 browser 工具可存取的網站。這對於防止 Agent 存取內部服務、管理面板或其他敏感 URL 很有用。
# 在 ~/.hermes/config.yaml 中
security:
website_blocklist:
enabled: true
domains:
- "*.internal.company.com"
- "admin.example.com"
shared_files:
- "/etc/hermes/blocked-sites.txt"
當請求的 URL 被封鎖時,工具會回傳錯誤說明該網域被策略封鎖。封鎖清單在 web_search、web_extract、browser_navigate 和所有支援 URL 的工具中強制執行。
詳見設定指南中的網站封鎖清單以了解完整詳情。
SSRF 防護
所有支援 URL 的工具(web search、web extract、vision、browser)在取得 URL 前都會進行驗證,以防止伺服器端請求偽造(SSRF)攻擊。封鎖的地址包括:
- 私有網路(RFC 1918):
10.0.0.0/8、172.16.0.0/12、192.168.0.0/16 - 迴路地址:
127.0.0.0/8、::1 - 鏈路本位地址:
169.254.0.0/16(包括169.254.169.254的雲端中繼資料) - CGNAT / 共用地址空間(RFC 6598):
100.64.0.0/10(Tailscale、WireGuard VPN) - 雲端中繼資料主機名稱:
metadata.google.internal、metadata.goog - 保留、多播和未指定地址
SSRF 防護在面向網際網路的使用中始終啟用,DNS 失敗會被視為封鎖(預設為安全失敗)。重新導向鏈在每個跳點都會重新驗證,以防止基於重新導向的繞過。
允許私有 URL
某些設定有正當需求需要存取私有/內部 URL——例如將 home.arpa 解析到 RFC 1918 空間的家庭網路、僅限區域網路的 Ollama/llama.cpp 端點、內部 wiki、雲端中繼資料除錯等。對於這些情況,有一個全域選擇退出機制:
security:
allow_private_urls: true # 預設:false
啟用後,web 工具、browser、vision URL 取得和 Gateway 媒體下載將不再拒絕 RFC 1918 / 迴路 / 鏈路本位 / CGNAT / 雲端中繼資料目的地。這是一個刻意的信任邊界——僅在 Agent 將任意提示注入的 URL 對本地網路執行屬於可接受風險的機器上啟用。面向公眾的 Gateway 應保持關閉。
不論此設定為何,主機子字串防護(即使底層 IP 為公網,也會封鎖形似 Unicode 網域的騙術)都會保持啟用。
Tirith 執行前安全掃描
Hermes 整合了 tirith,在執行前進行內容層級的指令掃描。Tirith 可偵測純模式比對會遺漏的威脅:
- 同形字 URL 欺騙(國際化網域攻擊)
- 管道到解譯器的模式(
curl | bash、wget | sh) - 終端注入攻擊
Tirith 在首次使用時從 GitHub releases 自動安裝,並進行 SHA-256 校驗和驗證(若 cosign 可用則進行 cosign 來源驗證)。
# 在 ~/.hermes/config.yaml 中
security:
tirith_enabled: true # 啟用/停用 tirith 掃描(預設:true)
tirith_path: "tirith" # tirith 二進位檔路徑(預設:PATH 查找)
tirith_timeout: 5 # 子程序逾時秒數
tirith_fail_open: true # tirith 不可用時允許執行(預設:true)
當 tirith_fail_open 為 true(預設)時,若 tirith 未安裝或逾時,指令會照常進行。在高安全性環境中設為 false,可在 tirith 不可用時阻止指令。
Tirith 提供 Linux(x86_64 / aarch64)和 macOS(x86_64 / arm64)的預建二進位檔。在沒有預建二進位檔的平台上(Windows 等),tirith 會被靜默跳過——模式比對防護仍會運行,且 CLI 不會顯示「不可用」橫幅。若要在 Windows 上使用 tirith,請在 WSL 下運行 Hermes。
Tirith 的判定會與審核流程整合:安全指令直接通過,而可疑和被封鎖的指令會觸發使用者審核,並附上完整的 tirith 發現(嚴重性、標題、說明、更安全的替代方案)。使用者可以批准或拒絕——預設選擇為拒絕,以確保無人值守場景的安全。
情境檔案注入防護
情境檔案(AGENTS.md、.cursorrules、SOUL.md)在被納入系統提示前會經過提示注入掃描。掃描器檢查以下內容:
- 忽略/漠視先前指令的指示
- 帶有可疑關鍵字的隱藏 HTML 註解
- 嘗試讀取密鑰(
.env、credentials、.netrc) - 透過
curl外洩憑證 - 不可見的 Unicode 字元(零寬空格、雙向覆蓋)
被封鎖的檔案會顯示警告:
[BLOCKED: AGENTS.md contained potential prompt injection (prompt_injection). Content not loaded.]
生產環境部署最佳實踐
Gateway 部署檢查清單
- 設定明確的白名單 — 生產環境中絕對不要使用
GATEWAY_ALLOW_ALL_USERS=true - 使用容器後端 — 在 config.yaml 中設定
terminal.backend: docker - 限制資源限制 — 設定適當的 CPU、記憶體和磁碟限制
- 安全儲存密鑰 — 將 API 金鑰放在
~/.hermes/.env中並設定適當的檔案權限 - 啟用 DM 配對 — 盡可能使用配對碼而非硬編碼使用者 ID
- 檢視指令白名單 — 定期稽核 config.yaml 中的
command_allowlist - 設定
terminal.cwd— 不要讓 Agent 從敏感目錄操作 - 以非 root 身分運行 — 絕對不要以 root 身分運行 Gateway
- 監控日誌 — 檢查
~/.hermes/logs/中的未授權存取嘗試 - 保持更新 — 定期執行
hermes update以取得安全性修補
保護 API 金鑰
# 設定 .env 檔案的適當權限
chmod 600 ~/.hermes/.env
# 為不同服務使用獨立的金鑰
# 絕對不要將 .env 檔案提交到版本控制
網路隔離
為了最大的安全性,請在獨立的機器或虛擬機上運行 Gateway。在 config.yaml 中設定 terminal.backend: ssh,然後在 ~/.hermes/.env 中透過環境變數提供主機詳細資訊:
# ~/.hermes/config.yaml
terminal:
backend: ssh
# ~/.hermes/.env
TERMINAL_SSH_HOST=agent-worker.local
TERMINAL_SSH_USER=hermes
TERMINAL_SSH_KEY=~/.ssh/hermes_agent_key
SSH 連線詳情存在於 .env(而非 config.yaml)中,因此不會隨著設定檔匯出被提交或分享。這讓 Gateway 的訊息連線與 Agent 的指令執行保持分離。
供應鏈安全公告檢查
Hermes 內建了一個安全公告掃描器,會標記活跃 venv 中符合已知被入侵版本精心整理清單的 Python 套件(供應鏈蠕蟲,例如 2026 年 5 月的 mistralai 2.4.6 投毒事件)。實作位於 hermes_cli/security_advisories.py。
運作方式:
- CLI 啟動橫幅。 若有符合的安全公告,會列印一行警告,並指引執行
hermes doctor取得完整的修復步驟。 hermes doctor。 顯示每個活跃的安全公告,附帶版本詳細資訊和 2-4 步的修復說明。- Gateway 啟動。 記錄至
gateway.log;第一則互動訊息會顯示簡短的營運橫幅。
每個安全公告都有一個穩定的 ID。一旦你已閱讀並採取行動,就可以永久關閉它:
hermes doctor --ack <advisory-id>
關閉狀態會持久化到 config.security.acked_advisories 並在重新啟動後保留。舊的安全公告故意不會從清單中移除——保留它們可以讓全新安裝對歷史上被投毒的版本(仍可能快取在私人映射站中)保持警告。
檢查本身僅使用標準函式庫,每次公告僅執行一次 importlib.metadata.version() 查找,因此可以安全地在每次啟動時運行。
可選依賴的延遲安裝
許多功能(Mistral TTS、ElevenLabs、Honcho 記憶、Bedrock、Slack、Matrix……)依賴不是每個使用者都需要的 Python 套件。Hermes 會在首次使用時延遲安裝這些套件,而非在 hermes-agent[all] 下急切安裝。實作位於 tools/lazy_deps.py。
這解決的取捨:
- 脆弱性。 當某個可選附加項的傳遞依賴在 PyPI 上變得不可用(因惡意軟體被隔離、被撤回、上傳損壞),整個
[all]解析會失敗,全新安裝會靜默回退到精簡版本——一次失去 10+ 個不相關的附加項。延遲安裝隔離每個後端,因此一個被投毒的依賴無法破壞不相關的功能。 - 臃腫。 只與一個供應商對話的使用者不再需要拉入數百個永遠不會匯入的套件。
運作方式:
- 後端模組在其首次匯入路徑的頂部呼叫
ensure("feature.name")。 - 若依賴缺失,
ensure會檢查config.yaml中的security.allow_lazy_installs(預設為true),並對白名單中的規格執行 venv 範圍的pip install。 - 若安裝失敗或使用者已停用延遲安裝,該呼叫會引發
FeatureUnavailable,附帶實際的 pip stderr 和hermes tools的指引。
tools/lazy_deps.py 強制執行的安全保證:
| 保證 | 意義 |
|---|---|
| 僅限 venv 範圍 | 安裝目標為活跃 venv 中的 sys.executable——永遠不是系統 Python |
| 僅從 PyPI 安裝 | 規格接受 "package>=1.0,<2" 語法。不允許 --index-url、git+https:// 或 file: 路徑——惡意的 config.yaml 無法重新導向安裝 |
| 白名單 | 僅有出現在內建 LAZY_DEPS 對應表中的規格才能透過此路徑安裝。功能名稱的拼寫錯誤不會取得安裝任意套件的語意 |
| 選擇退出 | 設定 security.allow_lazy_installs: false 可完全停用執行時安裝。適用於受限網路或嚴格的安全態勢 |
| 無靜默重試 | 失敗會以 FeatureUnavailable 呈現——不會快取壞狀態,不會出現重試風暴 |
停用執行時安裝:
# ~/.hermes/config.yaml
security:
allow_lazy_installs: false
停用後,需要可選依賴的後端會告知使用者手動執行安裝(pip install …)或透過 hermes tools 選擇不同的後端。