static_fe: Sanitize HTML in users
authorHaelwenn (lanodan) Monnier <contact@hacktivis.me>
Sun, 15 Mar 2020 16:00:54 +0000 (17:00 +0100)
committerHaelwenn (lanodan) Monnier <contact@hacktivis.me>
Sun, 15 Mar 2020 19:44:04 +0000 (20:44 +0100)
lib/pleroma/user.ex
lib/pleroma/web/activity_pub/views/user_view.ex
lib/pleroma/web/admin_api/views/account_view.ex
lib/pleroma/web/mastodon_api/views/account_view.ex
lib/pleroma/web/static_fe/static_fe_controller.ex

index db510d957090e5e7e90955a0991f61b1bd70fbf1..911dde6e2876bc9fba1b7dc093554e872a1c3269 100644 (file)
@@ -16,6 +16,7 @@ defmodule Pleroma.User do
   alias Pleroma.Conversation.Participation
   alias Pleroma.Delivery
   alias Pleroma.FollowingRelationship
+  alias Pleroma.HTML
   alias Pleroma.Keys
   alias Pleroma.Notification
   alias Pleroma.Object
@@ -2032,4 +2033,27 @@ defmodule Pleroma.User do
     |> validate_required([:invisible])
     |> update_and_set_cache()
   end
+
+  def sanitize_html(%User{} = user) do
+    sanitize_html(user, nil)
+  end
+
+  # User data that mastodon isn't filtering (treated as plaintext):
+  # - field name
+  # - display name
+  def sanitize_html(%User{} = user, filter) do
+    fields =
+      user
+      |> User.fields()
+      |> Enum.map(fn %{"name" => name, "value" => value} ->
+        %{
+          "name" => name,
+          "value" => HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly)
+        }
+      end)
+
+    user
+    |> Map.put(:bio, HTML.filter_tags(user.bio, filter))
+    |> Map.put(:fields, fields)
+  end
 end
index c0358b6787b55f262398ee57d2fc39cda2c2097e..bc21ac6c72804e0480bd3188902fd72285dc22a6 100644 (file)
@@ -73,6 +73,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
     {:ok, _, public_key} = Keys.keys_from_pem(user.keys)
     public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
     public_key = :public_key.pem_encode([public_key])
+    user = User.sanitize_html(user)
 
     endpoints = render("endpoints.json", %{user: user})
 
@@ -81,12 +82,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do
     fields =
       user
       |> User.fields()
-      |> Enum.map(fn %{"name" => name, "value" => value} ->
-        %{
-          "name" => Pleroma.HTML.strip_tags(name),
-          "value" => Pleroma.HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly)
-        }
-      end)
       |> Enum.map(&Map.put(&1, "type", "PropertyValue"))
 
     %{
index 619390ef4e51ce0518bf52882ea4363ab5adfac1..1e03849de035f950d73ee99bf91011b1201ba892 100644 (file)
@@ -5,7 +5,6 @@
 defmodule Pleroma.Web.AdminAPI.AccountView do
   use Pleroma.Web, :view
 
-  alias Pleroma.HTML
   alias Pleroma.User
   alias Pleroma.Web.AdminAPI.AccountView
   alias Pleroma.Web.MediaProxy
@@ -26,7 +25,8 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
 
   def render("show.json", %{user: user}) do
     avatar = User.avatar_url(user) |> MediaProxy.url()
-    display_name = HTML.strip_tags(user.name || user.nickname)
+    display_name = Pleroma.HTML.strip_tags(user.name || user.nickname)
+    user = User.sanitize_html(user, FastSanitize.Sanitizer.StripTags)
 
     %{
       "id" => user.id,
index 6dc19125022e1576fa430a91603c96dd39d0345a..341dc2c91e2f059a7ced3c4c50d4aca387796138 100644 (file)
@@ -5,7 +5,6 @@
 defmodule Pleroma.Web.MastodonAPI.AccountView do
   use Pleroma.Web, :view
 
-  alias Pleroma.HTML
   alias Pleroma.User
   alias Pleroma.Web.CommonAPI.Utils
   alias Pleroma.Web.MastodonAPI.AccountView
@@ -67,6 +66,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
   end
 
   defp do_render("show.json", %{user: user} = opts) do
+    user = User.sanitize_html(user, User.html_filter_policy(opts[:for]))
     display_name = user.name || user.nickname
 
     image = User.avatar_url(user) |> MediaProxy.url()
@@ -100,17 +100,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
         }
       end)
 
-    fields =
-      user
-      |> User.fields()
-      |> Enum.map(fn %{"name" => name, "value" => value} ->
-        %{
-          "name" => name,
-          "value" => Pleroma.HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly)
-        }
-      end)
-
-    bio = HTML.filter_tags(user.bio, User.html_filter_policy(opts[:for]))
     relationship = render("relationship.json", %{user: opts[:for], target: user})
 
     %{
@@ -123,17 +112,17 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
       followers_count: followers_count,
       following_count: following_count,
       statuses_count: user.note_count,
-      note: bio || "",
+      note: user.bio || "",
       url: User.profile_url(user),
       avatar: image,
       avatar_static: image,
       header: header,
       header_static: header,
       emojis: emojis,
-      fields: fields,
+      fields: user.fields,
       bot: bot,
       source: %{
-        note: HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
+        note: Pleroma.HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
         sensitive: false,
         fields: user.raw_fields,
         pleroma: %{
index 0b77f949c9f7b03efaa60bd6d1e58a3fe9c235ce..7f946426801ee1d6e69fe67eefd2e51538ec07a6 100644 (file)
@@ -66,7 +66,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do
       end
 
     %{
-      user: user,
+      user: User.sanitize_html(user),
       title: get_title(activity.object),
       content: content,
       attachment: data["attachment"],
@@ -120,7 +120,7 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do
         next_page_id = List.last(timeline) && List.last(timeline).id
 
         render(conn, "profile.html", %{
-          user: user,
+          user: User.sanitize_html(user),
           timeline: timeline,
           prev_page_id: prev_page_id,
           next_page_id: next_page_id,