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

Commit ef0ef1e

Browse files
committed
refactor(xss): missing escape convert on cms resources
1 parent a7a0751 commit ef0ef1e

File tree

12 files changed

+76
-52
lines changed

12 files changed

+76
-52
lines changed

lib/groupher_server/cms/job.ex

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ defmodule GroupherServer.CMS.Job do
1616
Tag
1717
}
1818

19+
alias Helper.HTML
20+
1921
@timestamps_opts [type: :utc_datetime_usec]
2022
@required_fields ~w(title company company_logo body digest length)a
2123
@optional_fields ~w(origial_community_id desc company_link link_addr copy_right salary exp education field finance scale)a
@@ -96,11 +98,6 @@ defmodule GroupherServer.CMS.Job do
9698
content
9799
|> validate_length(:title, min: 3, max: 50)
98100
|> validate_length(:body, min: 3, max: 10_000)
99-
end
100-
101-
@doc false
102-
def update_changeset(%Job{} = job, attrs) do
103-
job
104-
|> cast(attrs, @optional_fields ++ @required_fields)
101+
|> HTML.safe_string(:body)
105102
end
106103
end

lib/groupher_server/cms/job_comment.ex

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ defmodule GroupherServer.CMS.JobComment do
77
alias GroupherServer.Accounts
88

99
alias GroupherServer.CMS.{Job, JobCommentReply, JobCommentLike, JobCommentDislike}
10+
alias Helper.HTML
1011

1112
@required_fields ~w(body author_id job_id floor)a
1213
@optional_fields ~w(reply_id)a
@@ -46,13 +47,6 @@ defmodule GroupherServer.CMS.JobComment do
4647
|> foreign_key_constraint(:job_id)
4748
|> foreign_key_constraint(:author_id)
4849
|> validate_length(:body, min: 3, max: 2000)
49-
end
50-
51-
@doc false
52-
def update_changeset(%JobComment{} = job_comment, attrs) do
53-
job_comment
54-
|> cast(attrs, @required_fields ++ @optional_fields)
55-
|> foreign_key_constraint(:job_id)
56-
|> foreign_key_constraint(:author_id)
50+
|> HTML.safe_string(:body)
5751
end
5852
end

lib/groupher_server/cms/repo.ex

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

20+
alias Helper.HTML
21+
2022
@timestamps_opts [type: :utc_datetime_usec]
2123
@required_fields ~w(title owner_name owner_url repo_url desc readme star_count issues_count prs_count fork_count watch_count)a
2224
@optional_fields ~w(origial_community_id last_sync homepage_url release_tag license)a
@@ -100,13 +102,6 @@ defmodule GroupherServer.CMS.Repo do
100102
|> validate_length(:title, min: 1, max: 80)
101103
|> cast_embed(:contributors, with: &RepoContributor.changeset/2)
102104
|> cast_embed(:primary_language, with: &RepoLang.changeset/2)
103-
end
104-
105-
@doc false
106-
def update_changeset(%Repo{} = repo, attrs) do
107-
repo
108-
|> cast(attrs, @optional_fields ++ @required_fields)
109-
|> cast_embed(:contributors, with: &RepoContributor.changeset/2)
110-
|> cast_embed(:primary_language, with: &RepoLang.changeset/2)
105+
|> HTML.safe_string(:readme)
111106
end
112107
end

lib/groupher_server/cms/repo_comment.ex

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ defmodule GroupherServer.CMS.RepoComment do
1313
RepoCommentReply
1414
}
1515

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

@@ -51,14 +53,6 @@ defmodule GroupherServer.CMS.RepoComment do
5153
|> foreign_key_constraint(:repo_id)
5254
|> foreign_key_constraint(:author_id)
5355
|> validate_length(:body, min: 3, max: 2000)
54-
end
55-
56-
@doc false
57-
def update_changeset(%RepoComment{} = repo_comment, attrs) do
58-
repo_comment
59-
|> cast(attrs, @required_fields ++ @optional_fields)
60-
|> validate_length(:body, min: 1)
61-
|> foreign_key_constraint(:repo_id)
62-
|> foreign_key_constraint(:author_id)
56+
|> HTML.safe_string(:body)
6357
end
6458
end

lib/groupher_server/cms/video.ex

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,4 @@ defmodule GroupherServer.CMS.Video do
9393
|> validate_length(:original_author_link, min: 5, max: 200)
9494
|> validate_length(:link, min: 5, max: 200)
9595
end
96-
97-
def update_changeset(%Video{} = video, attrs) do
98-
video
99-
|> cast(attrs, @optional_fields)
100-
|> validate_length(:original_author, min: 3, max: 30)
101-
end
10296
end

