fix(profiles): reject traversal-shaped profile names in get_profile_dir

A WS 'profile' param like '../../foo' normalized to a path component that
escaped the profiles root, letting a connected client bind an arbitrary
existing directory as a profile home (state.db opened there, and session
delete chains into per-id file cleanup under <dir>/sessions/).

get_profile_dir now validates the canonical name against the profile id
regex before joining it under profiles/. The regex only, not the reserved
list, so pre-reserved-list dirs like profiles/hermes keep resolving.
Callers that probe existence (profile_exists, _profile_home, the 4064
resolvers) treat ValueError as 'not found'.
This commit is contained in:
Adolanium
2026-09-11 18:39:41 +03:00
committed by Teknium
parent 6636b0896c
commit 2770f93064
6 changed files with 63 additions and 7 deletions
+4 -1
View File
@@ -67,7 +67,10 @@ def resolve_profile(rid, params, err_fn) -> Tuple[Optional[Any], Optional[dict]]
from hermes_cli.profiles import get_profile_dir
from hermes_constants import set_hermes_home_override
profile_dir = get_profile_dir(profile)
try:
profile_dir = get_profile_dir(profile)
except ValueError:
return None, err_fn(rid, 4064, f"profile '{profile}' not found")
if not profile_dir or not profile_dir.is_dir():
return None, err_fn(rid, 4064, f"profile '{profile}' not found")
return set_hermes_home_override(str(profile_dir)), None