diff --git a/pyrit/converter/token_smuggling/sneaky_bits_smuggler_converter.py b/pyrit/converter/token_smuggling/sneaky_bits_smuggler_converter.py index bbbbb1b544..569b7013f9 100644 --- a/pyrit/converter/token_smuggling/sneaky_bits_smuggler_converter.py +++ b/pyrit/converter/token_smuggling/sneaky_bits_smuggler_converter.py @@ -38,12 +38,17 @@ def __init__( one_char (str | None): Character to represent binary 1 in ``sneaky_bits`` mode (default: U+2064). Raises: - ValueError: If an unsupported action or ``encoding_mode`` is provided. + ValueError: If the action is unsupported, marker values are not single characters, or markers are equal. """ super().__init__(action=action) self.zero_char = zero_char if zero_char is not None else "\u2062" # Invisible Times self.one_char = one_char if one_char is not None else "\u2064" # Invisible Plus + if len(self.zero_char) != 1 or len(self.one_char) != 1: + raise ValueError("zero_char and one_char must each be exactly one character") + if self.zero_char == self.one_char: + raise ValueError("zero_char and one_char must be distinct") + def _build_identifier(self) -> ComponentIdentifier: """ Build identifier with sneaky bits parameters. diff --git a/tests/unit/converter/test_sneaky_bits_smuggler_converter.py b/tests/unit/converter/test_sneaky_bits_smuggler_converter.py index 9f51c5875d..ff835ef17e 100644 --- a/tests/unit/converter/test_sneaky_bits_smuggler_converter.py +++ b/tests/unit/converter/test_sneaky_bits_smuggler_converter.py @@ -31,6 +31,25 @@ async def test_sneaky_bits_custom_chars(): assert len(result.output_text) == 8 # 1 ASCII byte = 8 bits +@pytest.mark.parametrize( + ("zero_char", "one_char"), + [ + ("", "1"), + ("00", "1"), + ("0", ""), + ("0", "11"), + ], +) +def test_sneaky_bits_custom_chars_must_be_single_characters(zero_char: str, one_char: str): + with pytest.raises(ValueError, match="exactly one character"): + SneakyBitsSmugglerConverter(zero_char=zero_char, one_char=one_char) + + +def test_sneaky_bits_custom_chars_must_be_distinct(): + with pytest.raises(ValueError, match="must be distinct"): + SneakyBitsSmugglerConverter(zero_char="x", one_char="x") + + async def test_sneaky_bits_empty(): converter = SneakyBitsSmugglerConverter(action="encode") result = await converter.convert_async(prompt="", input_type="text")