From 98a219c7a908dfdc347a1c796fba1e13ff01d318 Mon Sep 17 00:00:00 2001
From: Thomas Citharel <tcit@tcit.fr>
Date: Wed, 24 Mar 2021 11:17:24 +0100
Subject: [PATCH] Validate URIs before trying to proxify them

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
---
 lib/web/proxy/reverse_proxy.ex | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/lib/web/proxy/reverse_proxy.ex b/lib/web/proxy/reverse_proxy.ex
index cfc677de8..f09d751a0 100644
--- a/lib/web/proxy/reverse_proxy.ex
+++ b/lib/web/proxy/reverse_proxy.ex
@@ -120,7 +120,8 @@ defmodule Mobilizon.Web.ReverseProxy do
         opts
       end
 
-    with {:ok, code, headers, client} <- request(method, url, req_headers, hackney_opts),
+    with {:is_url, true} <- {:is_url, valid_uri?(url)},
+         {:ok, code, headers, client} <- request(method, url, req_headers, hackney_opts),
          :ok <- header_length_constraint(headers, Keyword.get(opts, :max_body_length)) do
       response(conn, client, url, code, headers, opts)
     else
@@ -129,6 +130,13 @@ defmodule Mobilizon.Web.ReverseProxy do
         |> head_response(url, code, headers, opts)
         |> halt()
 
+      {:is_url, false} ->
+        Logger.warn("Tried to reverse proxy URL #{inspect(url)}")
+
+        conn
+        |> error_or_redirect(url, 500, "Request failed", opts)
+        |> halt()
+
       {:error, {:invalid_http_response, code}} ->
         Logger.error("#{__MODULE__}: request to #{inspect(url)} failed with HTTP status #{code}")
 
@@ -397,4 +405,10 @@ defmodule Mobilizon.Web.ReverseProxy do
   def filename(url_or_path) do
     if path = URI.parse(url_or_path).path, do: Path.basename(path)
   end
+
+  @spec valid_uri?(String.t()) :: boolean()
+  defp valid_uri?(url) do
+    uri = URI.parse(url)
+    uri.scheme != nil && uri.host =~ "."
+  end
 end