pipal() built one rigid regex requiring exactly pipal_count consecutive
base-word lines, so any cracked set with fewer unique base words than
pipal_count (default 10) matched nothing and returned []. Parse the
"Top N base words" section line by line instead, collecting up to
pipal_count words and stopping at the blank line that ends the section.
Also replace the shell=True string-formatted Popen with list-form
arguments so file paths containing shell metacharacters can't be
interpreted as commands.
Adds tests/test_pipal_e2e.py: hermetic end-to-end tests that drive the
real pipal() through a fake pipal executable (parsing, $HEX decode,
fewer-basewords regression, and injection safety).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>