diff --git a/CHANGELOG.md b/CHANGELOG.md index 97c73a267..2edf2c758 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## Unreleased + +## Added +- Added a new configuration option to the MediaProxy feature that allows the blocking of specific domains from using the media proxy or being explicitly allowed by the Content-Security-Policy. + - Please make sure instances you wanted to block media from are not in the MediaProxy `whitelist`, and instead use `blocklist`. + ## 2023.05 ## Added diff --git a/config/config.exs b/config/config.exs index ca397a8fd..3430ee4d7 100644 --- a/config/config.exs +++ b/config/config.exs @@ -443,7 +443,8 @@ # Note: max_read_duration defaults to Pleroma.ReverseProxy.max_read_duration_default/1 max_read_duration: 30_000 ], - whitelist: [] + whitelist: [], + blocklist: [] config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Http, method: :purge, diff --git a/config/description.exs b/config/description.exs index bd20cb239..d425bf386 100644 --- a/config/description.exs +++ b/config/description.exs @@ -1558,7 +1558,21 @@ %{ key: :whitelist, type: {:list, :string}, - description: "List of hosts with scheme to bypass the MediaProxy", + description: """ + List of hosts with scheme to bypass the MediaProxy.\n + The media will be fetched by the client, directly from the remote server.\n + To allow this, it will Content-Security-Policy exceptions for each instance listed.\n + This is to be used for instances you trust and do not want to cache media for. + """, + suggestions: ["http://example.com"] + }, + %{ + key: :blocklist, + type: {:list, :string}, + description: """ + List of hosts with scheme which will not go through the MediaProxy, and will not be explicitly allowed by the Content-Security-Policy. + This is to be used for instances where you do not want their media to go through your server or to be accessed by clients. + """, suggestions: ["http://example.com"] } ] diff --git a/lib/pleroma/web/media_proxy.ex b/lib/pleroma/web/media_proxy.ex index 0b232f14b..9a5f47716 100644 --- a/lib/pleroma/web/media_proxy.ex +++ b/lib/pleroma/web/media_proxy.ex @@ -52,7 +52,7 @@ def url(url) do @spec url_proxiable?(String.t()) :: boolean() def url_proxiable?(url) do - not local?(url) and not whitelisted?(url) + not local?(url) and not whitelisted?(url) and not blocked?(url) end def preview_url(url, preview_params \\ []) do @@ -83,6 +83,11 @@ def whitelisted?(url) do domain in mediaproxy_whitelist_domains end + def blocked?(url) do + %{host: domain} = URI.parse(url) + domain in Config.get([:media_proxy, :whitelist]) + end + defp maybe_get_domain_from_url("http" <> _ = url) do URI.parse(url).host end diff --git a/test/pleroma/web/media_proxy_test.exs b/test/pleroma/web/media_proxy_test.exs index d97874f3a..71d7d605d 100644 --- a/test/pleroma/web/media_proxy_test.exs +++ b/test/pleroma/web/media_proxy_test.exs @@ -199,6 +199,15 @@ test "mediaproxy whitelist" do assert unencoded == url end + test "mediaproxy blocklist" do + clear_config([:media_proxy, :whitelist], ["https://google.com"]) + clear_config([:media_proxy, :blocklist], ["https://feld.me"]) + url = "https://feld.me/foo.png" + + unencoded = MediaProxy.url(url) + assert unencoded == url + end + # TODO: delete after removing support bare domains for media proxy whitelist test "mediaproxy whitelist bare domains whitelist (deprecated)" do clear_config([:media_proxy, :whitelist], ["google.com", "feld.me"]) @@ -220,6 +229,18 @@ test "does not change whitelisted urls" do assert String.starts_with?(encoded, media_url) end + test "does not change blocked urls" do + clear_config([:media_proxy, :whitelist], ["mycdn.akamai.com"]) + clear_config([:media_proxy, :base_url], "https://cache.pleroma.social") + + media_url = "https://mycdn.akamai.com" + + url = "#{media_url}/static/logo.png" + encoded = MediaProxy.url(url) + + assert String.starts_with?(encoded, media_url) + end + test "ensure Pleroma.Upload base_url is always whitelisted" do media_url = "https://media.pleroma.social" clear_config([Pleroma.Upload, :base_url], media_url) diff --git a/test/pleroma/web/plugs/http_security_plug_test.exs b/test/pleroma/web/plugs/http_security_plug_test.exs index d88d4624f..96fff304e 100644 --- a/test/pleroma/web/plugs/http_security_plug_test.exs +++ b/test/pleroma/web/plugs/http_security_plug_test.exs @@ -128,6 +128,12 @@ test "with media_proxy bare domains whitelist (deprecated)", %{conn: conn} do clear_config([:media_proxy, :whitelist], ["example4.com", "example5.com"]) assert_media_img_src(conn, "example5.com example4.com") end + + test "with media_proxy blocklist", %{conn: conn} do + clear_config([:media_proxy, :whitelist], ["https://example6.com", "https://example7.com"]) + clear_config([:media_proxy, :blocklist], ["https://example8.com"]) + assert_media_img_src(conn, "https://example7.com https://example6.com") + end end defp assert_media_img_src(conn, url) do