Skip to content
This repository was archived by the owner on Nov 8, 2022. It is now read-only.

Commit a7a0751

Browse files
committed
fix(xss): add escape hepler for resources
1 parent a505262 commit a7a0751

File tree

5 files changed

+51
-16
lines changed

5 files changed

+51
-16
lines changed

lib/groupher_server/cms/post.ex

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ defmodule GroupherServer.CMS.Post do
1717
Topic
1818
}
1919

20+
alias Helper.HTML
21+
2022
@timestamps_opts [type: :utc_datetime_usec]
2123
@required_fields ~w(title body digest length)a
2224
@optional_fields ~w(origial_community_id link_addr copy_right link_addr link_icon)a
@@ -104,15 +106,7 @@ defmodule GroupherServer.CMS.Post do
104106
|> validate_length(:title, min: 3, max: 50)
105107
|> validate_length(:body, min: 3, max: 10_000)
106108
|> validate_length(:link_addr, min: 5, max: 400)
107-
108-
# |> foreign_key_constraint(:posts_tags, name: :posts_tags_tag_id_fkey)
109-
# |> foreign_key_constraint(name: :posts_tags_tag_id_fkey)
110-
end
111-
112-
@doc false
113-
def update_changeset(%Post{} = post, attrs) do
114-
post
115-
|> cast(attrs, @optional_fields ++ @required_fields)
109+
|> HTML.safe_string(:body)
116110

117111
# |> foreign_key_constraint(:posts_tags, name: :posts_tags_tag_id_fkey)
118112
# |> foreign_key_constraint(name: :posts_tags_tag_id_fkey)

lib/groupher_server/cms/post_comment.ex

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ defmodule GroupherServer.CMS.PostComment do
1313
PostCommentReply
1414
}
1515

16+
alias Helper.HTML
17+
1618
@required_fields ~w(body author_id post_id floor)a
1719
@optional_fields ~w(reply_id)a
1820

@@ -51,13 +53,14 @@ defmodule GroupherServer.CMS.PostComment do
5153
|> foreign_key_constraint(:post_id)
5254
|> foreign_key_constraint(:author_id)
5355
|> validate_length(:body, min: 3, max: 2000)
56+
|> HTML.safe_string(:body)
5457
end
5558

56-
@doc false
57-
def update_changeset(%PostComment{} = post_comment, attrs) do
58-
post_comment
59-
|> cast(attrs, @required_fields ++ @optional_fields)
60-
|> foreign_key_constraint(:post_id)
61-
|> foreign_key_constraint(:author_id)
62-
end
59+
# @doc false
60+
# def update_changeset(%PostComment{} = post_comment, attrs) do
61+
# post_comment
62+
# |> cast(attrs, @required_fields ++ @optional_fields)
63+
# |> foreign_key_constraint(:post_id)
64+
# |> foreign_key_constraint(:author_id)
65+
# end
6366
end

lib/helper/html.ex

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
defmodule Helper.HTML do
2+
@moduledoc """
3+
escape unsafe inputs, especially for the markdown contents
4+
"""
5+
6+
import Ecto.Changeset
7+
alias Phoenix.HTML
8+
9+
def safe_string(%Ecto.Changeset{} = changeset, field) do
10+
case changeset do
11+
# %Ecto.Changeset{valid?: true, changes: %{body: val}} ->
12+
%Ecto.Changeset{valid?: true, changes: changes} ->
13+
changeset
14+
|> put_change(field, escape_to_safe_string(changes[field]))
15+
16+
_ ->
17+
changeset
18+
end
19+
end
20+
21+
defp escape_to_safe_string(v), do: v |> HTML.html_escape() |> HTML.safe_to_string()
22+
end

mix.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ defmodule GroupherServer.Mixfile do
5353
[
5454
{:phoenix, "~> 1.4.1"},
5555
{:phoenix_pubsub, "~> 1.1.1"},
56+
{:phoenix_html, "~> 2.13.3"},
5657
{:ecto_sql, "~> 3.1.2"},
5758
{:phoenix_ecto, "~> 4.0"},
5859
{:postgrex, ">= 0.14.1"},

test/groupher_server_web/mutation/cms/post_test.exs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,21 @@ defmodule GroupherServer.Test.Mutation.Post do
6363
assert {:ok, _} = ORM.find_by(CMS.Author, user_id: user.id)
6464
end
6565

66+
@tag :wip
67+
test "create post should excape xss attracts" do
68+
{:ok, user} = db_insert(:user)
69+
user_conn = simu_conn(:user, user)
70+
71+
{:ok, community} = db_insert(:community)
72+
post_attr = mock_attrs(:post, %{body: "<script>alert(\"hello,world\")</script>"})
73+
74+
variables = post_attr |> Map.merge(%{communityId: community.id})
75+
created = user_conn |> mutation_result(@create_post_query, variables, "createPost")
76+
{:ok, post} = ORM.find(CMS.Post, created["id"])
77+
78+
assert post.body == "&lt;script&gt;alert(&quot;hello,world&quot;)&lt;/script&gt;"
79+
end
80+
6681
# NOTE: this test is IMPORTANT, cause json_codec: Jason in router will cause
6782
# server crash when GraphQL parse error
6883
test "create post with missing non_null field should get 200 error" do

0 commit comments

Comments
 (0)