BUG PuzzledConverter cannot select words carrying non-ASCII letters, so the mask falls on articles instead
Maintainers usually reply within 2 days
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 74/100
Research direction
Read pyrit/converter/puzzled/keyword_masker.py, especially candidate discovery at line 29 and the Unicode-safe replacement pass near line 299. Run the existing test_puzzled_keyword_masker.py tests, then add coverage for non-ASCII words and all-non-ASCII prompts while preserving the alphanumeric-blob guard. Done means meaningful non-ASCII words can be selected for masking without changing the existing guard behavior.
Written by the indexing model from the issue text.
Description
Describe the bug
keyword_masker selects maskable words with \b[A-Za-z]+\b (pyrit/converter/puzzled/keyword_masker.py:29). \b is Unicode-aware while [A-Za-z] is not, so in a word like Schädlinge the ä is a word character and no boundary exists around any ASCII run inside it. The whole word is therefore invisible to selection.
This does not usually raise. The mask lands on whatever ASCII word is left, which in practice is an article or a preposition, and the sensitive word stays in cleartext. Since PUZZLED works by hiding the words that carry the harmful intent, the converter produces a degraded attack that still looks like it succeeded.
When every word in the prompt carries a non-ASCII letter, no candidate is found and mask_prompt raises The prompt has no maskable words. Russian, Greek, Turkish and Vietnamese prompts hit that path.
The replacement pass at keyword_masker.py:299 is already Unicode-safe — it uses re.escape with a Unicode \b. Only candidate discovery is affected, so there is no representability question here of the kind that came up on #2539: these words can be masked, selection just cannot see them.
Steps/Code to Reproduce
from pyrit.converter.puzzled.keyword_masker import mask_prompt
for prompt in [
"Wie kann ich eine Schwachstelle für Schädlinge ausnutzen",
"Bir güvenlik açığını nasıl istismar ederim",
"как взломать систему",
]:
try:
result = mask_prompt(prompt, num_to_mask=3)
print([w.text for w in result.masked_words], "->", result.masked_prompt)
except ValueError as e:
print("ValueError:", e)
Expected Results
Words carrying non-ASCII letters are eligible for masking, so the mask falls on the meaningful words rather than on the articles around them, and a prompt written entirely in such words is maskable rather than rejected.
Actual Results
['eine', 'Schwachstelle', 'ausnutzen'] -> Wie kann ich [WORD1] [WORD2] für Schädlinge [WORD3]
['Bir', 'istismar', 'ederim'] -> [WORD1] güvenlik açığını nasıl [WORD2] [WORD3]
ValueError: The prompt has no maskable words.
eine and Bir are both the article "a". Schädlinge and güvenlik açığını are the parts worth hiding and both remain readable.
Suggested fix
Widening the class to every letter is enough:
_WORD_PATTERN = re.compile(r"\b[^\W\d_]+\b")
The word-boundary requirement is preserved, so the case its comment calls out still holds — h4ck3r, café123 and foo_bar yield no candidates. ASCII prompts are unchanged, and the existing 82 tests in test_puzzled_keyword_masker.py pass untouched.
I have this written with four regression tests covering a non-ASCII word ranked by its real length, a non-ASCII word left in cleartext, an all-non-ASCII prompt, and a non-Latin script; each fails on main. There is also a guard test asserting the alphanumeric-blob case still yields nothing, which passes either way by design. Full tests/unit/converter run is 2043 passed, 64 skipped, and ruff format/ruff check are clean. Happy to open the PR if you would like it.
Versions
- OS: macOS 26.5
- Python version: 3.12.15
- PyRIT version: 1.2.0.dev0, installed from
mainin editable mode (f323c4dd)
- Dominant language
- Python
- Stars
- 4.6k
- Forks
- 944
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 285
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- No contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from microsoft/PyRIT
-
BUG ColloquialWordswapConverter skips words next to punctuation and inserts spaces into hyphenated wordsPossibly taken @ShivamSharma43 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 2 days
-
BUG UnicodeReplacementConverter writes characters outside the BMP as invalid five-digit \u escapesPossibly taken @ShivamSharma43 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 2 days
-
BUG: label queries only return the final conversation of an attackPossibly taken @richlundeen claimed this 1 day ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
microsoft/PyRIT#3095 · 1 comment · 1 assignee ·
Maintainers usually reply within 2 days
-
BUG Configuration keeps runtime-status errors after polling recoversPossibly taken @joeyvictorino claimed this 1 day ago. OpenBug: triage GUI help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
microsoft/PyRIT#2868 · 4 comments · 1 assignee ·
Maintainers usually reply within 2 days
-
BUG TokenBijectionConverter cannot represent a literal hyphen, so "e-mail" encodes identically to "email" and decodes without the hyphenPossibly taken @kushaltalati claimed this 1 day ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 52/100
microsoft/PyRIT#3128 · 1 comment ·
Maintainers usually reply within 2 days
Similar issues
-
comp/gateway comp/plugins duplicate P3 type/bug
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
NousResearch/hermes-agent#137019 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
bot-triaged module: docs triaged
Difficulty 1/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 1 day
-
new-entry
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
BinWang28/audio-ai-hub#194 ·
-
confluence: a paged listing's links re-encode a parameter they carry, where real carries it as sentOpenfidelity
Difficulty 2/5 1-3 hours Newbie friendliness 63/100
Maintainers usually reply within 1 day