mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-15 14:22:43 +00:00
fix(security): order sanitizer after installed hooks
This commit is contained in:
parent
92c2146039
commit
1f46145e03
2 changed files with 50 additions and 1 deletions
|
|
@ -64,7 +64,10 @@ class _CrossOriginRequestSanitizer(urllib.request.BaseHandler):
|
|||
# Request processors run in ascending order. Keep this last so an installed
|
||||
# cookie/auth/instrumentation processor cannot re-add a secret after the
|
||||
# redirect handler sanitizes the new Request.
|
||||
handler_order = 1_000_000_000
|
||||
# Infinity is greater than every finite handler order. If an installed
|
||||
# processor also uses infinity, stable sorting keeps this appended handler
|
||||
# after it, so sanitization still owns the final request boundary.
|
||||
handler_order = float("inf") # type: ignore[assignment]
|
||||
|
||||
def __init__(self, original_url: str) -> None:
|
||||
self._original_origin = url_origin(original_url)
|
||||
|
|
|
|||
|
|
@ -329,6 +329,8 @@ def test_installed_request_processor_cannot_resurrect_cross_origin_secret(
|
|||
_RecordingHandler.redirect_to = f"http://localhost:{sink.server_port}/sink"
|
||||
|
||||
class SecretProcessor(urllib.request.BaseHandler):
|
||||
handler_order = float("inf") # type: ignore[assignment]
|
||||
|
||||
def http_request(self, request):
|
||||
request.add_header("X-Installed-Secret", "must-not-cross")
|
||||
return request
|
||||
|
|
@ -481,6 +483,50 @@ def test_anthropic_profile_drops_x_api_key_on_redirect(monkeypatch):
|
|||
assert headers["accept"] == "application/json"
|
||||
|
||||
|
||||
def test_azure_catalog_probe_drops_api_key_and_bearer_on_redirect():
|
||||
from hermes_cli import azure_detect
|
||||
|
||||
source = _server()
|
||||
sink = _server()
|
||||
_RecordingHandler.requests = []
|
||||
_RecordingHandler.redirect_status = 302
|
||||
_RecordingHandler.redirect_to = f"http://localhost:{sink.server_port}/sink"
|
||||
try:
|
||||
status, body = azure_detect._http_get_json(
|
||||
f"http://127.0.0.1:{source.server_port}/redirect", "azure-secret", timeout=3
|
||||
)
|
||||
finally:
|
||||
source.shutdown()
|
||||
sink.shutdown()
|
||||
|
||||
assert status == 200
|
||||
assert body == {"data": []}
|
||||
_, headers = _RecordingHandler.requests[-1]
|
||||
assert "authorization" not in headers
|
||||
assert "api-key" not in headers
|
||||
|
||||
|
||||
def test_azure_anthropic_probe_drops_api_key_and_bearer_on_redirect():
|
||||
from hermes_cli import azure_detect
|
||||
|
||||
sink = _server()
|
||||
source = ThreadingHTTPServer(("127.0.0.1", 0), _LmStudioSourceHandler)
|
||||
Thread(target=source.serve_forever, daemon=True).start()
|
||||
_RecordingHandler.requests = []
|
||||
_LmStudioSourceHandler.redirect_to = f"http://localhost:{sink.server_port}/sink"
|
||||
try:
|
||||
azure_detect._probe_anthropic_messages(
|
||||
f"http://127.0.0.1:{source.server_port}", "azure-secret"
|
||||
)
|
||||
finally:
|
||||
source.shutdown()
|
||||
sink.shutdown()
|
||||
|
||||
_, headers = _RecordingHandler.requests[-1]
|
||||
assert "authorization" not in headers
|
||||
assert "api-key" not in headers
|
||||
|
||||
|
||||
def test_lmstudio_load_post_drops_bearer_on_redirect(monkeypatch):
|
||||
from hermes_cli import models
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue