mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-05 07:41:39 +00:00
fix(security): validate Nous Portal inference_base_url against host allowlist
The Nous Portal proxy adapter forwards minted ``agent_key`` bearer tokens to whatever ``base_url`` ``resolve_nous_runtime_credentials()`` returns, which is read directly from the refresh / agent-key-mint response and persisted to ``~/.hermes/auth.json``. With no validation beyond a trailing-slash strip, a poisoned URL (Portal-side MITM, or local write to auth.json) gets forwarded the legitimate bearer on every subsequent proxy request — exfiltrating the user's inference budget and opening a response-injection channel back into the IDE / chat client. Add ``_validate_nous_inference_url_from_network()`` in ``hermes_cli.auth``: an https + host-allowlist check that returns None for anything outside ``inference-api.nousresearch.com``, so callers fall back to the documented default rather than ship the bearer to an attacker. This commit wires the validator into the proxy adapter at ``nous_portal.py``. A follow-up commit wires it into the four refresh / mint sites in ``auth.py`` so the poisoned URL never lands in auth.json in the first place. The env-var override path (``NOUS_INFERENCE_BASE_URL``) bypasses validation by design — that's the documented staging/dev escape hatch and the env source is already trusted (the user set it themselves). Co-authored-by: memosr <mehmet.sr35@gmail.com>
This commit is contained in:
parent
09afafb87e
commit
d33c99bbb1
2 changed files with 67 additions and 2 deletions
|
|
@ -27,6 +27,7 @@ from hermes_cli.auth import (
|
|||
_quarantine_nous_oauth_state,
|
||||
_quarantine_nous_pool_entries,
|
||||
_save_auth_store,
|
||||
_validate_nous_inference_url_from_network,
|
||||
_write_shared_nous_state,
|
||||
resolve_nous_runtime_credentials,
|
||||
)
|
||||
|
|
@ -137,7 +138,10 @@ class NousPortalAdapter(UpstreamAdapter):
|
|||
"Try `hermes login nous` to re-authenticate."
|
||||
)
|
||||
|
||||
base_url = refreshed.get("base_url") or DEFAULT_NOUS_INFERENCE_URL
|
||||
base_url = (
|
||||
_validate_nous_inference_url_from_network(refreshed.get("base_url"))
|
||||
or DEFAULT_NOUS_INFERENCE_URL
|
||||
)
|
||||
base_url = base_url.rstrip("/")
|
||||
|
||||
return UpstreamCredential(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue