|
40 | 40 | import java.util.List; |
41 | 41 | import java.util.Map; |
42 | 42 | import java.util.Objects; |
| 43 | +import java.util.Set; |
43 | 44 | import java.util.regex.Matcher; |
44 | 45 | import java.util.regex.Pattern; |
45 | 46 | import java.util.stream.Collectors; |
@@ -1656,15 +1657,32 @@ private String sanitizeAndLinkify(String text) { |
1656 | 1657 | StringBuilder result = new StringBuilder(); |
1657 | 1658 | int last = 0; |
1658 | 1659 |
|
| 1660 | + // Expanded the allowed tags to include standard rich text formatting options |
| 1661 | + Set<String> allowedTags = Set |
| 1662 | + .of("div", "span", "p", "br", "b", "i", "u", "strong", "em", "ul", "ol", "li", "table", "tr", "td", "th", "thead", "tbody", "font", "a"); |
| 1663 | + |
1659 | 1664 | while (matcher.find()) { |
1660 | 1665 | String plainTextSegment = htmlText.substring(last, matcher.start()); |
1661 | 1666 | result.append(escapeHtml(plainTextSegment).replace("&nbsp;", " ")); |
1662 | 1667 |
|
1663 | 1668 | String htmlTag = matcher.group(1); |
1664 | 1669 | String url = matcher.group(2); |
1665 | 1670 | if (htmlTag != null) { |
1666 | | - // It's a rich text tag (like <div> or <br>). Pass it through safely. |
1667 | | - result.append(htmlTag); |
| 1671 | + // Only allow safe formatting tags |
| 1672 | + String cleanTagName = htmlTag.replaceAll("[<>/]", "").trim().split("\\s+")[0].toLowerCase(); |
| 1673 | + if (allowedTags.contains(cleanTagName)) { |
| 1674 | + String lowerTag = htmlTag.toLowerCase(); |
| 1675 | + if (lowerTag.contains("javascript:") |
| 1676 | + || lowerTag.contains("onclick") |
| 1677 | + || lowerTag.contains("onerror") |
| 1678 | + || lowerTag.contains("onload")) { |
| 1679 | + // Attack vector found! Escape it safely into text instead of executing it |
| 1680 | + result.append(escapeHtml(htmlTag)); |
| 1681 | + } else { |
| 1682 | + // It's a completely safe rich text element. Pass it through so styles render perfectly. |
| 1683 | + result.append(htmlTag); |
| 1684 | + } |
| 1685 | + } |
1668 | 1686 | } else if (url != null) { |
1669 | 1687 | // It's a plain-text URL. Wrap it in your custom blue link styling. |
1670 | 1688 | String escapedUrl = escapeHtml(url); |
|
0 commit comments