@@ -541,19 +541,20 @@ def _compute_registrant_summary_html(self):
541541 html_parts .append ('<i class="fa fa-users fa-lg text-primary me-2"></i>' )
542542 else :
543543 html_parts .append ('<i class="fa fa-user fa-lg text-primary me-2"></i>' )
544- html_parts .append (f"<strong>{ reg .name } </strong>" )
544+ html_parts .append (f"<strong>{ html_escape ( reg .name or '' ) } </strong>" )
545545 html_parts .append ("</div>" )
546546
547547 # ID badge
548548 if hasattr (reg , "spp_id" ) and reg .spp_id :
549- html_parts .append (f'<div class="mb-2"><span class="badge bg-secondary">ID: { reg .spp_id } </span></div>' )
549+ escaped_id = html_escape (reg .spp_id )
550+ html_parts .append (f'<div class="mb-2"><span class="badge bg-secondary">ID: { escaped_id } </span></div>' )
550551
551552 # Address
552553 address_parts = []
553554 if reg .street :
554- address_parts .append (reg .street )
555+ address_parts .append (html_escape ( reg .street ) )
555556 if reg .city :
556- address_parts .append (reg .city )
557+ address_parts .append (html_escape ( reg .city ) )
557558 if address_parts :
558559 html_parts .append (
559560 f'<div class="text-muted small mb-2">'
@@ -1073,7 +1074,7 @@ def _generate_preview_html(self):
10731074 action_label = action_labels .get (action , action .replace ("_" , " " ).title ())
10741075 html_parts .append (
10751076 f'<div class="mb-3 d-flex align-items-center">'
1076- f'<span class="badge bg-primary me-2">{ action_label } </span>'
1077+ f'<span class="badge bg-primary me-2">{ html_escape ( action_label ) } </span>'
10771078 f"</div>"
10781079 )
10791080
@@ -1085,7 +1086,7 @@ def _generate_preview_html(self):
10851086 for key , value in changes .items ():
10861087 if key .startswith ("_" ):
10871088 continue
1088- display_key = key .replace ("_" , " " ).title ()
1089+ display_key = html_escape ( key .replace ("_" , " " ).title () )
10891090
10901091 # Handle dict with old/new structure
10911092 if isinstance (value , dict ) and "new" in value :
@@ -1095,16 +1096,16 @@ def _generate_preview_html(self):
10951096 if old_val is None or old_val is False or old_val == "" :
10961097 old_display = '<span class="text-muted">—</span>'
10971098 else :
1098- old_display = str (old_val )
1099+ old_display = html_escape ( str (old_val ) )
10991100 # Format new value
11001101 if new_val is None or new_val is False or new_val == "" :
11011102 new_display = '<span class="text-muted">—</span>'
11021103 else :
1103- new_display = f"<strong>{ new_val } </strong>"
1104+ new_display = f"<strong>{ html_escape ( str ( new_val )) } </strong>"
11041105 display_value = f"{ old_display } → { new_display } "
11051106 elif isinstance (value , list ):
11061107 if value :
1107- display_value = "<br/>" .join (str (v ) for v in value )
1108+ display_value = "<br/>" .join (html_escape ( str (v ) ) for v in value )
11081109 else :
11091110 display_value = '<span class="text-muted">Not set</span>'
11101111 elif value is None or value is False or value == "" :
@@ -1114,7 +1115,7 @@ def _generate_preview_html(self):
11141115 # Only True reaches here (False caught above)
11151116 display_value = '<span class="badge text-bg-success">Yes</span>'
11161117 else :
1117- display_value = str (value )
1118+ display_value = html_escape ( str (value ) )
11181119
11191120 html_parts .append (f"<tr><td><strong>{ display_key } </strong></td><td>{ display_value } </td></tr>" )
11201121
0 commit comments