BerriAI/litellm · warning · ValueError
Invalid file path {file_path!r}: path traversal detected
Error message
Invalid file path {file_path!r}: path traversal detected What it means
The second branch of _sanitize_file_path: after splitting the path on '/', any segment equal to '..' triggers a path-traversal rejection. This prevents crafted paths from escaping the intended repository directory in the constructed BitBucket API URL. The check runs on the literal segment value before URL-encoding, so an encoded '%2E%2E' that later decodes to '..' upstream would still need to be literal here to be caught — the guard is on the raw input.
Source
Thrown at litellm/integrations/bitbucket/bitbucket_client.py:19
"""
BitBucket API client for fetching .prompt files from BitBucket repositories.
"""
import base64
import urllib.parse
from typing import Any, Final
from litellm.llms.custom_httpx.http_handler import HTTPHandler
def _sanitize_file_path(file_path: str) -> str:
"""Reject path traversal and URL-encode each path segment."""
if "#" in file_path or "?" in file_path:
raise ValueError(f"Invalid file path {file_path!r}: contains URL special characters")
parts: Final = file_path.split("/")
for part in parts:
if part == "..":
raise ValueError(f"Invalid file path {file_path!r}: path traversal detected")
return "/".join(urllib.parse.quote(part, safe="") for part in parts)
class BitBucketClient:
"""
Client for interacting with BitBucket API to fetch .prompt files.
Supports:
- Authentication with access tokens
- Fetching file contents from repositories
- Team-based access control through BitBucket permissions
- Branch-specific file fetching
"""
def __init__(self, config: dict[str, Any]):
"""
Initialize the BitBucket client.
View on GitHub (pinned to 6c2dcb801b)
Solutions
- Use a flat or explicitly allow-listed path — drop '..' segments from the file path / prompt_id
- Canonicalize and re-verify external paths (e.g. os.path.normpath then confirm the result stays under the allowed root) before passing them in
- Rename repository layout if legitimate files need relative-style references
Example fix
# before
client.get_file("prompts/../internal/admin.prompt") # ValueError: path traversal detected
# after
client.get_file("internal/admin.prompt") # reference the target directly Defensive patterns
Strategy: validation
Validate before calling
import posixpath
def normalize_repo_path(root: str, file_path: str) -> str:
if ".." in file_path.split("/"):
raise ValueError("path traversal not allowed")
normalized = posixpath.normpath(f"{root}/{file_path}").lstrip("/")
if normalized.startswith("..") or normalized.startswith("/"):
raise ValueError("path escapes allowed root")
return normalized Type guard
def is_within_root(root: str, p: str) -> bool:
if not isinstance(p, str) or ".." in p.split("/"):
return False
n = posixpath.normpath(p)
return not n.startswith("..") and not posixpath.isabs(n) Try / catch
try:
client.get_file(prompt_id)
except ValueError as e:
if "path traversal" in str(e):
# untrusted input: log the security event and reject the request entirely
security_log.warning("rejected traversal path: %r", prompt_id)
raise
raise Prevention
- Treat prompt IDs / paths from users as untrusted; reject '..' segments at the API boundary
- Prefer flat IDs mapped through a server-side lookup table to actual paths
- Run path normalization (normpath) plus a prefix check against the allowed root before any fetch
- Log and alert on traversal attempts — they indicate probing
When it happens
Trigger: Passing a file path with a '..' segment such as 'prompts/../../secrets/config' to get_file; prompt_id sourced from untrusted user input concatenated into a path; test payloads for path traversal.
Common situations: Prompt IDs built by string concatenation with user input; attempting to reference files outside the configured prompts directory; security scanners probing the integration.
Related errors
- {field_name} cannot be a dot path segment
- Invalid file path {file_path!r}: contains URL special charac
- workspace, repository, and access_token are required
- Template '{template_id}' not found
- Prompt template '{prompt_id}' not found
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/b928d1981b6cee88.
Report an issue: GitHub.