logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma

html_test.exs (8049B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.HTMLTest do
  5. alias Pleroma.HTML
  6. alias Pleroma.Object
  7. alias Pleroma.Web.CommonAPI
  8. use Pleroma.DataCase
  9. import Pleroma.Factory
  10. @html_sample """
  11. <b>this is in bold</b>
  12. <p>this is a paragraph</p>
  13. this is a linebreak<br />
  14. this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
  15. this is a link with not allowed "rel" attribute: <a href="http://example.com/" rel="tag noallowed">example.com</a>
  16. this is an image: <img src="http://example.com/image.jpg"><br />
  17. <script>alert('hacked')</script>
  18. """
  19. @html_onerror_sample """
  20. <img src="http://example.com/image.jpg" onerror="alert('hacked')">
  21. """
  22. @html_span_class_sample """
  23. <span class="animate-spin">hi</span>
  24. """
  25. @html_span_microformats_sample """
  26. <span class="h-card"><a class="u-url mention">@<span>foo</span></a></span>
  27. """
  28. @html_span_invalid_microformats_sample """
  29. <span class="h-card"><a class="u-url mention animate-spin">@<span>foo</span></a></span>
  30. """
  31. describe "StripTags scrubber" do
  32. test "works as expected" do
  33. expected = """
  34. this is in bold
  35. this is a paragraph
  36. this is a linebreak
  37. this is a link with allowed &quot;rel&quot; attribute: example.com
  38. this is a link with not allowed &quot;rel&quot; attribute: example.com
  39. this is an image:
  40. alert(&#39;hacked&#39;)
  41. """
  42. assert expected == HTML.strip_tags(@html_sample)
  43. end
  44. test "does not allow attribute-based XSS" do
  45. expected = "\n"
  46. assert expected == HTML.strip_tags(@html_onerror_sample)
  47. end
  48. end
  49. describe "TwitterText scrubber" do
  50. test "normalizes HTML as expected" do
  51. expected = """
  52. this is in bold
  53. <p>this is a paragraph</p>
  54. this is a linebreak<br/>
  55. this is a link with allowed &quot;rel&quot; attribute: <a href="http://example.com/" rel="tag">example.com</a>
  56. this is a link with not allowed &quot;rel&quot; attribute: <a href="http://example.com/">example.com</a>
  57. this is an image: <img src="http://example.com/image.jpg"/><br/>
  58. alert(&#39;hacked&#39;)
  59. """
  60. assert expected == HTML.filter_tags(@html_sample, Pleroma.HTML.Scrubber.TwitterText)
  61. end
  62. test "does not allow attribute-based XSS" do
  63. expected = """
  64. <img src="http://example.com/image.jpg"/>
  65. """
  66. assert expected == HTML.filter_tags(@html_onerror_sample, Pleroma.HTML.Scrubber.TwitterText)
  67. end
  68. test "does not allow spans with invalid classes" do
  69. expected = """
  70. <span>hi</span>
  71. """
  72. assert expected ==
  73. HTML.filter_tags(@html_span_class_sample, Pleroma.HTML.Scrubber.TwitterText)
  74. end
  75. test "does allow microformats" do
  76. expected = """
  77. <span class="h-card"><a class="u-url mention">@<span>foo</span></a></span>
  78. """
  79. assert expected ==
  80. HTML.filter_tags(@html_span_microformats_sample, Pleroma.HTML.Scrubber.TwitterText)
  81. end
  82. test "filters invalid microformats markup" do
  83. expected = """
  84. <span class="h-card"><a>@<span>foo</span></a></span>
  85. """
  86. assert expected ==
  87. HTML.filter_tags(
  88. @html_span_invalid_microformats_sample,
  89. Pleroma.HTML.Scrubber.TwitterText
  90. )
  91. end
  92. end
  93. describe "default scrubber" do
  94. test "normalizes HTML as expected" do
  95. expected = """
  96. <b>this is in bold</b>
  97. <p>this is a paragraph</p>
  98. this is a linebreak<br/>
  99. this is a link with allowed &quot;rel&quot; attribute: <a href="http://example.com/" rel="tag">example.com</a>
  100. this is a link with not allowed &quot;rel&quot; attribute: <a href="http://example.com/">example.com</a>
  101. this is an image: <img src="http://example.com/image.jpg"/><br/>
  102. alert(&#39;hacked&#39;)
  103. """
  104. assert expected == HTML.filter_tags(@html_sample, Pleroma.HTML.Scrubber.Default)
  105. end
  106. test "does not allow attribute-based XSS" do
  107. expected = """
  108. <img src="http://example.com/image.jpg"/>
  109. """
  110. assert expected == HTML.filter_tags(@html_onerror_sample, Pleroma.HTML.Scrubber.Default)
  111. end
  112. test "does not allow spans with invalid classes" do
  113. expected = """
  114. <span>hi</span>
  115. """
  116. assert expected == HTML.filter_tags(@html_span_class_sample, Pleroma.HTML.Scrubber.Default)
  117. end
  118. test "does allow microformats" do
  119. expected = """
  120. <span class="h-card"><a class="u-url mention">@<span>foo</span></a></span>
  121. """
  122. assert expected ==
  123. HTML.filter_tags(@html_span_microformats_sample, Pleroma.HTML.Scrubber.Default)
  124. end
  125. test "filters invalid microformats markup" do
  126. expected = """
  127. <span class="h-card"><a>@<span>foo</span></a></span>
  128. """
  129. assert expected ==
  130. HTML.filter_tags(
  131. @html_span_invalid_microformats_sample,
  132. Pleroma.HTML.Scrubber.Default
  133. )
  134. end
  135. end
  136. describe "extract_first_external_url_from_object" do
  137. test "extracts the url" do
  138. user = insert(:user)
  139. {:ok, activity} =
  140. CommonAPI.post(user, %{
  141. status:
  142. "I think I just found the best github repo https://github.com/komeiji-satori/Dress"
  143. })
  144. object = Object.normalize(activity)
  145. {:ok, url} = HTML.extract_first_external_url_from_object(object)
  146. assert url == "https://github.com/komeiji-satori/Dress"
  147. end
  148. test "skips mentions" do
  149. user = insert(:user)
  150. other_user = insert(:user)
  151. {:ok, activity} =
  152. CommonAPI.post(user, %{
  153. status:
  154. "@#{other_user.nickname} install misskey! https://github.com/syuilo/misskey/blob/develop/docs/setup.en.md"
  155. })
  156. object = Object.normalize(activity)
  157. {:ok, url} = HTML.extract_first_external_url_from_object(object)
  158. assert url == "https://github.com/syuilo/misskey/blob/develop/docs/setup.en.md"
  159. refute url == other_user.ap_id
  160. end
  161. test "skips hashtags" do
  162. user = insert(:user)
  163. {:ok, activity} =
  164. CommonAPI.post(user, %{
  165. status: "#cofe https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140"
  166. })
  167. object = Object.normalize(activity)
  168. {:ok, url} = HTML.extract_first_external_url_from_object(object)
  169. assert url == "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140"
  170. end
  171. test "skips microformats hashtags" do
  172. user = insert(:user)
  173. {:ok, activity} =
  174. CommonAPI.post(user, %{
  175. status:
  176. "<a href=\"https://pleroma.gov/tags/cofe\" rel=\"tag\">#cofe</a> https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140",
  177. content_type: "text/html"
  178. })
  179. object = Object.normalize(activity)
  180. {:ok, url} = HTML.extract_first_external_url_from_object(object)
  181. assert url == "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140"
  182. end
  183. test "does not crash when there is an HTML entity in a link" do
  184. user = insert(:user)
  185. {:ok, activity} = CommonAPI.post(user, %{status: "\"http://cofe.com/?boomer=ok&foo=bar\""})
  186. object = Object.normalize(activity)
  187. assert {:ok, nil} = HTML.extract_first_external_url_from_object(object)
  188. end
  189. test "skips attachment links" do
  190. user = insert(:user)
  191. {:ok, activity} =
  192. CommonAPI.post(user, %{
  193. status:
  194. "<a href=\"https://pleroma.gov/media/d24caa3a498e21e0298377a9ca0149a4f4f8b767178aacf837542282e2d94fb1.png?name=image.png\" class=\"attachment\">image.png</a>"
  195. })
  196. object = Object.normalize(activity)
  197. assert {:ok, nil} = HTML.extract_first_external_url_from_object(object)
  198. end
  199. end
  200. end