fix: always consider report content as text

Report content was used as HTML in front-end and e-mails but wasn't sanitized as such.

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2023-12-06 11:05:56 +01:00
parent ded59bec27
commit ffff379d47
No known key found for this signature in database
GPG key ID: A061B9DDE0CA0773
5 changed files with 49 additions and 8 deletions

View file

@ -60,6 +60,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Flag do
"actor" => Relay.get_actor().url, "actor" => Relay.get_actor().url,
"id" => report.url, "id" => report.url,
"content" => report.content, "content" => report.content,
"mediaType" => "text/plain",
"object" => object "object" => object
} }
end end

View file

@ -192,7 +192,7 @@
> >
<p style="margin: 0"> <p style="margin: 0">
<h3><%= gettext("Reasons for report") %></h3> <h3><%= gettext("Reasons for report") %></h3>
<%= @report.content |> raw %> <%= @report.content %>
</p> </p>
<table <table
cellspacing="0" cellspacing="0"

View file

@ -63,7 +63,9 @@
{{ t("Reported by an unknown actor") }} {{ t("Reported by an unknown actor") }}
</span> </span>
</div> </div>
<div class="" v-if="report.content" v-html="report.content" /> <div class="line-clamp-1" v-if="report.content">
{{ report.content }}
</div>
</div> </div>
</div> </div>
</template> </template>

View file

@ -216,11 +216,9 @@
</div> </div>
<p v-else>{{ t("Unknown actor") }}</p> <p v-else>{{ t("Unknown actor") }}</p>
</div> </div>
<div <div class="prose dark:prose-invert" v-if="report.content">
class="prose dark:prose-invert" {{ report.content }}
v-if="report.content" </div>
v-html="nl2br(report.content)"
/>
<p v-else>{{ t("No comment") }}</p> <p v-else>{{ t("No comment") }}</p>
</div> </div>
</section> </section>
@ -407,7 +405,6 @@ import {
} from "@/types/actor"; } from "@/types/actor";
import { DELETE_EVENT } from "@/graphql/event"; import { DELETE_EVENT } from "@/graphql/event";
import uniq from "lodash/uniq"; import uniq from "lodash/uniq";
import { nl2br } from "@/utils/html";
import { DELETE_COMMENT } from "@/graphql/comment"; import { DELETE_COMMENT } from "@/graphql/comment";
import { IComment } from "@/types/comment.model"; import { IComment } from "@/types/comment.model";
import { ActorType, AntiSpamFeedback, ReportStatusEnum } from "@/types/enums"; import { ActorType, AntiSpamFeedback, ReportStatusEnum } from "@/types/enums";

View file

@ -0,0 +1,41 @@
defmodule Mobilizon.Federation.ActivityPub.Types.ReportsTest do
use Mobilizon.DataCase
import Mobilizon.Factory
alias Mobilizon.Actors.Actor
alias Mobilizon.Federation.ActivityPub.Types.Reports
alias Mobilizon.Reports.Report
describe "report creation" do
test "with XSS" do
%Actor{id: reporter_id} = insert(:actor)
%Actor{id: reported_id} = insert(:actor)
content =
"hello <meta http-equiv=\"refresh\" content=\"0; url=http://example.com/\" />"
assert {:ok, %Report{content: saved_content}, _} =
Reports.flag(%{
reporter_id: reporter_id,
reported_id: reported_id,
content: content
})
assert saved_content == "hello "
content =
"<<img src=''/>meta http-equiv=\"refresh\" content=\"0; url=http://example.com/\" />"
assert {:ok, %Report{content: saved_content}, _} =
Reports.flag(%{
reporter_id: reporter_id,
reported_id: reported_id,
content: content
})
assert saved_content ==
"<meta http-equiv=\"refresh\" content=\"0; url=http://example.com/\" />"
end
end
end