lib/groupher_server/cms/video_comment.ex

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ defmodule GroupherServer.CMS.VideoComment do
1313
VideoCommentReply
1414
}
1515

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

@@ -51,14 +53,6 @@ defmodule GroupherServer.CMS.VideoComment do
5153
|> foreign_key_constraint(:video_id)
5254
|> foreign_key_constraint(:author_id)
5355
|> validate_length(:body, min: 3, max: 2000)
54-
end
55-
56-
@doc false
57-
def update_changeset(%VideoComment{} = video_comment, attrs) do
58-
video_comment
59-
|> cast(attrs, @required_fields ++ @optional_fields)
60-
|> validate_length(:body, min: 1)
61-
|> foreign_key_constraint(:video_id)
62-
|> foreign_key_constraint(:author_id)
56+
|> HTML.safe_string(:body)
6357
end
6458
end

lib/helper/html.ex

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@ defmodule Helper.HTML do
66
import Ecto.Changeset
77
alias Phoenix.HTML
88

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} ->
9+
def safe_string(%Ecto.Changeset{valid?: true, changes: changes} = changeset, field) do
10+
case Map.has_key?(changes, field) do
11+
true ->
1312
changeset
1413
|> put_change(field, escape_to_safe_string(changes[field]))
1514

@@ -18,5 +17,18 @@ defmodule Helper.HTML do
1817
end
1918
end
2019

20+
def safe_string(%Ecto.Changeset{} = changeset, _field), do: changeset
21+
22+
# def safe_string(%Ecto.Changeset{} = changeset, field) do
23+
# case changeset do
24+
# %Ecto.Changeset{valid?: true, changes: changes} ->
25+
# changeset
26+
# |> put_change(field, escape_to_safe_string(changes[field]))
27+
28+
# _ ->
29+
# changeset
30+
# end
31+
# end
32+
2133
defp escape_to_safe_string(v), do: v |> HTML.html_escape() |> HTML.safe_to_string()
2234
end

test/groupher_server_web/mutation/cms/job_test.exs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,21 @@ defmodule GroupherServer.Test.Mutation.Job do
9292
assert created["id"] == to_string(found.id)
9393
end
9494

95+
@tag :wip
96+
test "create job should excape xss attracts" do
97+
{:ok, user} = db_insert(:user)
98+
user_conn = simu_conn(:user, user)
99+
100+
{:ok, community} = db_insert(:community)
101+
job_attr = mock_attrs(:job, %{body: xss_string()})
102+
103+
variables = job_attr |> Map.merge(%{communityId: community.id}) |> camelize_map_key
104+
created = user_conn |> mutation_result(@create_job_query, variables, "createJob")
105+
{:ok, job} = ORM.find(CMS.Job, created["id"])
106+
107+
assert job.body == xss_safe_string()
108+
end
109+
95110
test "can create job with tags" do
96111
{:ok, user} = db_insert(:user)
97112
user_conn = simu_conn(:user, user)

test/groupher_server_web/mutation/cms/post_comment_test.exs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,17 @@ defmodule GroupherServer.Test.Mutation.PostComment do
4848
assert created["id"] == to_string(found.id)
4949
end
5050

51+
@tag :wip
52+
test "xss comment should be escaped", ~m(user_conn community post)a do
53+
variables = %{community: community.raw, thread: "POST", id: post.id, body: xss_string()}
54+
created = user_conn |> mutation_result(@create_comment_query, variables, "createComment")
55+
56+
{:ok, found} = ORM.find(CMS.PostComment, created["id"])
57+
58+
assert created["id"] == to_string(found.id)
59+
assert created["body"] == xss_safe_string()
60+
end
61+
5162
test "guest user create comment fails", ~m(guest_conn post community)a do
5263
variables = %{community: community.raw, thread: "POST", id: post.id, body: "this a comment"}
5364

test/groupher_server_web/mutation/cms/post_test.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,13 @@ defmodule GroupherServer.Test.Mutation.Post do
6969
user_conn = simu_conn(:user, user)
7070

7171
{:ok, community} = db_insert(:community)
72-
post_attr = mock_attrs(:post, %{body: "<script>alert(\"hello,world\")</script>"})
72+
post_attr = mock_attrs(:post, %{body: xss_string()})
7373

7474
variables = post_attr |> Map.merge(%{communityId: community.id})
7575
created = user_conn |> mutation_result(@create_post_query, variables, "createPost")
7676
{:ok, post} = ORM.find(CMS.Post, created["id"])
7777

78-
assert post.body == "&lt;script&gt;alert(&quot;hello,world&quot;)&lt;/script&gt;"
78+
assert post.body == xss_safe_string()
7979
end
8080

8181
# NOTE: this test is IMPORTANT, cause json_codec: Jason in router will cause

0 commit comments

Comments
 (0)