fix!: Restrict allowed HTML in msgprints (#37399)

Co-authored-by: AarDG10 <aarol.dsouza@gmail.com>
This commit is contained in:
Ankush Menat 2026-02-23 17:19:15 +05:30 committed by GitHub
parent 0f35058688
commit 657b1eb50c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 34 additions and 6 deletions

View file

@ -1679,3 +1679,19 @@ class TestDataUtils(UnitTestCase):
self.assertEqual(comma_or(["a", "b", "c"]), "'a', 'b' ou 'c'")
self.assertEqual(comma_or(["a", "b", "c"], add_quotes=False), "a, b ou c")
class TestMsgPrint(UnitTestCase):
def tearDown(self) -> None:
super().tearDown()
frappe.clear_messages()
def test_msgprint(self):
frappe.msgprint("Validate: <script>alert('bounty')</script>")
message = frappe.get_message_log()[-1]
self.assertNotIn("script", message.message)
frappe.msgprint("<ul><li>abc<li></ul>")
message = frappe.get_message_log()[-1]
self.assertIn("<ul><li>", message.message)

View file

@ -1,4 +1,3 @@
import functools
import sys
from collections.abc import Sequence
from typing import Literal
@ -8,8 +7,6 @@ from frappe import _
from frappe.utils import strip_html_tags
from frappe.utils.data import safe_decode
_strip_html_tags = functools.lru_cache(maxsize=1024)(strip_html_tags)
def msgprint(
msg: str | Sequence[str] | Sequence[Sequence[str]],
@ -24,6 +21,7 @@ def msgprint(
wide: bool = False,
*,
realtime=False,
allow_dangerous_html=False,
) -> None:
"""Print a message to the user (via HTTP response).
Messages are sent in the `__server_messages` property in the
@ -38,9 +36,12 @@ def msgprint(
:param is_minimizable: [optional] Allow users to minimize the modal
:param wide: [optional] Show wide modal
:param realtime: Publish message immediately using websocket.
:param allow_dangerous_html: Allow arbitrary HTML in message.
"""
import inspect
from frappe.utils.html_utils import clean_html
msg = safe_decode(msg)
out = frappe._dict(message=msg)
@ -67,13 +68,21 @@ def msgprint(
else:
out.as_table = as_table
if not allow_dangerous_html:
if out.as_list:
out.message = [clean_html(cell) for cell in msg]
elif out.as_table:
out.message = [[clean_html(cell) for cell in row] for row in msg]
else:
out.message = clean_html(msg)
if sys.stdin and sys.stdin.isatty():
if out.as_list:
msg = [_strip_html_tags(cell) for cell in msg]
msg = [strip_html_tags(cell) for cell in msg]
elif out.as_table:
msg = [[_strip_html_tags(cell) for cell in row] for row in msg]
msg = [[strip_html_tags(cell) for cell in row] for row in msg]
else:
msg = _strip_html_tags(msg)
msg = strip_html_tags(msg)
if frappe.flags.print_messages and out.message:
print(f"Message: {msg}")
@ -134,6 +143,8 @@ def throw(
wide: bool = False,
as_list: bool = False,
primary_action=None,
*,
allow_dangerous_html=False,
) -> None:
"""Throw execption and show message (`msgprint`).
@ -154,6 +165,7 @@ def throw(
wide=wide,
as_list=as_list,
primary_action=primary_action,
allow_dangerous_html=allow_dangerous_html,
)