Summary
BrailleConverter silently drops any character that is not in its Braille lookup table (and not an escape character or a mapped uppercase letter). Since the converter is used to obfuscate prompts for red-teaming, the model receives a different instruction than intended without any warning.
Reproduction
import asyncio
from pyrit.converter import BrailleConverter
async def main():
c = BrailleConverter()
for prompt in ["What\x27s 2+2?", "a@b.com", "100% sure", "café 中文"]:
r = await c.convert_async(prompt=prompt, input_type="text")
print(repr(r.output_text))
asyncio.run(main())
Output on current main:
\x27⠠⠺⠓⠁⠞⠄⠎ ⠼⠃⠼⠃⠦\x27 # "+" dropped → "22?"
\x27⠁⠃⠲⠉⠕⠍\x27 # "@" dropped → "ab.com"
\x27⠼⠁⠚⠚ ⠎⠥⠗⠑\x27 # "%" dropped
\x27⠉⠁⠋ \x27 # "é 中文" dropped → "caf "
+, @, %, <, &, accented letters and CJK characters are all silently removed.
Expected behavior
Characters outside the Braille table should pass through unchanged, matching every other converter in this codebase (e.g. AtbashConverter uses str.translate which leaves unmapped characters as-is, and ArabiziConverter/CharacterSpaceConverter keep unknown characters). The encoded prompt should preserve the original instruction verbatim apart from the Braille-translatable parts.
Summary
BrailleConvertersilently drops any character that is not in its Braille lookup table (and not an escape character or a mapped uppercase letter). Since the converter is used to obfuscate prompts for red-teaming, the model receives a different instruction than intended without any warning.Reproduction
Output on current main:
+,@,%,<,&, accented letters and CJK characters are all silently removed.Expected behavior
Characters outside the Braille table should pass through unchanged, matching every other converter in this codebase (e.g.
AtbashConverterusesstr.translatewhich leaves unmapped characters as-is, andArabiziConverter/CharacterSpaceConverterkeep unknown characters). The encoded prompt should preserve the original instruction verbatim apart from the Braille-translatable parts.