mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-21 10:22:18 +00:00
fix(managed-scope): honor managed scope in config→env bridges too
Manual verification surfaced a second bypass class beyond the standalone config loaders: several code paths bridge config.yaml values into os.environ (HERMES_TIMEZONE, HERMES_REDACT_SECRETS, HERMES_MAX_ITERATIONS, TERMINAL_*, network.force_ipv4, ...) by reading the raw user YAML, so the env the whole process reads carried the USER's value even when an administrator pinned it — e.g. a managed timezone was overridden because gateway/run.py wrote the user's timezone into HERMES_TIMEZONE, and _resolve_timezone_name() checks the env var first. Wired the shared apply_managed_overlay() into every config→env bridge: - gateway/run.py module-level startup bridge (timezone, redact_secrets, max_turns, terminal, display, gateway.strict, ...) - gateway/run.py _reload_runtime_env_preserving_config_authority (the per-turn re-bridge that keeps config authoritative over reloaded .env — must keep MANAGED authoritative on every turn, not just startup) - hermes_cli/main.py early security.redact_secrets / network.force_ipv4 bridge (runs before load_config is usable, at import time) - hermes_cli/send_cmd.py top-level scalar config→env bridge Verified end-to-end against a writable managed dir (12/12 checks incl. timezone, logging, model, skin, gateway settings, write-guard) and in a clean process the gateway per-turn bridge writes HERMES_TIMEZONE=<managed>. Adds an order-independent regression test for the bridge overlay.
This commit is contained in:
parent
b0e47a98f9
commit
1928aa0443
4 changed files with 67 additions and 0 deletions
|
|
@ -531,6 +531,16 @@ try:
|
|||
if _cfg_path.exists():
|
||||
with open(_cfg_path, encoding="utf-8") as _f:
|
||||
_early_cfg_raw = _yaml_early.safe_load(_f) or {}
|
||||
# Managed scope: overlay administrator-pinned values so a managed
|
||||
# security.redact_secrets / network.force_ipv4 wins here too. This early
|
||||
# bridge reads config.yaml directly (before load_config is usable), so
|
||||
# without the overlay a managed redact_secrets toggle would be ignored.
|
||||
# Fail-open via the shared helper.
|
||||
try:
|
||||
from hermes_cli import managed_scope
|
||||
_early_cfg_raw = managed_scope.apply_managed_overlay(_early_cfg_raw)
|
||||
except Exception:
|
||||
pass
|
||||
if "HERMES_REDACT_SECRETS" not in os.environ:
|
||||
_early_sec_cfg = _early_cfg_raw.get("security", {})
|
||||
if isinstance(_early_sec_cfg, dict):
|
||||
|
|
|
|||
|
|
@ -276,6 +276,14 @@ def _load_hermes_env() -> None:
|
|||
except Exception:
|
||||
pass
|
||||
|
||||
# Managed scope: overlay administrator-pinned values before bridging to env,
|
||||
# so a managed top-level scalar wins here too. Fail-open via the helper.
|
||||
try:
|
||||
from hermes_cli import managed_scope
|
||||
raw = managed_scope.apply_managed_overlay(raw if isinstance(raw, dict) else {})
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not isinstance(raw, dict):
|
||||
return
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue