{"record":{"id":"08332ca9b60abf86","repo":"BerriAI/litellm","slug":"invalid-identifier-identifier-r-path-traversal","errorCode":null,"errorMessage":"Invalid identifier {identifier!r}: path traversal detected","messagePattern":"Invalid identifier (.+?): path traversal detected","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/integrations/arize/arize_phoenix_client.py","lineNumber":16,"sourceCode":"\"\"\"\nArize Phoenix API client for fetching prompt versions from Arize Phoenix.\n\"\"\"\n\nimport urllib.parse\nfrom typing import Any, Final\n\nfrom litellm.llms.custom_httpx.http_handler import HTTPHandler\n\n\ndef _sanitize_id(identifier: str) -> str:\n    \"\"\"Reject path traversal characters and URL-encode the identifier.\"\"\"\n    if any(c in identifier for c in (\"/\", \"\\\\\", \"#\", \"?\")):\n        raise ValueError(f\"Invalid identifier {identifier!r}: contains disallowed characters\")\n    if \"..\" in identifier:\n        raise ValueError(f\"Invalid identifier {identifier!r}: path traversal detected\")\n    return urllib.parse.quote(identifier, safe=\"\")\n\n\nclass ArizePhoenixClient:\n    \"\"\"\n    Client for interacting with Arize Phoenix API to fetch prompt versions.\n\n    Supports:\n    - Authentication with Bearer tokens\n    - Fetching prompt versions\n    - Direct API base URL configuration\n    \"\"\"\n\n    def __init__(self, api_key: str | None = None, api_base: str | None = None):\n        \"\"\"\n        Initialize the Arize Phoenix client.\n\n        Args:","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/integrations/arize/arize_phoenix_client.py#L1-L34","documentation":"Companion guard to the disallowed-character check: `_sanitize_id` additionally rejects any identifier containing '..' even if it passed the character check, because '..' in a URL path segment enables path-traversal ('../' style) attacks against the Phoenix API base URL. This is a deliberate security check, not a formatting nit.","triggerScenarios":"Passing a prompt or prompt-version identifier containing '..' anywhere, e.g. prompt_version_id='../admin/prompt_versions', or an ID like 'my..prompt'. Raised synchronously in ArizePhoenixClient before any HTTP call.","commonSituations":"Unsanitized user input flowing into prompt_id from a web endpoint; test fixtures with placeholder IDs like '../id'; constructed IDs that concatenate directory-like segments.","solutions":["Pass only opaque identifiers issued by Phoenix; never build IDs from path-like segments","Sanitize external input before it reaches litellm: reject or encode any identifier containing '..'","Log the rejected identifier at your boundary so misuse is visible in your own telemetry"],"exampleFix":"# before\nprompt_version_id = \"../v1/prompt_versions/abc\"  # '..' -> path traversal ValueError\n\n# after\nprompt_version_id = \"abc\"  # opaque ID from Phoenix","handlingStrategy":"validation","validationCode":"def reject_traversal(identifier: str) -> str:\n    if \"..\" in identifier:\n        raise ValueError(\"path traversal sequence rejected\")\n    return identifier\n\nprompt_id = reject_traversal(raw_input)","typeGuard":"def is_traversal_free(identifier: str) -> bool:\n    return isinstance(identifier, str) and \"..\" not in identifier","tryCatchPattern":"try:\n    client.get_prompt_version(prompt_version_id)\nexcept ValueError as e:\n    if \"path traversal\" in str(e):\n        log.security(\"blocked traversal attempt: %r\", prompt_version_id)  # audit, do not retry\n    raise","preventionTips":["Treat '..' in identifiers as a security event: log and reject, never auto-clean","Generate IDs server-side where possible so user input never becomes a path component"],"tags":["arize-phoenix","path-traversal","security","input-validation","prompts"],"backgroundTag":"path-traversal-blocked","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}