hermes - 💡(How to fix) Fix [Bug]: hermes config set writes api_key values to config.yaml in plaintext — contradicts SECURITY.md guidance

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

A related reliability concern: in the same session where the api_key was set via hermes config set, another security-sensitive key (security.redact_secrets) was also toggled via the same command. Even after the documented restart (/reset), on the next session the value had reverted to its previous state. While the root cause was not isolated, it reinforces the concern that config.yaml is not a reliable persistence target for values whose correctness is security-sensitive — whether they are secrets (api_key) or security toggles (redact_secrets).

Fix Action

Fix / Workaround

  • config.yaml is readable by the read_file and search_files tools. config.yaml 可被 read_file、search_files 等工具读取。
  • .env is properly guarded: read_file returns "Access denied: Hermes credential store" and patch returns "Write denied: protected system/ credential file." .env 受到正确保护:read_file 拒绝读取,patch 拒绝写入。
  • This creates a dangerous asymmetry: a user who runs hermes config set with a credential (a natural, first-session thing to try) unwittingly places it in an unprotected file. 这造成了不对称:用户自然地用 hermes config set 设置凭证后, secret 实际上落入了不受保护的文件。
RAW_BUFFERClick to expand / collapse

Bug Description / 问题描述

Running hermes config set with a key path ending in api_key (e.g. auxiliary.vision.api_key) writes the credential value directly into config.yaml in plaintext. This contradicts the project's own hardening guidance (SECURITY.md §4: "Keep credentials in the operator credential file with tight permissions, never in the main config, never in version control.").

执行 hermes config set 时,若键名以 api_key 结尾(如 auxiliary.vision.api_key),凭证会被明文写入 config.yaml。 这与项目自身的安全指引(SECURITY.md §4)直接矛盾。

Why this matters / 为什么重要

  • config.yaml is readable by the read_file and search_files tools. config.yaml 可被 read_file、search_files 等工具读取。
  • .env is properly guarded: read_file returns "Access denied: Hermes credential store" and patch returns "Write denied: protected system/ credential file." .env 受到正确保护:read_file 拒绝读取,patch 拒绝写入。
  • This creates a dangerous asymmetry: a user who runs hermes config set with a credential (a natural, first-session thing to try) unwittingly places it in an unprotected file. 这造成了不对称:用户自然地用 hermes config set 设置凭证后, secret 实际上落入了不受保护的文件。

Steps to Reproduce / 复现步骤

  1. Run: hermes config set auxiliary.vision.api_key <any_value>
  2. Check: cat ~/.hermes/config.yaml | grep api_key
  3. The value appears in plaintext under auxiliary.vision.api_key. 明文出现在 config.yaml 中。
  4. Confirm asymmetry: read_file on .env is blocked, but read_file on config.yaml returns the full file including the key. 确认不对称:read_file 对 .env 拒绝,对 config.yaml 正常返回全部内容。

Additional Observation / 附加观察

A related reliability concern: in the same session where the api_key was set via hermes config set, another security-sensitive key (security.redact_secrets) was also toggled via the same command. Even after the documented restart (/reset), on the next session the value had reverted to its previous state. While the root cause was not isolated, it reinforces the concern that config.yaml is not a reliable persistence target for values whose correctness is security-sensitive — whether they are secrets (api_key) or security toggles (redact_secrets).

一个相关的可靠性问题:同一次会话中,除了 api_key 之外,另一个安全敏感键 security.redact_secrets 也通过 hermes config set 被修改过。按照文档 要求 /reset 重启后,下次启动时该值已恢复为修改前的状态。虽然未定位根因, 但这进一步说明 config.yaml 不适合作为安全敏感值的持久化目标——无论是 secret(api_key)还是安全开关(redact_secrets)。

Expected Behavior / 预期行为

hermes config set should either:

  1. Refuse to write fields named api_key (or other credential-suffixed fields) to config.yaml, and direct the user to .env; or
  2. At minimum, emit a clear warning that the value is being stored in an unprotected file and recommend using .env instead.

hermes config set 应当:

  1. 拒绝将 api_key 字段写入 config.yaml,并引导用户使用 .env;或
  2. 至少发出明确警告,说明该值将存入不受保护的文件,建议改用 .env

Actual Behavior / 实际行为

The credential is silently written to config.yaml in plaintext with no warning. The file is fully readable by agent tools.

凭证被静默地以明文写入 config.yaml,没有任何警告。该文件可被 agent 工具完全读取。

Affected Component / 影响组件

  • Configuration (config.yaml, .env, hermes setup)
  • Agent Core (conversation loop, context compression, memory)

Version / 版本

Hermes Agent v0.15.1 (2026.5.29), macOS 26.5

Root Cause Analysis (optional)

The hermes config set command in hermes_cli/config.py treats all config keys uniformly — it writes the value into the YAML tree and saves it back. There is no field-name-aware guard that checks for credential-bearing suffixes (api_key, _token, etc.) before writing.

hermes config set 对所有键一视同仁地写入 YAML,没有按字段名做区分。

Proposed Fix (optional)

In hermes config set, scan the key path for credential suffixes. When matched, either reject the write with a message pointing to .env, or write the value to .env instead (and reference it via ${ENV_VAR} in config.yaml).

hermes config set 中检测键名是否以 api_key 等结尾,匹配时拒绝 并引导用户写入 .env

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - 💡(How to fix) Fix [Bug]: hermes config set writes api_key values to config.yaml in plaintext — contradicts SECURITY.md guidance