fix(cli): safe mode also skips shell-hook registration
--safe-mode promised to disable ALL customizations, but shell hooks declared in config.yaml's hooks: block registered anyway — register_from_config() runs independently of plugin discovery and load_config() does not honor HERMES_IGNORE_USER_CONFIG. Gate it on HERMES_SAFE_MODE at the single chokepoint so troubleshooting runs fire zero user-configured code (plugins, MCP, and hooks). Docs (en + zh) updated; positive + negative tests added.
This commit is contained in:
parent
fc02b1c276
commit
299d5c6603
5 changed files with 49 additions and 3 deletions
|
|
@ -224,6 +224,15 @@ def register_from_config(
|
|||
if not isinstance(cfg, dict):
|
||||
return []
|
||||
|
||||
# Safe mode (--safe-mode / HERMES_SAFE_MODE=1): shell hooks are user
|
||||
# customizations too — skip registration entirely so a troubleshooting
|
||||
# run fires zero user-configured code (plugins, MCP, AND hooks).
|
||||
from utils import env_var_enabled
|
||||
|
||||
if env_var_enabled("HERMES_SAFE_MODE"):
|
||||
logger.info("HERMES_SAFE_MODE=1 — shell-hook registration skipped")
|
||||
return []
|
||||
|
||||
effective_accept = _resolve_effective_accept(cfg, accept_hooks)
|
||||
|
||||
specs = _parse_hooks_block(cfg.get("hooks"))
|
||||
|
|
|
|||
|
|
@ -130,3 +130,40 @@ def test_parser_accepts_safe_mode_on_root_and_chat():
|
|||
assert parser.parse_args(["--safe-mode"]).safe_mode is True
|
||||
assert parser.parse_args(["chat", "--safe-mode"]).safe_mode is True
|
||||
assert parser.parse_args(["chat"]).safe_mode is False
|
||||
|
||||
|
||||
def test_shell_hooks_skipped(monkeypatch):
|
||||
monkeypatch.setenv("HERMES_SAFE_MODE", "1")
|
||||
from agent.shell_hooks import register_from_config
|
||||
|
||||
cfg = {
|
||||
"hooks": {
|
||||
"pre_tool_call": [{"command": "echo hooked"}],
|
||||
},
|
||||
"hooks_auto_accept": True,
|
||||
}
|
||||
|
||||
assert register_from_config(cfg, accept_hooks=True) == []
|
||||
|
||||
|
||||
def test_shell_hooks_register_without_safe_mode(monkeypatch):
|
||||
import agent.shell_hooks as sh
|
||||
|
||||
cfg = {
|
||||
"hooks": {
|
||||
"pre_tool_call": [{"command": "echo hooked"}],
|
||||
},
|
||||
"hooks_auto_accept": True,
|
||||
}
|
||||
|
||||
manager = types.SimpleNamespace(_hooks={})
|
||||
plugins = types.ModuleType("hermes_cli.plugins")
|
||||
setattr(plugins, "get_plugin_manager", lambda: manager)
|
||||
setattr(plugins, "VALID_HOOKS", {"pre_tool_call"})
|
||||
monkeypatch.setitem(sys.modules, "hermes_cli.plugins", plugins)
|
||||
monkeypatch.setattr(sh, "_registered", set())
|
||||
|
||||
registered = sh.register_from_config(cfg, accept_hooks=True)
|
||||
|
||||
assert len(registered) == 1
|
||||
assert "pre_tool_call" in manager._hooks
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ Common options:
|
|||
| `--pass-session-id` | Pass the session ID into the system prompt. |
|
||||
| `--ignore-user-config` | Ignore `~/.hermes/config.yaml` and use built-in defaults. Credentials in `.env` are still loaded. Useful for isolated CI runs, reproducible bug reports, and third-party integrations. |
|
||||
| `--ignore-rules` | Skip auto-injection of `AGENTS.md`, `SOUL.md`, `.cursorrules`, persistent memory, and preloaded skills. Combine with `--ignore-user-config` for a fully isolated run. |
|
||||
| `--safe-mode` | Troubleshooting mode: disable ALL customizations — user config, rules/memory injection, plugins, and MCP servers (implies `--ignore-user-config` and `--ignore-rules`). Use to isolate whether a problem comes from your setup or from Hermes itself. |
|
||||
| `--safe-mode` | Troubleshooting mode: disable ALL customizations — user config, rules/memory injection, plugins, shell hooks, and MCP servers (implies `--ignore-user-config` and `--ignore-rules`). Use to isolate whether a problem comes from your setup or from Hermes itself. |
|
||||
| `--source <tag>` | Session source tag for filtering (default: `cli`). Use `tool` for third-party integrations that should not appear in user session lists. |
|
||||
| `--max-turns <N>` | Maximum tool-calling iterations per conversation turn (default: 90, or `agent.max_turns` in config). |
|
||||
|
||||
|
|
|
|||
|
|
@ -716,7 +716,7 @@ Advanced per-platform knobs for throttling the outbound message batcher. Most us
|
|||
| `HERMES_ACCEPT_HOOKS` | Auto-approve any unseen shell hooks declared in `config.yaml` without a TTY prompt. Equivalent to `--accept-hooks` or `hooks_auto_accept: true`. |
|
||||
| `HERMES_IGNORE_USER_CONFIG` | Skip `~/.hermes/config.yaml` and use built-in defaults (credentials in `.env` still load). Equivalent to `--ignore-user-config`. |
|
||||
| `HERMES_IGNORE_RULES` | Skip auto-injection of `AGENTS.md`, `SOUL.md`, `.cursorrules`, memory, and preloaded skills. Equivalent to `--ignore-rules`. |
|
||||
| `HERMES_SAFE_MODE` | Troubleshooting mode: disable ALL customizations — skips plugin discovery and MCP server loading. Set automatically by `--safe-mode` (which also sets the two flags above). |
|
||||
| `HERMES_SAFE_MODE` | Troubleshooting mode: disable ALL customizations — skips plugin discovery, MCP server loading, and shell-hook registration. Set automatically by `--safe-mode` (which also sets the two flags above). |
|
||||
| `HERMES_MD_NAMES` | Comma-separated list of rules-file names to auto-inject (default: `AGENTS.md,CLAUDE.md,.cursorrules,SOUL.md`). |
|
||||
| `HERMES_TOOL_PROGRESS` | Deprecated compatibility variable for tool progress display. Prefer `display.tool_progress` in `config.yaml`. |
|
||||
| `HERMES_TOOL_PROGRESS_MODE` | Deprecated compatibility variable for tool progress mode. Prefer `display.tool_progress` in `config.yaml`. |
|
||||
|
|
|
|||
|
|
@ -532,7 +532,7 @@ Graph 事件(Teams 会议、日历、聊天等)的入站变更通知监听
|
|||
| `HERMES_ACCEPT_HOOKS` | 无需 TTY 提示自动批准 `config.yaml` 中声明的任何未见过的 shell hook。等同于 `--accept-hooks` 或 `hooks_auto_accept: true`。 |
|
||||
| `HERMES_IGNORE_USER_CONFIG` | 跳过 `~/.hermes/config.yaml` 并使用内置默认值(`.env` 中的凭证仍会加载)。等同于 `--ignore-user-config`。 |
|
||||
| `HERMES_IGNORE_RULES` | 跳过 `AGENTS.md`、`SOUL.md`、`.cursorrules`、记忆和预加载技能的自动注入。等同于 `--ignore-rules`。 |
|
||||
| `HERMES_SAFE_MODE` | 故障排查模式:禁用**所有**自定义项——跳过插件发现和 MCP 服务器加载。由 `--safe-mode` 自动设置(同时也会设置上面两个 flag)。 |
|
||||
| `HERMES_SAFE_MODE` | 故障排查模式:禁用**所有**自定义项——跳过插件发现、MCP 服务器加载和 shell hook 注册。由 `--safe-mode` 自动设置(同时也会设置上面两个 flag)。 |
|
||||
| `HERMES_MD_NAMES` | 自动注入的规则文件名逗号分隔列表(默认:`AGENTS.md,CLAUDE.md,.cursorrules,SOUL.md`)。 |
|
||||
| `HERMES_TOOL_PROGRESS` | 工具进度显示的已弃用兼容变量。优先使用 `config.yaml` 中的 `display.tool_progress`。 |
|
||||
| `HERMES_TOOL_PROGRESS_MODE` | 工具进度模式的已弃用兼容变量。优先使用 `config.yaml` 中的 `display.tool_progress`。 |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue