vLLM: Qwen2-VL / Qwen3-VL video samplers bound on request-controlled max_frames, which the num_frames ceiling does not reach
### Summary An unauthenticated remote attacker can exhaust the memory of the vLLM API-server process by raising the request-level `media_io_kwargs.video.max_frames` and `fps` knobs on any deployment serving a Qwen2-VL or Qwen3-VL model. 74 extra bytes of JSON took the server's peak RSS from 2 271 MiB to 13 629 MiB over unauthenticated `POST /tokenize`. The `num_frames` ceiling reported in GHSA-vxqj-p4gw-9h4c and fixed by open PR #51969 does not reach this path: the Qwen samplers do not read `num_frames` at all. The same knobs were already capped upstream for `GLMGAVideoBackend` as an accepted security fix in `8b6de0eb9` (PR #54935, merged 2026-09-04); that cap never reached Qwen. ### Details #### Relationship to GHSA-vxqj-p4gw-9h4c and PR #51969 (read this first) GHSA-vxqj-p4gw-9h4c reported that request-level `media_io_kwargs.video.num_frames` overrides the engine frame-count ceiling, and open PR #51969 fixes it by clamping `num_frames` inside `VideoMediaIO.merge_kwargs`. That clamp does not reach the Qwen samplers. `Qwen2VLVideoBackend` and `Qwen3VLVideoBackend` do not read `num_frames` at all — `Qwen2VLVideoBackend`'s own docstring says so ("``num_frames`` is ignored (fps-driven, like the Qwen3-VL loader)"). They bound on `max_frames`, read from the same merged dict with no ceiling: ```python # vllm/multimodal/video.py — Qwen3VLVideoBackend.compute_frames_index_to_sample min_frames = kwargs.get("min_frames", 4) max_frames = kwargs.get("max_frames", 768) num_frames = int(to
- Products
- vllm
- Affected versions
- 0.24.0, 0.25.0, 0.25.1, 0.26.0, 0.27.0, 0.27.1, 0.28.0, 0.29.0
- Fixed versions
- 0.30.0
- CVEs
- CVE-2026-105758
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 30 Oct 2026, 18:15 UTC · Revision 1
Source evidence
vLLM: Qwen2-VL / Qwen3-VL video samplers bound on request-controlled max_frames, which the num_frames ceiling does not reach
core-osv · Original sourcePublished 5 Oct 2026, 23:42 UTC
### Summary An unauthenticated remote attacker can exhaust the memory of the vLLM API-server process by raising the request-level `media_io_kwargs.video.max_frames` and `fps` knobs on any deployment serving a Qwen2-VL or Qwen3-VL model. 74 extra bytes of JSON took the server's peak RSS from 2 271 MiB to 13 629 MiB over unauthenticated `POST /tokenize`. The `num_frames` ceiling reported in GHSA-vxqj-p4gw-9h4c and fixed by open PR #51969 does not reach this path: the Qwen samplers do not read `num_frames` at all. The same knobs were already capped upstream for `GLMGAVideoBackend` as an accepted security fix in `8b6de0eb9` (PR #54935, merged 2026-09-04); that cap never reached Qwen. ### Details #### Relationship to GHSA-vxqj-p4gw-9h4c and PR #51969 (read this first) GHSA-vxqj-p4gw-9h4c reported that request-level `media_io_kwargs.video.num_frames` overrides the engine frame-count ceiling, and open PR #51969 fixes it by clamping `num_frames` inside `VideoMediaIO.merge_kwargs`. That clamp does not reach the Qwen samplers. `Qwen2VLVideoBackend` and `Qwen3VLVideoBackend` do not read `num_frames` at all — `Qwen2VLVideoBackend`'s own docstring says so ("``num_frames`` is ignored (fps-driven, like the Qwen3-VL loader)"). They bound on `max_frames`, read from the same merged dict with no ceiling: ```python # vllm/multimodal/video.py — Qwen3VLVideoBackend.compute_frames_index_to_sample min_frames = kwargs.get("min_frames", 4) max_frames = kwargs.get("max_frames", 768) num_frames = int(to
osv:GHSA-x6mc-67gf-chw4
vllm
Fixed versions: 0.30.0
Complete source record
{
"id": "25429f2ae087869e14173ca8b16b1a0f7f3b58a5840adefc5b81ad8c7d44b0b3",
"url": "https://osv.dev/vulnerability/GHSA-x6mc-67gf-chw4",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "vLLM: Qwen2-VL / Qwen3-VL video samplers bound on request-controlled max_frames, which the num_frames ceiling does not reach",
"summary": "### Summary An unauthenticated remote attacker can exhaust the memory of the vLLM API-server process by raising the request-level `media_io_kwargs.video.max_frames` and `fps` knobs on any deployment serving a Qwen2-VL or Qwen3-VL model. 74 extra bytes of JSON took the server's peak RSS from 2 271 MiB to 13 629 MiB over unauthenticated `POST /tokenize`. The `num_frames` ceiling reported in GHSA-vxqj-p4gw-9h4c and fixed by open PR #51969 does not reach this path: the Qwen samplers do not read `num_frames` at all. The same knobs were already capped upstream for `GLMGAVideoBackend` as an accepted security fix in `8b6de0eb9` (PR #54935, merged 2026-09-04); that cap never reached Qwen. ### Details #### Relationship to GHSA-vxqj-p4gw-9h4c and PR #51969 (read this first) GHSA-vxqj-p4gw-9h4c reported that request-level `media_io_kwargs.video.num_frames` overrides the engine frame-count ceiling, and open PR #51969 fixes it by clamping `num_frames` inside `VideoMediaIO.merge_kwargs`. That clamp does not reach the Qwen samplers. `Qwen2VLVideoBackend` and `Qwen3VLVideoBackend` do not read `num_frames` at all — `Qwen2VLVideoBackend`'s own docstring says so (\"``num_frames`` is ignored (fps-driven, like the Qwen3-VL loader)\"). They bound on `max_frames`, read from the same merged dict with no ceiling: ```python # vllm/multimodal/video.py — Qwen3VLVideoBackend.compute_frames_index_to_sample min_frames = kwargs.get(\"min_frames\", 4) max_frames = kwargs.get(\"max_frames\", 768) num_frames = int(to",
"evidence": "osv:GHSA-x6mc-67gf-chw4",
"products": [
{
"name": {
"value": "vllm",
"evidence": "/affected/0/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "0.30.0",
"evidence": "/affected/0/ranges"
}
],
"affected_versions": [
{
"value": "0.24.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.25.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.25.1",
"evidence": "/affected/0/versions"
},
{
"value": "0.26.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.27.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.27.1",
"evidence": "/affected/0/versions"
},
{
"value": "0.28.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.29.0",
"evidence": "/affected/0/versions"
}
]
}
],
"severity": "medium",
"structured": {
"id": "GHSA-x6mc-67gf-chw4",
"aliases": [
"CVE-2026-105758",
"GHSA-x6mc-67gf-chw4",
"PYSEC-2026-4310"
],
"metrics": [
{
"type": "CVSS_V3",
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L"
}
],
"affected": [
{
"ranges": [
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "0.24.0"
},
{
"fixed": "0.30.0"
}
]
}
],
"package": {
"name": "vllm",
"purl": "pkg:pypi/vllm",
"ecosystem": "PyPI"
},
"versions": [
"0.24.0",
"0.25.0",
"0.25.1",
"0.26.0",
"0.27.0",
"0.27.1",
"0.28.0",
"0.29.0"
],
"database_specific": {
"source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-x6mc-67gf-chw4/GHSA-x6mc-67gf-chw4.json"
}
}
],
"modified": "2026-10-15T14:55:52.413199549Z",
"provider": "osv",
"references": [
"https://github.com/vllm-project/vllm/security/advisories/GHSA-x6mc-67gf-chw4",
"https://github.com/vllm-project/vllm/pull/56729",
"https://github.com/vllm-project/vllm/commit/ea723c81c3ea26425cb69503a5d5e90822a04a45",
"https://github.com/vllm-project/vllm",
"https://github.com/vllm-project/vllm/releases/tag/v0.30.0"
],
"provider_metadata": {
"cwe_ids": [
"CWE-770"
],
"severity": "MODERATE",
"github_reviewed": true,
"nvd_published_at": null,
"github_reviewed_at": "2026-10-05T23:42:59Z"
}
},
"related_cves": [
{
"value": "CVE-2026-105758",
"evidence": "/aliases"
}
],
"security_relevant": true,
"severity_evidence": "/severity/0/score"
},
"source_id": "core-osv",
"document_id": 332682,
"published_at": "2026-10-05T23:42:59+00:00"
}vLLM: Qwen2-VL / Qwen3-VL video samplers bound on request-controlled max_frames, which the num_frames ceiling does not reach
core-osv · Original sourcePublished 15 Oct 2026, 10:22 UTC
### Summary An unauthenticated remote attacker can exhaust the memory of the vLLM API-server process by raising the request-level `media_io_kwargs.video.max_frames` and `fps` knobs on any deployment serving a Qwen2-VL or Qwen3-VL model. 74 extra bytes of JSON took the server's peak RSS from 2 271 MiB to 13 629 MiB over unauthenticated `POST /tokenize`. The `num_frames` ceiling reported in GHSA-vxqj-p4gw-9h4c and fixed by open PR #51969 does not reach this path: the Qwen samplers do not read `num_frames` at all. The same knobs were already capped upstream for `GLMGAVideoBackend` as an accepted security fix in `8b6de0eb9` (PR #54935, merged 2026-09-04); that cap never reached Qwen. ### Details #### Relationship to GHSA-vxqj-p4gw-9h4c and PR #51969 (read this first) GHSA-vxqj-p4gw-9h4c reported that request-level `media_io_kwargs.video.num_frames` overrides the engine frame-count ceiling, and open PR #51969 fixes it by clamping `num_frames` inside `VideoMediaIO.merge_kwargs`. That clamp does not reach the Qwen samplers. `Qwen2VLVideoBackend` and `Qwen3VLVideoBackend` do not read `num_frames` at all — `Qwen2VLVideoBackend`'s own docstring says so ("``num_frames`` is ignored (fps-driven, like the Qwen3-VL loader)"). They bound on `max_frames`, read from the same merged dict with no ceiling: ```python # vllm/multimodal/video.py — Qwen3VLVideoBackend.compute_frames_index_to_sample min_frames = kwargs.get("min_frames", 4) max_frames = kwargs.get("max_frames", 768) num_frames = int(to
osv:PYSEC-2026-4310
vllm
Fixed versions: 0.30.0
Complete source record
{
"id": "5d86939e9ce3ea1b205982bd431579250dabd2fcff7234110222b1134fe21493",
"url": "https://osv.dev/vulnerability/PYSEC-2026-4310",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "vLLM: Qwen2-VL / Qwen3-VL video samplers bound on request-controlled max_frames, which the num_frames ceiling does not reach",
"summary": "### Summary An unauthenticated remote attacker can exhaust the memory of the vLLM API-server process by raising the request-level `media_io_kwargs.video.max_frames` and `fps` knobs on any deployment serving a Qwen2-VL or Qwen3-VL model. 74 extra bytes of JSON took the server's peak RSS from 2 271 MiB to 13 629 MiB over unauthenticated `POST /tokenize`. The `num_frames` ceiling reported in GHSA-vxqj-p4gw-9h4c and fixed by open PR #51969 does not reach this path: the Qwen samplers do not read `num_frames` at all. The same knobs were already capped upstream for `GLMGAVideoBackend` as an accepted security fix in `8b6de0eb9` (PR #54935, merged 2026-09-04); that cap never reached Qwen. ### Details #### Relationship to GHSA-vxqj-p4gw-9h4c and PR #51969 (read this first) GHSA-vxqj-p4gw-9h4c reported that request-level `media_io_kwargs.video.num_frames` overrides the engine frame-count ceiling, and open PR #51969 fixes it by clamping `num_frames` inside `VideoMediaIO.merge_kwargs`. That clamp does not reach the Qwen samplers. `Qwen2VLVideoBackend` and `Qwen3VLVideoBackend` do not read `num_frames` at all — `Qwen2VLVideoBackend`'s own docstring says so (\"``num_frames`` is ignored (fps-driven, like the Qwen3-VL loader)\"). They bound on `max_frames`, read from the same merged dict with no ceiling: ```python # vllm/multimodal/video.py — Qwen3VLVideoBackend.compute_frames_index_to_sample min_frames = kwargs.get(\"min_frames\", 4) max_frames = kwargs.get(\"max_frames\", 768) num_frames = int(to",
"evidence": "osv:PYSEC-2026-4310",
"products": [
{
"name": {
"value": "vllm",
"evidence": "/affected/0/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "0.30.0",
"evidence": "/affected/0/ranges"
}
],
"affected_versions": [
{
"value": "0.24.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.25.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.25.1",
"evidence": "/affected/0/versions"
},
{
"value": "0.26.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.27.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.27.1",
"evidence": "/affected/0/versions"
},
{
"value": "0.28.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.29.0",
"evidence": "/affected/0/versions"
}
]
}
],
"severity": "medium",
"structured": {
"id": "PYSEC-2026-4310",
"aliases": [
"CVE-2026-105758",
"GHSA-x6mc-67gf-chw4",
"PYSEC-2026-4310"
],
"metrics": [
{
"type": "CVSS_V3",
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L"
}
],
"affected": [
{
"ranges": [
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "0.24.0"
},
{
"fixed": "0.30.0"
}
]
}
],
"package": {
"name": "vllm",
"purl": "pkg:pypi/vllm",
"ecosystem": "PyPI"
},
"versions": [
"0.24.0",
"0.25.0",
"0.25.1",
"0.26.0",
"0.27.0",
"0.27.1",
"0.28.0",
"0.29.0"
],
"database_specific": {
"source": "https://github.com/pypa/advisory-database/blob/main/vulns/vllm/PYSEC-2026-4310.yaml"
}
}
],
"modified": "2026-10-15T14:45:14.128616170Z",
"provider": "osv",
"references": [
"https://github.com/vllm-project/vllm/security/advisories/GHSA-x6mc-67gf-chw4",
"https://github.com/vllm-project/vllm/pull/56729",
"https://github.com/vllm-project/vllm/commit/ea723c81c3ea26425cb69503a5d5e90822a04a45",
"https://github.com/vllm-project/vllm",
"https://github.com/vllm-project/vllm/releases/tag/v0.30.0",
"https://pypi.org/project/vllm",
"https://github.com/advisories/GHSA-x6mc-67gf-chw4",
"https://nvd.nist.gov/vuln/detail/CVE-2026-105758"
]
},
"related_cves": [
{
"value": "CVE-2026-105758",
"evidence": "/aliases"
}
],
"security_relevant": true,
"severity_evidence": "/severity/0/score"
},
"source_id": "core-osv",
"document_id": 332658,
"published_at": "2026-10-15T10:22:45.585356+00:00"
}