Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 lines
7.1KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2018 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 "rel" attribute: example.com
  38. this is a link with not allowed "rel" attribute: example.com
  39. this is an image:
  40. alert('hacked')
  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 "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
  56. this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
  57. this is an image: <img src="http://example.com/image.jpg" /><br />
  58. alert('hacked')
  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 "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
  100. this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
  101. this is an image: <img src="http://example.com/image.jpg" /><br />
  102. alert('hacked')
  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" 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(object, object.data["content"])
  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(object, object.data["content"])
  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" =>
  166. "#cofe https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140"
  167. })
  168. object = Object.normalize(activity)
  169. {:ok, url} = HTML.extract_first_external_url(object, object.data["content"])
  170. assert url == "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140"
  171. end
  172. test "skips microformats hashtags" do
  173. user = insert(:user)
  174. {:ok, activity} =
  175. CommonAPI.post(user, %{
  176. "status" =>
  177. "<a href=\"https://pleroma.gov/tags/cofe\" rel=\"tag\">#cofe</a> https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140",
  178. "content_type" => "text/html"
  179. })
  180. object = Object.normalize(activity)
  181. {:ok, url} = HTML.extract_first_external_url(object, object.data["content"])
  182. assert url == "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=72255140"
  183. end
  184. end
  185. end