{"record":{"id":"5e3e10079f79a37a","repo":"BerriAI/litellm","slug":"invalid-key-alias","errorCode":null,"errorMessage":"Invalid key_alias","messagePattern":"Invalid key_alias","errorType":"http","errorClass":"ProxyException","httpStatus":400,"severity":"warning","filePath":"litellm/proxy/management_endpoints/key_management_endpoints.py","lineNumber":6628,"sourceCode":"\n    The remaining charset/length rules are gated behind\n    ``litellm.enable_key_alias_format_validation`` (default **False**). When disabled,\n    only the baseline validation above is performed, so existing workflows are not\n    broken.\n\n    Rules (when enabled):\n    - None is OK (no alias).\n    - Otherwise must be 2–255 chars\n    - start/end with alphanumeric\n    - only allow a-zA-Z0-9_-/.@\n    \"\"\"\n    if key_alias is None:\n        return\n\n    try:\n        raise_if_unsafe_secret_name(key_alias)\n    except ValueError:\n        raise ProxyException(\n            message=\"Invalid key_alias\",\n            type=ProxyErrorTypes.bad_request_error,\n            param=\"key_alias\",\n            code=400,\n        )\n\n    if not litellm.enable_key_alias_format_validation:\n        return\n\n    if not _KEY_ALIAS_PATTERN.match(key_alias):\n        raise ProxyException(\n            message=\"Invalid key_alias format. Must be 2-255 characters, start/end with alphanumeric, and only contain a-zA-Z0-9_-/.@.\",\n            type=ProxyErrorTypes.bad_request_error,\n            param=\"key_alias\",\n            code=400,\n        )\n\n","sourceCodeStart":6610,"sourceCodeEnd":6646,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/management_endpoints/key_management_endpoints.py#L6610-L6646","documentation":"Key aliases are validated with the same guard LiteLLM uses for secret-manager names (raise_if_unsafe_secret_name) before any format checks. The guard rejects '..' appearing as a whole path segment ('../x', 'x/..', or exactly '..') and any ASCII control characters (\\x00-\\x1f, \\x7f-\\x9f, which includes tabs and newlines), because aliases can flow into secret-manager lookups. A violation becomes a 400 ProxyException with param='key_alias' and the terse message 'Invalid key_alias'.","triggerScenarios":"POST /key/generate or /key/update with key_alias='../secrets/openai', 'team/../prod', '..', or an alias pasted from a terminal that embedded a tab/newline (e.g. 'prod\\talias').","commonSituations":"Aliases derived from file paths or branch names; YAML/JSON config files where the alias string accidentally spans lines; CI variables containing trailing carriage returns on Windows.","solutions":["Remove '..' segments and any '/'-path traversal patterns from the alias","Sanitize the string: strip control characters (alias = ''.join(c for c in alias if c >= ' ' and c != chr(127))) or just c.strip() plus a printable-check","Prefer flat slugs like 'team-prod-readonly' over path-shaped names","Note this check always runs — it is not gated by litellm.enable_key_alias_format_validation"],"exampleFix":"# before\nawait client.post('/key/generate', json={'key_alias': '../secrets/prod'})   # 400: Invalid key_alias\n# after\nawait client.post('/key/generate', json={'key_alias': 'prod-readonly-alias'})","handlingStrategy":"validation","validationCode":"import re\n\n_UNSAFE_SECRET_NAME = re.compile(r'(^|/)\\.\\.(/|$)|[\\x00-\\x1f\\x7f-\\x9f]')\n\ndef sanitize_alias(alias: str) -> str:\n    cleaned = re.sub(r'[\\x00-\\x1f\\x7f-\\x9f]', '', alias)\n    cleaned = '/'.join(seg for seg in cleaned.split('/') if seg != '..')\n    return cleaned","typeGuard":"def is_safe_alias(alias: str) -> bool:\n    return bool(alias) and _UNSAFE_SECRET_NAME.search(alias) is None","tryCatchPattern":"try:\n    await client.post('/key/generate', json={'key_alias': alias, **rest})\nexcept httpx.HTTPStatusError as e:\n    if e.response.status_code == 400 and 'key_alias' in e.response.text:\n        await client.post('/key/generate', json={'key_alias': sanitize_alias(alias), **rest})\n    else:\n        raise","preventionTips":["Never derive aliases from raw filesystem paths or branch names without sanitizing","Add a printable-ASCII assertion wherever aliases enter the system (UI forms, YAML, CSV import)","Remember this traversal check runs even when format validation is disabled"],"tags":["key-alias","validation","path-traversal","litellm-proxy","sanitization"],"backgroundTag":"path-traversal-blocked","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}