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:
mateo-berri 2026-05-19 06:39:34 +00:00
parent 5d65fdb4d8
commit 0ace1c4433
No known key found for this signature in database
2 changed files with 54 additions and 0 deletions

View file

@ -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"

View file

@ -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
# ---------------------------------------------------------------------------