Conversation
Messages arriving during a pending TOTP challenge were unconditionally treated as code attempts, causing message deletion, spurious 'Invalid code' responses, and unnecessary sudo calls for normal chat text. Add a format check (exactly 6 digits) before the verification path. Non-code messages get a brief 'Enter your 6-digit code' reminder instead of being deleted and fed to verify_code(). Fixes #122
Review by KaiPR Review: Filter non-code messages in TOTP gateOverall: Clean, well-scoped fix for a real bug. Logic is correct. A few findings below. Warning
if not code.isdigit() or len(code) != 6:
The PR description notes import re
if not re.fullmatch(r'[0-9]{6}', code):This also eliminates the redundant WarningExpiry check ordering is unverifiable from the diff The new block is inserted between Suggestion
The delete block immediately below is wrapped in try:
await update.effective_chat.send_message("Authentication required. Enter your 6-digit code.")
except Exception:
pass # or logger.warning(...)
returnSuggestionOverly broad test assertion ( assert "6-digit" in sent.lower() or "code" in sent.lower()
assert "6-digit" in sentClean items
|
…t assertion isdigit() accepts non-ASCII digit characters (superscripts, Arabic-Indic numerals). Add isascii() prefix guard so only ASCII digits pass. Also tighten test assertion from broad 'code' match to specific '6-digit'.
Review by KaiPR Review: Filter non-code messages in TOTP gate (Round 2)Overall: Looks good. Both items from the prior review that warranted code changes were addressed correctly. Nothing new to raise. Addressed from prior reviewNon-ASCII digit bypass (Warning → resolved) The author added if not (code.isascii() and code.isdigit() and len(code) == 6):
Overly broad test assertion (Suggestion → resolved) assert "6-digit" in sentTightened from the prior Unaddressed from prior reviewPer review policy, not re-raising items the author has already seen ( New findingsNone. The logic is correct, the filter is placed before the delete/verify path, the tests cover the meaningful edge cases (5-digit, 7-digit, alphanumeric, prefixed), and the positive path ( The Clean to merge. |
Summary
handle_message()concurrent_updates=True, messages arriving while a TOTP challenge is pending were unconditionally treated as code attemptssudocalls viaget_lockout_remaining()/get_failure_count()verify_code()intotp.pyalready has the same format guard (line 171) as defense-in-depth, but the handler needs to distinguish non-codes before reaching the delete/lockout/verify pathWhat changed
Single
ifblock added betweencode = ...and the message deletion block inhandle_message(). Everything downstream (delete, lockout check, verify_code, failure handling) is untouched.Test plan
test_non_code_message_not_deleted- normal text not deleted, verify_code not called, reminder senttest_six_digit_code_still_verified- 6-digit strings still reach verify_code and get deletedtest_non_code_no_sudo_calls- no sudo-backed functions called for non-code texttest_partial_digit_string_not_treated_as_code- edge cases: 5 digits, 7 digits, mixed alphanumeric, prefixed digitstest_code_message_deleted_after_verification(uses "123456") still passestest_invalid_code_shows_remaining_attempts(uses "000000") still passesmake checkcleanFixes #122