Python -VV
Python 3.12.14 (main, Aug 25 2026, 14:00:49) [Clang 22.1.3 ]
Pip Freeze
mistral-common @ main (1fdcf24)
numpy==2.2.6
opencv-python-headless==4.11.0.86
pillow==11.3.0
pydantic==2.11.7
requests==2.32.4
tiktoken==0.12.0
Reproduction Steps
image_from_chunk (src/mistral_common/tokens/tokenizers/image.py) sits on the encode path for every ImageURLChunk: ImageEncoder.__call__ -> InstructTokenizerV3._encode_content_chunk -> MistralTokenizer.encode_chat_completion. Three inputs misbehave:
- Data URL without a comma raises
IndexError instead of a library error:
from mistral_common.protocol.instruct.chunk import ImageURLChunk
from mistral_common.tokens.tokenizers.image import image_from_chunk
image_from_chunk(ImageURLChunk(image_url="data:image/png;base64"))
# IndexError: list index out of range (image.py: data = chunk.get_url().split(",")[1])
- The local-file branch matches
startswith("file"), not file://. Any URL whose text starts with "file" is opened relative to the server's cwd:
# with a file named file.png in cwd:
image_from_chunk(ImageURLChunk(image_url="file.png"))
# <PIL.PngImagePlugin.PngImageFile ... size=8x8> (opened from disk, handle never closed)
download_image (src/mistral_common/image.py) calls requests.get(url, headers=headers) with no timeout. A server that accepts the connection and never responds blocks the encode call forever (Bandit B113).
Expected Behavior
- A malformed data URL should raise the same
RuntimeError family the function already uses for unsupported schemes, not IndexError.
- Only
file:// URIs should be treated as local files. A bare name like file.png should fall through to "Unsupported image url scheme".
requests.get should have a finite timeout so one dead URL cannot hang an encode worker.
Additional Context
Reachable with untrusted input: ImageURLChunk is accepted on user messages, and the experimental tokenize server (mistral_common.experimental.app) turns the IndexError into an unhandled 500 since its handlers only catch ValueError. vLLM and the Transformers MistralCommonBackend go through the same encode_chat_completion path.
Audio.from_url in src/mistral_common/tokens/tokenizers/audio.py has the same missing timeout; I left it out to keep the fix reviewable in one function.
Suggested Solutions
Split the data URL on the first comma and raise RuntimeError when there is no payload, require the file:// prefix for the local-file branch (and close the handle), and pass a default timeout to requests.get in download_image. I have a branch with this fix plus tests that fail on main and pass with the change; PR to follow.
Python -VV
Pip Freeze
Reproduction Steps
image_from_chunk(src/mistral_common/tokens/tokenizers/image.py) sits on the encode path for everyImageURLChunk:ImageEncoder.__call__->InstructTokenizerV3._encode_content_chunk->MistralTokenizer.encode_chat_completion. Three inputs misbehave:IndexErrorinstead of a library error:startswith("file"), notfile://. Any URL whose text starts with "file" is opened relative to the server's cwd:download_image(src/mistral_common/image.py) callsrequests.get(url, headers=headers)with notimeout. A server that accepts the connection and never responds blocks the encode call forever (Bandit B113).Expected Behavior
RuntimeErrorfamily the function already uses for unsupported schemes, notIndexError.file://URIs should be treated as local files. A bare name likefile.pngshould fall through to "Unsupported image url scheme".requests.getshould have a finite timeout so one dead URL cannot hang an encode worker.Additional Context
Reachable with untrusted input:
ImageURLChunkis accepted on user messages, and the experimental tokenize server (mistral_common.experimental.app) turns theIndexErrorinto an unhandled 500 since its handlers only catchValueError. vLLM and the TransformersMistralCommonBackendgo through the sameencode_chat_completionpath.Audio.from_urlinsrc/mistral_common/tokens/tokenizers/audio.pyhas the same missing timeout; I left it out to keep the fix reviewable in one function.Suggested Solutions
Split the data URL on the first comma and raise
RuntimeErrorwhen there is no payload, require thefile://prefix for the local-file branch (and close the handle), and pass a defaulttimeouttorequests.getindownload_image. I have a branch with this fix plus tests that fail onmainand pass with the change; PR to follow.