test(media): lock XSS escaping on new-media-type user-string sinks (#21 review F1)
Docker Image CI / build (pull_request) Has been cancelled
Docker Image CI / build (pull_request) Has been cancelled
The new Telegram media types (Kurigram 2.2.23) escape every user string in _format_special_media, but only CONTACT first_name + CHECKLIST task text were regression-tested — the reviewer mutation-proved the other sinks were uncovered (removing html.escape from VENUE title / GIVEAWAY description / CHECKLIST title kept the suite green). Given this project's XSS history (#12 fail-open, #13 debug-title), lock them. Add 7 regression tests (mirroring test_contact_name_is_escaped): a <script> payload in VENUE title, VENUE address label, DICE emoji, GAME title, CHECKLIST title, GIVEAWAY description, and GIVEAWAY_WINNERS prize_description; each asserts the raw payload is absent and the escaped form present. Mutation-verified: removing the escape on each sink reds its test. 321 passed (314 + 7). Test-only — no production code touched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -371,6 +371,73 @@ def test_checklist_task_text_is_escaped(parser):
|
||||
assert "📝 My list" in body
|
||||
|
||||
|
||||
def test_venue_title_is_escaped(parser):
|
||||
# VENUE title feeds venue_label -> html.escape(venue_label)
|
||||
venue = SimpleNamespace(title=XSS, address="1 Main St",
|
||||
location=SimpleNamespace(latitude=1.5, longitude=2.5))
|
||||
msg = make_message(303, media=MessageMediaType.VENUE, venue=venue)
|
||||
body = parser._generate_html_body(msg)
|
||||
assert XSS not in body
|
||||
assert XSS_ESCAPED in body
|
||||
|
||||
|
||||
def test_venue_address_label_is_escaped(parser):
|
||||
# VENUE address also feeds venue_label -> html.escape(venue_label)
|
||||
venue = SimpleNamespace(title="Blue Bottle", address=XSS,
|
||||
location=SimpleNamespace(latitude=1.5, longitude=2.5))
|
||||
msg = make_message(304, media=MessageMediaType.VENUE, venue=venue)
|
||||
body = parser._generate_html_body(msg)
|
||||
assert XSS not in body
|
||||
assert XSS_ESCAPED in body
|
||||
|
||||
|
||||
def test_dice_emoji_is_escaped(parser):
|
||||
# DICE emoji -> html.escape(str(dice_emoji))
|
||||
msg = make_message(305, media=MessageMediaType.DICE,
|
||||
dice=SimpleNamespace(emoji=XSS, value=6))
|
||||
body = parser._generate_html_body(msg)
|
||||
assert XSS not in body
|
||||
assert XSS_ESCAPED in body
|
||||
|
||||
|
||||
def test_game_title_is_escaped(parser):
|
||||
# GAME title -> html.escape(game_title.strip())
|
||||
msg = make_message(306, media=MessageMediaType.GAME,
|
||||
game=SimpleNamespace(title=XSS))
|
||||
body = parser._generate_html_body(msg)
|
||||
assert XSS not in body
|
||||
assert XSS_ESCAPED in body
|
||||
|
||||
|
||||
def test_checklist_title_is_escaped(parser):
|
||||
# CHECKLIST title -> html.escape(title_str)
|
||||
checklist = SimpleNamespace(title=XSS, tasks=[])
|
||||
msg = make_message(307, media=MessageMediaType.CHECKLIST, checklist=checklist)
|
||||
body = parser._generate_html_body(msg)
|
||||
assert XSS not in body
|
||||
assert XSS_ESCAPED in body
|
||||
|
||||
|
||||
def test_giveaway_description_is_escaped(parser):
|
||||
# GIVEAWAY description -> html.escape(description.strip())
|
||||
giveaway = SimpleNamespace(quantity=5, months=None, stars=None,
|
||||
until_date=None, description=XSS)
|
||||
msg = make_message(308, media=MessageMediaType.GIVEAWAY, giveaway=giveaway)
|
||||
body = parser._generate_html_body(msg)
|
||||
assert XSS not in body
|
||||
assert XSS_ESCAPED in body
|
||||
|
||||
|
||||
def test_giveaway_winners_prize_description_is_escaped(parser):
|
||||
# GIVEAWAY_WINNERS prize_description -> html.escape(prize_description.strip())
|
||||
winners = SimpleNamespace(winner_count=2, quantity=5, prize_description=XSS,
|
||||
unclaimed_prize_count=0, winners=[])
|
||||
msg = make_message(309, media=MessageMediaType.GIVEAWAY_WINNERS, giveaway_winners=winners)
|
||||
body = parser._generate_html_body(msg)
|
||||
assert XSS not in body
|
||||
assert XSS_ESCAPED in body
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 7. Giveaway / giveaway winners info blocks
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user