BerriAI/litellm · error · ValueError

cannot be a dot path segment

Error message

{field_name} cannot be a dot path segment

What it means

ValueError raised by encode_url_path_segment when the segment is exactly '.' or '..'. urllib.parse.quote deliberately leaves RFC 3986 unreserved characters (including '.') unescaped, so standalone dot segments are rejected explicitly — otherwise they would be joined into the upstream URL and normalized by the HTTP client into a path traversal.

Solutions

  1. Validate ids against a strict format (UUID, charset whitelist) at the boundary and reject '.'/'..' with 400.
  2. Treat identifiers as opaque tokens; never accept path fragments as ids.
  3. If the value is legitimately a filename, apply a basename/allowlist check before encoding.

Example fix

# before
file_id = request.get("file_id")  # ".."
path = encode_url_path_segment(file_id)  # ValueError: file_id cannot be a dot path segment

# after
file_id = request.get("file_id", "")
if not re.fullmatch(r"[A-Za-z0-9_-]{1,128}", file_id):
    raise HTTPException(status_code=400, detail="invalid file_id")
path = encode_url_path_segment(file_id, field_name="file_id")
Defensive patterns

Strategy: validation

Validate before calling

import re

ID_RE = re.compile(r"[A-Za-z0-9_-]{1,128}")
file_id = request.get("file_id", "")
if file_id in {".", ".."} or not ID_RE.fullmatch(file_id):
    raise HTTPException(status_code=400, detail="invalid file_id")
path = encode_url_path_segment(file_id, field_name="file_id")

Type guard

import re

ID_RE = re.compile(r"[A-Za-z0-9_-]{1,128}")

def is_safe_path_segment(value: str) -> bool:
    return bool(value) and value not in {".", ".."} and bool(ID_RE.fullmatch(value))

Try / catch

try:
    path = encode_url_path_segment(value, field_name="file_id")
except ValueError as e:
    if "dot path segment" in str(e):
        logger.warning("path traversal attempt blocked: %r", value)
    raise HTTPException(status_code=400, detail=str(e))

Prevention

When it happens

Trigger: User-controlled ids, filenames, or keys equal to '.' or '..' reaching encode_url_path_segment, e.g. ?file_id=.. on a route that builds /files/{file_id} for the upstream provider.

Common situations: Security scanners and penetration tests probing path-based routes; clients sending relative path components as identifiers; path fragments copied wholesale and reused as ids.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/5cdcbc6bd31d37f5. Report an issue: GitHub.

Appendix: source

Thrown at litellm/litellm_core_utils/url_utils.py:62

    """Raised when a URL targets a blocked network."""


def encode_url_path_segment(value: Any, *, field_name: str = "path parameter") -> str:
    """Percent-encode one user-controlled URL path segment.

    ``urllib.parse.quote(..., safe="")`` intentionally leaves RFC 3986
    unreserved characters such as ``.`` unescaped, so reject standalone dot
    segments before they can be appended to an upstream URL and normalized by
    the HTTP client.
    """
    if value is None:
        raise ValueError(f"{field_name} is required")

    value_str: Final = str(value)
    if value_str == "":
        raise ValueError(f"{field_name} is required")
    if value_str in {".", ".."}:
        raise ValueError(f"{field_name} cannot be a dot path segment")

    return quote(value_str, safe="")


def encode_url_path_segments(value: Any, *, field_name: str = "path") -> str:
    """Percent-encode a user-controlled URL path made of multiple segments.

    Empty segments are rejected, so leading, trailing, or consecutive slashes
    fail closed instead of being normalized by the HTTP client.
    """
    if value is None:
        raise ValueError(f"{field_name} is required")

    value_str: Final = str(value)
    if value_str == "":
        raise ValueError(f"{field_name} is required")

    encoded_segments: Final = []

View on GitHub (pinned to 77b7c6c40c)