feat: embedder environment-hint hook for the system prompt (#34574)

* fix(security): block AWS SDK creds from subprocess env

* fix(security): narrow Bedrock subprocess strip to inference bearer token only

Scopes the AWS_SDK subprocess strip down from the full AWS credential chain
to just AWS_BEARER_TOKEN_BEDROCK — the only Hermes-managed *inference* secret
(analogous to OPENAI_API_KEY). The general AWS credential chain
(AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN / AWS_PROFILE
/ config + role pointers) is intentionally left inheritable.

Why: per SECURITY.md §3.2 the local terminal is the user's trusted operator
shell. Hard-blocklisting the general chain would (a) regress *every* user who
runs aws/terraform/cdk/boto3 in the agent terminal — not just Bedrock users,
since PROVIDER_REGISTRY is iterated unconditionally at import — and (b) be
unrecoverable, because env_passthrough.py refuses to re-allow anything in
_HERMES_PROVIDER_ENV_BLOCKLIST (GHSA-rhgp-j443-p4rf). The narrow strip closes
the reported leak (opencode enumerating the Bedrock catalog off the leaked
bearer token) with no capability loss.

Keeps zapabob's self-healing auth_type=="aws_sdk" mechanism so any future
SDK-cred provider is covered automatically.

Tests: bearer token stripped + general chain preserved (no-regression guard),
on both the runtime strip path and the blocklist-membership path.

Co-authored-by: zapabob <1920071390@campus.ouj.ac.jp>

* feat: embedder environment-hint hook for the system prompt

Adds HERMES_ENVIRONMENT_HINT env var (and config.yaml agent.environment_hint)
so a host wrapping Hermes (sandbox runner, managed platform) can describe the
runtime environment — proxy, credential handling, mount layout — in the system
prompt's environment-hints block, without editing the identity slot (SOUL.md).

Read once at prompt-build time, so it lands in the stable, cache-safe portion
of the system prompt. Env var overrides the config key (build-time/container
mechanism). Empty by default — no behavior change for existing installs.

---------

Co-authored-by: zapabob <1920071390@campus.ouj.ac.jp>
This commit is contained in:
Teknium
2026-05-29 04:10:05 -07:00
committed by GitHub
co-authored by zapabob
parent c0b17b3c0c
commit e4b9532c18
3 changed files with 80 additions and 0 deletions
+52
View File
@@ -947,6 +947,58 @@ class TestEnvironmentHints:
f"info is suppressed in the system prompt"
)
def test_environment_hint_from_env_var_is_appended(self, monkeypatch):
"""HERMES_ENVIRONMENT_HINT lets an embedder describe the runtime env."""
import agent.prompt_builder as _pb
monkeypatch.setattr(_pb, "is_wsl", lambda: False)
monkeypatch.delenv("TERMINAL_ENV", raising=False)
monkeypatch.setenv("HERMES_ENVIRONMENT_HINT", "Running inside an OpenShell sandbox.")
_pb._clear_backend_probe_cache()
result = _pb.build_environment_hints()
assert "Running inside an OpenShell sandbox." in result
# The factual host block must still come first.
assert result.index("Host:") < result.index("OpenShell")
def test_environment_hint_env_var_overrides_config(self, monkeypatch):
"""Env var wins over config.yaml agent.environment_hint."""
import agent.prompt_builder as _pb
monkeypatch.setattr(_pb, "is_wsl", lambda: False)
monkeypatch.delenv("TERMINAL_ENV", raising=False)
monkeypatch.setenv("HERMES_ENVIRONMENT_HINT", "ENV-WINS")
monkeypatch.setattr(
"hermes_cli.config.load_config",
lambda: {"agent": {"environment_hint": "CONFIG-VALUE"}},
)
_pb._clear_backend_probe_cache()
result = _pb.build_environment_hints()
assert "ENV-WINS" in result
assert "CONFIG-VALUE" not in result
def test_environment_hint_falls_back_to_config(self, monkeypatch):
"""With no env var, the config.yaml value is used."""
import agent.prompt_builder as _pb
monkeypatch.setattr(_pb, "is_wsl", lambda: False)
monkeypatch.delenv("TERMINAL_ENV", raising=False)
monkeypatch.delenv("HERMES_ENVIRONMENT_HINT", raising=False)
monkeypatch.setattr(
"hermes_cli.config.load_config",
lambda: {"agent": {"environment_hint": "CONFIG-VALUE"}},
)
_pb._clear_backend_probe_cache()
result = _pb.build_environment_hints()
assert "CONFIG-VALUE" in result
def test_environment_hint_empty_by_default(self, monkeypatch):
"""No hint configured anywhere → no embedder text, host block intact."""
import agent.prompt_builder as _pb
monkeypatch.setattr(_pb, "is_wsl", lambda: False)
monkeypatch.delenv("TERMINAL_ENV", raising=False)
monkeypatch.delenv("HERMES_ENVIRONMENT_HINT", raising=False)
monkeypatch.setattr("hermes_cli.config.load_config", lambda: {"agent": {}})
_pb._clear_backend_probe_cache()
result = _pb.build_environment_hints()
assert "Host:" in result
# =========================================================================
# Conditional skill activation