OpenBMB/ChatDev · warning · ValidationError

Invalid session_id: only letters, digits, underscores, and h

Error message

Invalid session_id: only letters, digits, underscores, and hyphens are allowed

What it means

download_session validates session_id against an allowlist (letters, digits, underscores, hyphens) and logs a security event INVALID_SESSION_ID_FORMAT before raising ValidationError. This is a path-traversal guard for the warehouse directory lookup.

Source

Thrown at server/routes/sessions.py:27

from server.settings import WARE_HOUSE_DIR
from utils.exceptions import ResourceNotFoundError, ValidationError
from utils.structured_logger import get_server_logger, LogType

router = APIRouter()


@router.get("/api/sessions/{session_id}/download")
async def download_session(session_id: str):
    try:
        if not re.match(r"^[a-zA-Z0-9_-]+$", session_id):
            logger = get_server_logger()
            logger.log_security_event(
                "INVALID_SESSION_ID_FORMAT",
                f"Invalid session_id format: {session_id}",
                details={"received_session_id": session_id},
            )
            raise ValidationError(
                "Invalid session_id: only letters, digits, underscores, and hyphens are allowed",
                field="session_id",
            )

        dir_name = f"session_{session_id}"
        session_path = WARE_HOUSE_DIR / dir_name

        if not session_path.exists() or not session_path.is_dir():
            raise ResourceNotFoundError(
                "Session directory not found",
                resource_type="session",
                resource_id=session_id,
            )

        with tempfile.NamedTemporaryFile(delete=False, suffix=".zip") as tmp_file:
            zip_path = Path(tmp_file.name)

        archive_base = zip_path.with_suffix("")

View on GitHub (pinned to 4fb2db0ea9)

Solutions

  1. Strip any 'session_' prefix and slashes from the ID before calling
  2. Use only the exact session_id returned when the session was created
  3. URL-encode the path segment properly and avoid raw ../ sequences
  4. Add a client-side regex check: ^[A-Za-z0-9_-]+$

Example fix

# before
session_id = "session_abc123/.."
# after
session_id = "abc123"
Defensive patterns

Strategy: type-guard

Validate before calling

import re
SESSION_ID_RE = re.compile(r'^[A-Za-z0-9_-]+$')
if not SESSION_ID_RE.match(session_id):
    raise ValueError('bad session_id format')

Type guard

def is_safe_session_id(sid: str) -> bool:
    import re
    return bool(re.fullmatch(r'[A-Za-z0-9_-]+', sid))

Try / catch

except HTTPError as e:
    if e.response.status_code == 400 and 'Invalid session_id' in e.response.text:
        session_id = extract_raw_id(session_id); retry()

Prevention

When it happens

Trigger: GET session download with session_id containing slashes, dots (../), spaces, percent-encoded separators, or any character outside [A-Za-z0-9_-].

Common situations: Passing a full directory name like session_abc123 instead of the bare ID; unencoded special characters from URLs; attempted or accidental path traversal strings.

Related errors


AI-assisted analysis of OpenBMB/ChatDev@4fb2db0ea9 (2026-08-27). Data as JSON: /api/errors/ae7a2b41dedd137e. Report an issue: GitHub.