mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-25 11:02:03 +00:00
fix(V-009): reject Windows drive-letter paths in session field validation
Extends the CWE-22 path traversal guard to cover Windows absolute paths of the form C:/... and D:\... — previously only leading / and \ were checked, which missed drive-letter prefixes. Replaces the inline startswith check with a compiled module-level regex (_TRAVERSAL_RE) that covers all three attack patterns: .., leading /\, and leading X: drives. Adds two regression tests for C:/windows/system32 and D:\\path\\to\\file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3a6a43cb81
commit
aa2aac68b0
2 changed files with 17 additions and 1 deletions
|
|
@ -12,6 +12,7 @@ import hashlib
|
|||
import logging
|
||||
import os
|
||||
import json
|
||||
import re
|
||||
import threading
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
|
|
@ -66,6 +67,11 @@ from .whatsapp_identity import (
|
|||
)
|
||||
from utils import atomic_replace
|
||||
|
||||
# Matches any value that could escape the sessions directory as a file path.
|
||||
# Covers: directory traversal (..), Unix/Windows absolute paths (/ \),
|
||||
# and Windows drive-letter paths (C:/ D:\\ etc.).
|
||||
_TRAVERSAL_RE = re.compile(r'\.\.|^[/\\]|^[A-Za-z]:')
|
||||
|
||||
|
||||
@dataclass
|
||||
class SessionSource:
|
||||
|
|
@ -578,7 +584,7 @@ class SessionEntry:
|
|||
|
||||
# Validate path-sensitive fields to prevent directory traversal (CWE-22)
|
||||
for _field, _val in (("session_key", session_key), ("session_id", session_id)):
|
||||
if _val and (".." in str(_val) or str(_val).startswith(("/", "\\"))):
|
||||
if _val and _TRAVERSAL_RE.search(str(_val)):
|
||||
raise ValueError(
|
||||
f"Invalid {_field}: potential directory traversal detected"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1085,6 +1085,16 @@ class TestSessionEntryFromDictTraversalValidation:
|
|||
with pytest.raises(ValueError, match="session_id"):
|
||||
SessionEntry.from_dict(self._entry(session_id="\\windows\\system32\\config"))
|
||||
|
||||
def test_session_id_windows_drive_letter_raises(self):
|
||||
from gateway.session import SessionEntry
|
||||
with pytest.raises(ValueError, match="session_id"):
|
||||
SessionEntry.from_dict(self._entry(session_id="C:/windows/system32"))
|
||||
|
||||
def test_session_id_windows_drive_backslash_raises(self):
|
||||
from gateway.session import SessionEntry
|
||||
with pytest.raises(ValueError, match="session_id"):
|
||||
SessionEntry.from_dict(self._entry(session_id="D:\\path\\to\\file"))
|
||||
|
||||
|
||||
class TestEnsureLoadedSkipsInvalidEntries:
|
||||
"""Regression: one bad sessions.json entry must not block valid entries from loading."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue