BerriAI/litellm · error · ValueError

Path parameter '{param_name}' cannot include '.' or '..' seg

Error message

Path parameter '{param_name}' cannot include '.' or '..' segments

What it means

Second guard in _sanitize_path_parameter_value in the OpenAPI-to-MCP generator: after the slash check, the value is parsed with PurePosixPath and any '.' or '..' segment raises this ValueError, preventing dot-segment traversal (e.g. a value of '..' escaping one path level). Because any '/' already raised the earlier error, this branch in practice fires for a parameter whose entire value is '..' (or a lone '.' in callers that pre-split segments). Like the sibling error it is returned as "Invalid path parameter: ..." on the generated tool path.

Source

Thrown at litellm/proxy/_experimental/mcp_server/openapi_to_mcp_generator.py:124

    "_request_resolved_auth_headers", default=None
)


def _sanitize_path_parameter_value(param_value: object, param_name: str) -> str:
    """Ensure path params cannot introduce directory traversal."""
    if param_value is None:
        return ""

    value_str: Final = str(param_value)
    if value_str == "":
        return ""

    normalized_value: Final = value_str.replace("\\", "/")
    if "/" in normalized_value:
        raise ValueError(f"Path parameter '{param_name}' must not contain path separators")

    if any(part in {".", ".."} for part in PurePosixPath(normalized_value).parts):
        raise ValueError(f"Path parameter '{param_name}' cannot include '.' or '..' segments")

    return quote(value_str, safe="")


def load_openapi_spec(filepath: str) -> dict[str, Any]:
    """
    Sync wrapper. For URL specs, use the shared/custom MCP httpx client.
    """
    try:
        # If we're already inside an event loop, prefer the async function.
        asyncio.get_running_loop()
        raise RuntimeError(
            "load_openapi_spec() was called from within a running event loop. "
            "Use 'await load_openapi_spec_async(...)' instead."
        )
    except RuntimeError as e:
        # "no running event loop" is fine; other RuntimeErrors we re-raise
        if "no running event loop" not in str(e).lower():

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Pass a concrete segment value, never a dot-relative path component.
  2. If the value comes from filesystem logic, resolve it (Path(x).resolve().name) or validate it before sending it to the tool.
  3. Treat this error text in a tool result as untrusted-input feedback: reject the caller's input in your own app with a 4xx rather than retrying.

Example fix

# before
parent = os.path.join(base, "..")  # leaks '..'
await call_mcp_tool(server_id="fs", tool_name="list_dir", arguments={"path": parent})

# after
parent = os.path.basename(os.path.normpath(os.path.join(base, "..")))
await call_mcp_tool(server_id="fs", tool_name="list_dir", arguments={"path": parent})
Defensive patterns

Strategy: validation

Validate before calling

def has_no_dot_segments(value: object) -> bool:
    s = "" if value is None else str(value)
    if "/" in s or "\\" in s:
        return False
    return s not in (".", "..")

assert has_no_dot_segments(args[name]), f"{name} must be a concrete segment"

Type guard

from typing import TypeGuard

def is_safe_path_segment(value: object) -> TypeGuard[str]:
    if not isinstance(value, str) or not value:
        return False
    return "/" not in value and "\\" not in value and value not in (".", "..")

Try / catch

try:
    safe = _sanitize_path_parameter_value(value, name)
except ValueError as e:
    raise BadRequest(str(e)) from None
# REST callers: a result string "Invalid path parameter: Path parameter 'x' cannot include '.' or '..' segments" is a permanent 4xx

Prevention

When it happens

Trigger: Calling a generated MCP tool with a path parameter value of exactly ".." (or ".") for a path like /files/{parent}/items/{name}; commonly happens when a caller computes the parent segment with os.path and accidentally passes the '..' produced by a relative path.

Common situations: Defaulted/empty-optional arguments that fall back to '..'; path manipulation code (os.path.join, pathlib) leaking dot segments into tool args; test fixtures that use '..' as a sentinel ID.

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/619a654c1bf0b898. Report an issue: GitHub.