[Security] Cap Qwen-VL video sampling knobs (#56729)

Signed-off-by: Juan Pérez de Algaba <jperezde@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>

Juan Pérez de Algaba committed Sep 14, 2026 at 12:22 UTC ea723c81c3ea26425cb69503a5d5e90822a04a45
1 file changed +10 -4
vllm/multimodal/video.py
+10 -4
@@ -357,6 +357,9 @@ class PyNvVideoCodecVideoBackend(VideoBackend):
357 video_processor=("Qwen3VLVideoProcessor", "Cosmos3EdgeVideoProcessor"),
358 )
359 class Qwen3VLVideoBackend(VideoBackend):
360 + _MAX_FRAMES: ClassVar[int] = 768
361 + _MAX_FPS: ClassVar[int] = 30
362 +
363 @classmethod
364 def compute_frames_index_to_sample(
365 cls,
@@ -366,10 +369,10 @@ class Qwen3VLVideoBackend(VideoBackend):
369 ) -> list[int]:
370 total_frames_num = source.total_frames_num
371 original_fps = source.original_fps
369 - fps = target.fps
372 + fps = min(target.fps, cls._MAX_FPS)
373 max_frame_idx = source.total_frames_num - 1
374 min_frames = kwargs.get("min_frames", 4)
372 - max_frames = kwargs.get("max_frames", 768)
375 + max_frames = min(kwargs.get("max_frames", cls._MAX_FRAMES), cls._MAX_FRAMES)
376
377 # Refer to:
378 # https://github.com/huggingface/transformers/blob/v5.9.0/src/transformers/models/qwen3_vl/video_processing_qwen3_vl.py#L119-L125
@@ -420,6 +423,9 @@ class Qwen2VLVideoBackend(VideoBackend):
423 clip); it is clamped to the last valid frame.
424 """
425
426 + _MAX_FRAMES: ClassVar[int] = 768
427 + _MAX_FPS: ClassVar[int] = 30
428 +
429 @classmethod
430 def compute_frames_index_to_sample(
431 cls,
@@ -433,7 +439,7 @@ class Qwen2VLVideoBackend(VideoBackend):
439 original_fps = source.original_fps
440 temporal_patch_size = kwargs.get("temporal_patch_size", 2)
441 min_frames = kwargs.get("min_frames", 4)
436 - max_frames = kwargs.get("max_frames", 768)
442 + max_frames = min(kwargs.get("max_frames", cls._MAX_FRAMES), cls._MAX_FRAMES)
443
444 # vLLM reports original_fps == 0 for clips with unknown/variable fps
445 # (VFR, malformed, streaming); fail loudly instead of dividing by zero.
@@ -447,7 +453,7 @@ class Qwen2VLVideoBackend(VideoBackend):
453 math.floor(min(max_frames, total_frames_num) / temporal_patch_size)
454 * temporal_patch_size
455 )
450 - n = total_frames_num / original_fps * target.fps
456 + n = total_frames_num / original_fps * min(target.fps, cls._MAX_FPS)
457 n = min(max(n, min_frames), max_frames, total_frames_num)
458 n = math.floor(n / temporal_patch_size) * temporal_patch_size
459