xss_util.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import bleach
  2. ALLOWED_TAGS = [
  3. "a",
  4. "abbr",
  5. "acronym",
  6. "b",
  7. "blockquote",
  8. "br",
  9. "code",
  10. "col",
  11. "colgroup",
  12. "dd",
  13. "del",
  14. "dl",
  15. "dt",
  16. "em",
  17. "h1",
  18. "h2",
  19. "h3",
  20. "h4",
  21. "h5",
  22. "h6",
  23. "hr",
  24. "i",
  25. "img",
  26. "li",
  27. "ol",
  28. "p",
  29. "pre",
  30. "s",
  31. "span",
  32. "strike",
  33. "strong",
  34. "sub",
  35. "sup",
  36. "table",
  37. "tbody",
  38. "td",
  39. "tfoot",
  40. "th",
  41. "thead",
  42. "tr",
  43. "tt",
  44. "u",
  45. "ul",
  46. "video",
  47. "source",
  48. "div",
  49. "font",
  50. ]
  51. ALLOWED_ATTRIBUTES = {
  52. "*": ["class", "style", "id", "data-*"],
  53. "a": ["href", "title", "target", "rel"],
  54. "abbr": ["title"],
  55. "acronym": ["title"],
  56. "img": ["src", "alt", "title", "width", "height"],
  57. "video": ["src", "controls", "width", "height", "poster"],
  58. "source": ["src", "type"],
  59. "font": ["color", "size", "face"],
  60. "td": ["width", "height", "colspan", "rowspan"],
  61. "th": ["width", "height", "colspan", "rowspan"],
  62. "col": ["width", "span"],
  63. "colgroup": ["span"],
  64. }
  65. ALLOWED_STYLES = [
  66. "color",
  67. "background-color",
  68. "font-size",
  69. "font-family",
  70. "font-weight",
  71. "font-style",
  72. "text-decoration",
  73. "text-align",
  74. "margin",
  75. "margin-left",
  76. "margin-right",
  77. "margin-top",
  78. "margin-bottom",
  79. "padding",
  80. "padding-left",
  81. "padding-right",
  82. "padding-top",
  83. "padding-bottom",
  84. "border",
  85. "border-color",
  86. "border-width",
  87. "border-style",
  88. "width",
  89. "height",
  90. "line-height",
  91. "display",
  92. ]
  93. def sanitize_html(content: str) -> str:
  94. """
  95. 清理 HTML 内容,移除潜在的 XSS 攻击代码。
  96. 参数:
  97. - content (str): 需要清理的 HTML 内容
  98. 返回:
  99. - str: 清理后的安全 HTML 内容
  100. """
  101. if not content:
  102. return content
  103. return bleach.clean(
  104. content,
  105. tags=ALLOWED_TAGS,
  106. attributes=ALLOWED_ATTRIBUTES,
  107. strip=True,
  108. strip_comments=True,
  109. )
  110. def sanitize_html_with_styles(content: str) -> str:
  111. """
  112. 清理 HTML 内容;标签与属性白名单与 `sanitize_html` 一致。
  113. 参数:
  114. - content (str): 需要清理的 HTML 内容。
  115. 返回:
  116. - str: 清理后的 HTML 字符串。
  117. 说明:
  118. - `ALLOWED_STYLES` 供后续接入 bleach 样式清洗时使用,当前实现与 `sanitize_html` 相同。
  119. """
  120. if not content:
  121. return content
  122. return bleach.clean(
  123. content,
  124. tags=ALLOWED_TAGS,
  125. attributes=ALLOWED_ATTRIBUTES,
  126. strip=True,
  127. strip_comments=True,
  128. )
  129. def strip_all_tags(content: str) -> str:
  130. """
  131. 移除所有 HTML 标签,只保留纯文本。
  132. 参数:
  133. - content (str): 需要处理的 HTML 内容
  134. 返回:
  135. - str: 纯文本内容
  136. """
  137. if not content:
  138. return content
  139. return bleach.clean(content, tags=[], attributes={}, strip=True)