mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-27 01:22:18 +00:00
fix(oci): validate oci_region before URL interpolation to prevent SSRF
Anchor oci_region to ^[a-z][a-z0-9-]{0,30}[a-z0-9]$ inside get_oci_base_url
so user-supplied regions that would redirect the signed request to an
attacker-controlled host (e.g. 'evil.com/#') fail with HTTP 400 before
the URL or signature is built. Empty string still falls back to the
us-ashburn-1 default, so existing callers are unaffected.
This commit is contained in:
parent
5d65fdb4d8
commit
0ace1c4433
2 changed files with 54 additions and 0 deletions
|
|
@ -3,6 +3,7 @@ import datetime
|
|||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Dict, Optional, Protocol, Tuple
|
||||
from urllib.parse import urlparse
|
||||
|
|
@ -185,12 +186,23 @@ def resolve_oci_credentials(optional_params: dict) -> dict:
|
|||
}
|
||||
|
||||
|
||||
_OCI_REGION_RE = re.compile(r"^[a-z][a-z0-9-]{0,30}[a-z0-9]$")
|
||||
|
||||
|
||||
def get_oci_base_url(optional_params: dict, api_base: Optional[str] = None) -> str:
|
||||
"""Return the OCI inference base URL, respecting any explicit api_base override."""
|
||||
if api_base:
|
||||
return api_base.rstrip("/")
|
||||
creds = resolve_oci_credentials(optional_params)
|
||||
region = creds["oci_region"]
|
||||
if not isinstance(region, str) or not _OCI_REGION_RE.match(region):
|
||||
raise OCIError(
|
||||
status_code=400,
|
||||
message=(
|
||||
f"Invalid OCI region {region!r}: must match "
|
||||
"^[a-z][a-z0-9-]{0,30}[a-z0-9]$ (e.g. 'us-ashburn-1')."
|
||||
),
|
||||
)
|
||||
return f"https://inference.generativeai.{region}.oci.oraclecloud.com"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -157,6 +157,48 @@ def test_get_oci_base_url_from_region():
|
|||
assert url == "https://inference.generativeai.eu-frankfurt-1.oci.oraclecloud.com"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"region",
|
||||
[
|
||||
"evil.com/#",
|
||||
"evil.com",
|
||||
"us-ashburn-1/../attacker",
|
||||
"ATTACKER",
|
||||
"-leading-hyphen",
|
||||
"trailing-hyphen-",
|
||||
"a",
|
||||
"a" * 33,
|
||||
"us ashburn 1",
|
||||
"us_ashburn_1",
|
||||
],
|
||||
)
|
||||
def test_get_oci_base_url_rejects_unsafe_region(region):
|
||||
with pytest.raises(OCIError, match="Invalid OCI region"):
|
||||
get_oci_base_url({"oci_region": region})
|
||||
|
||||
|
||||
def test_get_oci_base_url_empty_region_falls_back_to_default(monkeypatch):
|
||||
monkeypatch.delenv("OCI_REGION", raising=False)
|
||||
url = get_oci_base_url({"oci_region": ""})
|
||||
assert url == "https://inference.generativeai.us-ashburn-1.oci.oraclecloud.com"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"region",
|
||||
[
|
||||
"us-ashburn-1",
|
||||
"eu-frankfurt-1",
|
||||
"ap-tokyo-1",
|
||||
"us-chicago-1",
|
||||
"us-phoenix-1",
|
||||
"ap",
|
||||
],
|
||||
)
|
||||
def test_get_oci_base_url_accepts_valid_region(region):
|
||||
url = get_oci_base_url({"oci_region": region})
|
||||
assert url == f"https://inference.generativeai.{region}.oci.oraclecloud.com"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# validate_oci_environment
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue