mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-21 05:11:26 +00:00
fix(security): require dashboard auth for plugin API routes
Remove the blanket /api/plugins/* exemption from auth_middleware so plugin API routes (e.g. Kanban dashboard) require the same session token as all other /api/ endpoints. Fixes #19533
This commit is contained in:
parent
7312f7f849
commit
ec9329ec41
2 changed files with 44 additions and 1 deletions
|
|
@ -225,7 +225,7 @@ async def host_header_middleware(request: Request, call_next):
|
||||||
async def auth_middleware(request: Request, call_next):
|
async def auth_middleware(request: Request, call_next):
|
||||||
"""Require the session token on all /api/ routes except the public list."""
|
"""Require the session token on all /api/ routes except the public list."""
|
||||||
path = request.url.path
|
path = request.url.path
|
||||||
if path.startswith("/api/") and path not in _PUBLIC_API_PATHS and not path.startswith("/api/plugins/"):
|
if path.startswith("/api/") and path not in _PUBLIC_API_PATHS:
|
||||||
if not _has_valid_session_token(request):
|
if not _has_valid_session_token(request):
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
status_code=401,
|
status_code=401,
|
||||||
|
|
|
||||||
|
|
@ -1826,6 +1826,49 @@ class TestNormaliseThemeExtensions:
|
||||||
assert r["componentStyles"]["card"] == {"opacity": "0.8", "zIndex": "5"}
|
assert r["componentStyles"]["card"] == {"opacity": "0.8", "zIndex": "5"}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TestPluginAPIAuth:
|
||||||
|
"""Tests that plugin API routes require the session token (issue #19533)."""
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def _setup_test_client(self, monkeypatch, _isolate_hermes_home):
|
||||||
|
"""Create a TestClient without the session token header."""
|
||||||
|
try:
|
||||||
|
from starlette.testclient import TestClient
|
||||||
|
except ImportError:
|
||||||
|
pytest.skip("fastapi/starlette not installed")
|
||||||
|
|
||||||
|
import hermes_state
|
||||||
|
from hermes_constants import get_hermes_home
|
||||||
|
from hermes_cli.web_server import app, _SESSION_HEADER_NAME, _SESSION_TOKEN
|
||||||
|
|
||||||
|
monkeypatch.setattr(hermes_state, "DEFAULT_DB_PATH", get_hermes_home() / "state.db")
|
||||||
|
|
||||||
|
self.client = TestClient(app)
|
||||||
|
self.auth_client = TestClient(app)
|
||||||
|
self.auth_client.headers[_SESSION_HEADER_NAME] = _SESSION_TOKEN
|
||||||
|
|
||||||
|
def test_plugin_route_requires_auth(self):
|
||||||
|
"""Plugin API routes should return 401 without a valid session token."""
|
||||||
|
# Use a known plugin route (kanban board)
|
||||||
|
resp = self.client.get("/api/plugins/kanban/board")
|
||||||
|
assert resp.status_code == 401
|
||||||
|
|
||||||
|
def test_plugin_route_allows_auth(self):
|
||||||
|
"""Plugin API routes should work with a valid session token."""
|
||||||
|
# This test verifies the fix doesn't break authenticated access.
|
||||||
|
# The kanban plugin may not be loaded in the test environment,
|
||||||
|
# so we accept 200 (plugin loaded) or 404 (plugin not mounted).
|
||||||
|
resp = self.auth_client.get("/api/plugins/kanban/board")
|
||||||
|
assert resp.status_code in (200, 404)
|
||||||
|
|
||||||
|
def test_plugin_post_requires_auth(self):
|
||||||
|
"""Plugin POST routes should return 401 without a valid session token."""
|
||||||
|
resp = self.client.post("/api/plugins/kanban/tasks", json={"title": "test"})
|
||||||
|
assert resp.status_code == 401
|
||||||
|
|
||||||
class TestDashboardPluginManifestExtensions:
|
class TestDashboardPluginManifestExtensions:
|
||||||
"""Tests for the extended plugin manifest fields (tab.override,
|
"""Tests for the extended plugin manifest fields (tab.override,
|
||||||
tab.hidden, slots) read by _discover_dashboard_plugins()."""
|
tab.hidden, slots) read by _discover_dashboard_plugins()."""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue