mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
fix(runwayml): fetch provider output URLs via safe_get
RunwayML video content and TTS download paths called httpx directly on provider-returned output URLs with no SSRF validation. Route those fetches through safe_get/async_safe_get (same as Black Forest Labs image_edit) so private/link-local targets and unsafe redirects are rejected.
This commit is contained in:
parent
e24a9146e3
commit
e04577d8d9
2 changed files with 10 additions and 9 deletions
|
|
@ -22,6 +22,7 @@ from litellm.llms.base_llm.text_to_speech.transformation import (
|
|||
TextToSpeechRequestData,
|
||||
)
|
||||
from litellm.secret_managers.main import get_secret_str
|
||||
from litellm.litellm_core_utils.url_utils import async_safe_get, safe_get
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
|
||||
|
|
@ -496,11 +497,11 @@ class RunwayMLTextToSpeechConfig(BaseTextToSpeechConfig):
|
|||
if not isinstance(audio_url, str):
|
||||
raise ValueError(f"RunwayML TTS audio URL is not a string: {audio_url}")
|
||||
|
||||
# Download the audio file
|
||||
# Download the audio file with SSRF guards (provider output URLs are untrusted).
|
||||
from litellm.llms.custom_httpx.http_handler import _get_httpx_client
|
||||
|
||||
client: Final = _get_httpx_client()
|
||||
audio_response: Final = client.get(url=audio_url)
|
||||
audio_response: Final = safe_get(client, audio_url)
|
||||
audio_response.raise_for_status()
|
||||
|
||||
verbose_logger.debug("RunwayML TTS audio downloaded successfully")
|
||||
|
|
@ -565,11 +566,11 @@ class RunwayMLTextToSpeechConfig(BaseTextToSpeechConfig):
|
|||
if not isinstance(audio_url, str):
|
||||
raise ValueError(f"RunwayML TTS audio URL is not a string: {audio_url}")
|
||||
|
||||
# Download the audio file (async)
|
||||
# Download the audio file (async) with SSRF guards.
|
||||
from litellm.llms.custom_httpx.http_handler import get_async_httpx_client
|
||||
|
||||
client: Final = get_async_httpx_client(llm_provider=litellm.LlmProviders.RUNWAYML)
|
||||
audio_response: Final = await client.get(url=audio_url)
|
||||
audio_response: Final = await async_safe_get(client, audio_url)
|
||||
audio_response.raise_for_status()
|
||||
|
||||
verbose_logger.debug("RunwayML TTS audio downloaded successfully (async)")
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from httpx._types import RequestFiles
|
|||
|
||||
import litellm
|
||||
from litellm.constants import RUNWAYML_DEFAULT_API_VERSION
|
||||
from litellm.litellm_core_utils.url_utils import encode_url_path_segment
|
||||
from litellm.litellm_core_utils.url_utils import async_safe_get, encode_url_path_segment, safe_get
|
||||
from litellm.llms.base_llm.chat.transformation import BaseLLMException
|
||||
from litellm.llms.base_llm.videos.transformation import BaseVideoConfig
|
||||
from litellm.llms.custom_httpx.http_handler import (
|
||||
|
|
@ -376,9 +376,9 @@ class RunwayMLVideoConfig(BaseVideoConfig):
|
|||
response_data: Final = raw_response.json()
|
||||
video_url: Final = self._extract_video_url_from_response(response_data)
|
||||
|
||||
# Download the video from the CloudFront URL synchronously
|
||||
# Download the video from the provider URL with SSRF guards (same as BFL image_edit).
|
||||
httpx_client: Final[HTTPHandler] = _get_httpx_client()
|
||||
video_response: Final = httpx_client.get(video_url)
|
||||
video_response: Final = safe_get(httpx_client, video_url)
|
||||
video_response.raise_for_status()
|
||||
|
||||
return video_response.content
|
||||
|
|
@ -405,11 +405,11 @@ class RunwayMLVideoConfig(BaseVideoConfig):
|
|||
response_data: Final = raw_response.json()
|
||||
video_url: Final = self._extract_video_url_from_response(response_data)
|
||||
|
||||
# Download the video from the CloudFront URL asynchronously
|
||||
# Download the video from the provider URL with SSRF guards (same as BFL image_edit).
|
||||
async_httpx_client: Final[AsyncHTTPHandler] = get_async_httpx_client(
|
||||
llm_provider=litellm.LlmProviders.RUNWAYML,
|
||||
)
|
||||
video_response: Final = await async_httpx_client.get(video_url)
|
||||
video_response: Final = await async_safe_get(async_httpx_client, video_url)
|
||||
video_response.raise_for_status()
|
||||
|
||||
return video_response.content
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue