diff options
author | lambda <pleromagit@rogerbraun.net> | 2018-11-13 15:15:05 +0000 |
---|---|---|
committer | lambda <pleromagit@rogerbraun.net> | 2018-11-13 15:15:05 +0000 |
commit | a43195bdaa295f624315cba9daad42097de0cfe7 (patch) | |
tree | c22a5d599bb619ce640ac5b790d46eac2d95982d /lib/pleroma/web/media_proxy/controller.ex | |
parent | 22d20c497b813cdaedddb40a46df2f597311b235 (diff) | |
parent | 9b553a1087a3539280a4a085bcf7a79f29972f0a (diff) | |
download | pleroma-a43195bdaa295f624315cba9daad42097de0cfe7.tar.gz |
Merge branch 'media-proxy-safety' into 'develop'
media_proxy: CSP, content-disposition
See merge request pleroma/pleroma!448
Diffstat (limited to 'lib/pleroma/web/media_proxy/controller.ex')
-rw-r--r-- | lib/pleroma/web/media_proxy/controller.ex | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/lib/pleroma/web/media_proxy/controller.ex b/lib/pleroma/web/media_proxy/controller.ex index 8195a665e..10e6b4e52 100644 --- a/lib/pleroma/web/media_proxy/controller.ex +++ b/lib/pleroma/web/media_proxy/controller.ex @@ -11,15 +11,47 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController do error: "public, must-revalidate, max-age=160" } - def remote(conn, %{"sig" => sig, "url" => url}) do + # Content-types that will not be returned as content-disposition attachments + # Override with :media_proxy, :safe_content_types in the configuration + @safe_content_types [ + "image/gif", + "image/jpeg", + "image/jpg", + "image/png", + "image/svg+xml", + "audio/mpeg", + "audio/mp3", + "video/webm", + "video/mp4" + ] + + def remote(conn, params = %{"sig" => sig, "url" => url}) do config = Application.get_env(:pleroma, :media_proxy, []) with true <- Keyword.get(config, :enabled, false), {:ok, url} <- Pleroma.Web.MediaProxy.decode_url(sig, url), - {:ok, content_type, body} <- proxy_request(url) do + filename <- Path.basename(url), + true <- + if(Map.get(params, "filename"), + do: filename == Path.basename(conn.request_path), + else: true + ), + {:ok, content_type, body} <- proxy_request(url), + safe_content_type <- + Enum.member?( + Keyword.get(config, :safe_content_types, @safe_content_types), + content_type + ) do conn |> put_resp_content_type(content_type) |> set_cache_header(:default) + |> put_resp_header( + "content-security-policy", + "default-src 'none'; style-src 'unsafe-inline'; media-src data:; img-src 'self' data:" + ) + |> put_resp_header("x-xss-protection", "1; mode=block") + |> put_resp_header("x-content-type-options", "nosniff") + |> put_attachement_header(safe_content_type, filename) |> send_resp(200, body) else false -> @@ -92,6 +124,12 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController do # TODO: the body is passed here as well because some hosts do not provide a content-type. # At some point we may want to use magic numbers to discover the content-type and reply a proper one. defp proxy_request_content_type(headers, _body) do - headers["Content-Type"] || headers["content-type"] || "image/jpeg" + headers["Content-Type"] || headers["content-type"] || "application/octet-stream" + end + + defp put_attachement_header(conn, true, _), do: conn + + defp put_attachement_header(conn, false, filename) do + put_resp_header(conn, "content-disposition", "attachment; filename='#{filename}'") end end |