Skip to content

[BUG: image_from_chunk crashes on malformed data URLs, opens bare "file*" names as local paths, and downloads with no timeout] #307

Description

@BarneyChambers

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:

  1. 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])
  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)
  1. 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

  1. A malformed data URL should raise the same RuntimeError family the function already uses for unsupported schemes, not IndexError.
  2. Only file:// URIs should be treated as local files. A bare name like file.png should fall through to "Unsupported image url scheme".
  3. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions