mirror of
https://github.com/nesquena/hermes-webui.git
synced 2026-06-04 16:10:24 +00:00
Merge pull request #3023
This commit is contained in:
+7
-3
@@ -690,8 +690,10 @@ class Session:
|
||||
|
||||
@classmethod
|
||||
def load(cls, sid):
|
||||
# Validate session ID format to prevent path traversal
|
||||
if not sid or not all(c in '0123456789abcdefghijklmnopqrstuvwxyz_' for c in sid):
|
||||
# Validate session ID format to prevent path traversal. API/gateway
|
||||
# session ids may contain hyphens (for example ``api-*`` and
|
||||
# ``reachy-voice-*``); allow those but still reject dots/slashes.
|
||||
if not sid or not all(c in '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-' for c in sid):
|
||||
return None
|
||||
p = SESSION_DIR / f'{sid}.json'
|
||||
if not p.exists():
|
||||
@@ -718,7 +720,9 @@ class Session:
|
||||
top-level "messages" field and synthesize a small metadata-only object.
|
||||
Falls back to load() for legacy or unexpected file layouts.
|
||||
"""
|
||||
if not sid or not all(c in '0123456789abcdefghijklmnopqrstuvwxyz_' for c in sid):
|
||||
# Same path-safety contract as load(): hyphens are valid session ids,
|
||||
# path separators and traversal dots are not.
|
||||
if not sid or not all(c in '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-' for c in sid):
|
||||
return None
|
||||
p = SESSION_DIR / f'{sid}.json'
|
||||
if not p.exists():
|
||||
|
||||
@@ -83,6 +83,28 @@ def test_compact_exposes_last_message_at_from_message_timestamp():
|
||||
assert compact["last_message_at"] == 200.0
|
||||
|
||||
|
||||
def test_session_load_allows_hyphenated_safe_ids_but_rejects_traversal():
|
||||
sid = "api-182894de593468b6"
|
||||
s = _make_session(sid, "API session", updated_at=100)
|
||||
s.path.write_text(json.dumps(s.__dict__, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
|
||||
assert Session.load(sid) is not None
|
||||
assert Session.load_metadata_only(sid) is not None
|
||||
assert Session.load("bad/../id") is None
|
||||
assert Session.load_metadata_only("bad.id") is None
|
||||
|
||||
|
||||
def test_full_index_rebuild_includes_hyphenated_sessions():
|
||||
sid = "reachy-voice-20260513-1131-d5542adf"
|
||||
s = _make_session(sid, "Reachy voice", updated_at=100)
|
||||
s.path.write_text(json.dumps(s.__dict__, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
|
||||
_write_session_index(updates=None)
|
||||
|
||||
ids = [entry["session_id"] for entry in _read_index(models.SESSION_INDEX_FILE)]
|
||||
assert sid in ids
|
||||
|
||||
|
||||
def test_prune_session_from_index_removes_requested_row_only():
|
||||
index_file = models.SESSION_INDEX_FILE
|
||||
s_a = _make_session("sess_a", "A", updated_at=100)
|
||||
|
||||
Reference in New Issue
Block a user