Skip to content

BUG: BinaryConverter rejects characters in words the selection strategy never converts #2590

Description

Describe the bug

BinaryConverter rejects a prompt because of a character in a word that the configured word selection strategy never converts.

WordLevelConverter.convert_async calls self.validate_input(prompt=prompt) on the whole prompt (pyrit/converter/word_level_converter.py:114) and only afterwards applies the selection strategy (:118). BinaryConverter.validate_input scans every character in the prompt, so an unselected word raises ValueError even though that word is passed through unencoded and cannot overflow bits_per_char.

Steps to reproduce

import asyncio

from pyrit.converter import BinaryConverter
from pyrit.converter.text_selection_strategy import WordIndexSelectionStrategy


async def main():
    # Only word 0 ("hello") is selected, so the emoji is never encoded.
    converter = BinaryConverter(
        bits_per_char=BinaryConverter.BitsPerChar.BITS_16,
        word_selection_strategy=WordIndexSelectionStrategy(indices=[0]),
    )
    print(await converter.convert_async(prompt="hello 👋", input_type="text"))


asyncio.run(main())

Expected behavior

hello is encoded at 16 bits per character and 👋 is passed through untouched, as it is for every other WordLevelConverter subclass.

Actual behavior

ValueError: bits_per_char=16 is too small for the characters in the prompt. Minimum required bits: 17.

Nothing is converted. The only way to encode hello is to raise bits_per_char to 32 for a character that is never encoded, which changes the encoding of every selected word.

Additional context

The default AllWordsSelectionStrategy path is unaffected: when every word is converted, whole-prompt and per-word validation agree. The mismatch only appears once a selection strategy is supplied.

Validating the words that are actually converted resolves this. I have a PR ready with that fix and regression tests. Happy to move the fix into WordLevelConverter.convert_async instead (validating after selection, which would cover any future subclass that overrides validate_input) if you prefer that shape.

Environment: PyRIT 1.2.0.dev0 (main at 623d57a), Python 3.14, Linux.

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