Merge branch 'audit-mix-audit-report' (#69) into release/2.11
# Conflicts: # lib/pleroma/http/adapter_helper/hackney.ex
This commit is contained in:
commit
9ea8d37e9f
23 changed files with 216 additions and 22 deletions
|
|
@ -169,7 +169,8 @@ defmodule Pleroma.Formatter do
|
|||
Enum.map(nodes, &strip_email_autolinks(&1, emails))
|
||||
end
|
||||
|
||||
defp strip_email_autolinks({"a", attrs, [email], _meta} = node, emails) do
|
||||
defp strip_email_autolinks({"a", attrs, [email], _meta} = node, emails)
|
||||
when is_binary(email) do
|
||||
if List.keyfind(attrs, "href", 0) == {"href", "mailto:" <> email} and
|
||||
MapSet.member?(emails, email) do
|
||||
email
|
||||
|
|
@ -251,9 +252,13 @@ defmodule Pleroma.Formatter do
|
|||
|
||||
defp sanitize_markdown_url(value, name) do
|
||||
if String.downcase(to_string(name)) in ["href", "src"] do
|
||||
value
|
||||
|> String.split(~r/["<>]/, parts: 2)
|
||||
|> hd()
|
||||
# Percent-encode instead of cutting, so the URL stays complete but can
|
||||
# never close the attribute or open a tag.
|
||||
String.replace(value, ~r/["<>]/, fn
|
||||
"\"" -> "%22"
|
||||
"<" -> "%3C"
|
||||
">" -> "%3E"
|
||||
end)
|
||||
else
|
||||
value
|
||||
end
|
||||
|
|
|
|||
40
lib/pleroma/html/uri_attributes.ex
Normal file
40
lib/pleroma/html/uri_attributes.ex
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.HTML.URIAttributes do
|
||||
@moduledoc """
|
||||
URI attribute rules for the scrubbers.
|
||||
|
||||
Works like `FastSanitize.Sanitizer.Meta.allow_tag_with_uri_attributes/3`, but
|
||||
checks the scheme the way a browser reads the URL. Browsers remove tabs and
|
||||
newlines anywhere and control characters and spaces at the start, so
|
||||
`java\\tscript:` is a `javascript:` link to them, while `URI.parse/1` finds no
|
||||
scheme and FastSanitize lets it through.
|
||||
"""
|
||||
|
||||
defmacro allow_tag_with_uri_attributes(tag, attrs, valid_schemes) do
|
||||
for attr <- attrs do
|
||||
quote do
|
||||
def scrub_attribute(unquote(tag), {unquote(attr), "&" <> _}), do: nil
|
||||
|
||||
def scrub_attribute(unquote(tag), {unquote(attr), uri} = attribute) do
|
||||
if Pleroma.HTML.URIAttributes.valid_scheme?(uri, unquote(valid_schemes)),
|
||||
do: attribute
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@spec valid_scheme?(String.t(), [String.t()]) :: boolean()
|
||||
def valid_scheme?(uri, valid_schemes) do
|
||||
scheme =
|
||||
uri
|
||||
|> String.replace(~r/[\t\n\r]/, "")
|
||||
|> String.replace(~r/\A[\x00-\x20]+/, "")
|
||||
|> URI.parse()
|
||||
|> Map.get(:scheme)
|
||||
|
||||
is_nil(scheme) or scheme in valid_schemes
|
||||
end
|
||||
end
|
||||
|
|
@ -28,6 +28,7 @@ defmodule Pleroma.HTTP.AdapterHelper.Gun do
|
|||
|
||||
@defaults
|
||||
|> Keyword.merge(config_opts)
|
||||
|> ssl_options_to_tls_opts()
|
||||
|> add_scheme_opts(uri)
|
||||
|> AdapterHelper.maybe_add_proxy(proxy)
|
||||
|> Keyword.merge(incoming_opts)
|
||||
|
|
@ -35,6 +36,15 @@ defmodule Pleroma.HTTP.AdapterHelper.Gun do
|
|||
|> maybe_stream()
|
||||
end
|
||||
|
||||
# [:http, :adapter, :ssl_options] is Hackney's name for the TLS options,
|
||||
# and AdminFE sets it. Keep those settings when Gun is the adapter.
|
||||
defp ssl_options_to_tls_opts(opts) do
|
||||
case Keyword.pop(opts, :ssl_options) do
|
||||
{nil, opts} -> opts
|
||||
{ssl_options, opts} -> Keyword.put_new(opts, :tls_opts, ssl_options)
|
||||
end
|
||||
end
|
||||
|
||||
defp add_scheme_opts(opts, %{scheme: "http"}), do: opts
|
||||
|
||||
defp add_scheme_opts(opts, %{scheme: "https"}) do
|
||||
|
|
|
|||
|
|
@ -30,9 +30,25 @@ defmodule Pleroma.HTTP.AdapterHelper.Hackney do
|
|||
|> Pleroma.HTTP.AdapterHelper.maybe_add_proxy(proxy)
|
||||
|> Keyword.put(:follow_redirect, false)
|
||||
|> Keyword.put(:force_redirect, false)
|
||||
|> normalize_proxy()
|
||||
|> Pleroma.HTTP.TLS.put_hackney_ssl_options()
|
||||
end
|
||||
|
||||
# Hackney 4 ignores a proxy whose host is an IP tuple and connects directly.
|
||||
# ConfigDB turns a numeric proxy host into such a tuple.
|
||||
defp normalize_proxy(opts) do
|
||||
case Keyword.fetch(opts, :proxy) do
|
||||
{:ok, {type, host, port}} when is_tuple(host) ->
|
||||
Keyword.put(opts, :proxy, {type, :inet.ntoa(host), port})
|
||||
|
||||
{:ok, {host, port}} when is_tuple(host) ->
|
||||
Keyword.put(opts, :proxy, {:inet.ntoa(host), port})
|
||||
|
||||
_ ->
|
||||
opts
|
||||
end
|
||||
end
|
||||
|
||||
defp add_scheme_opts(opts, _), do: opts
|
||||
|
||||
defp maybe_add_with_body(opts) do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue