Apply Patch
authorfoxing <foxing@noreply.akkoma>
Sun, 12 Mar 2023 19:13:56 +0000 (19:13 +0000)
committerfoxing <foxing@noreply.akkoma>
Sun, 12 Mar 2023 19:13:56 +0000 (19:13 +0000)
lib/pleroma/web/activity_pub/activity_pub.ex
test/pleroma/web/activity_pub/activity_pub_test.exs
test/pleroma/web/mastodon_api/controllers/media_controller_test.exs
test/pleroma/web/mastodon_api/update_credentials_test.exs

index 8e55df0d8cac2fc955b2394e197be133167ffe89..649bf909544d3f07f484c2bf966623bc29ec4e7b 100644 (file)
@@ -1502,13 +1502,22 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
 
   @spec upload(Upload.source(), keyword()) :: {:ok, Object.t()} | {:error, any()}
   def upload(file, opts \\ []) do
-    with {:ok, data} <- Upload.store(file, opts) do
+    with {:ok, data} <- Upload.store(sanitize_upload_file(file), opts) do
       obj_data = Maps.put_if_present(data, "actor", opts[:actor])
 
       Repo.insert(%Object{data: obj_data})
     end
   end
 
+  defp sanitize_upload_file(%Plug.Upload{filename: filename} = upload) when is_binary(filename) do
+    %Plug.Upload{
+      upload
+      | filename: Path.basename(filename)
+    }
+  end
+
+  defp sanitize_upload_file(upload), do: upload
+
   @spec get_actor_url(any()) :: binary() | nil
   defp get_actor_url(url) when is_binary(url), do: url
   defp get_actor_url(%{"href" => href}) when is_binary(href), do: href
index 17c52fc912354a460665445a8860533c05cf8acc..e95e4490aa57da984517bcf744a1f8d2ef3d5e1e 100644 (file)
@@ -1303,6 +1303,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
       %{test_file: test_file}
     end
 
+    test "strips / from filename", %{test_file: file} do
+      file = %Plug.Upload{file | filename: "../../../../../nested/bad.jpg"}
+      {:ok, %Object{} = object} = ActivityPub.upload(file)
+      [%{"href" => href}] = object.data["url"]
+      assert Regex.match?(~r"/bad.jpg$", href)
+      refute Regex.match?(~r"/nested/", href)
+    end
+
     test "sets a description if given", %{test_file: file} do
       {:ok, %Object{} = object} = ActivityPub.upload(file, description: "a cool file")
       assert object.data["name"] == "a cool file"
index 50b9febead639757f117d1c925f6169beb8667c4..7ff8cff6bd0b9e67400986c5a3cc1fa5449745f7 100644 (file)
@@ -124,6 +124,23 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
 
       assert :ok == File.rm(Path.absname("test/tmp/large_binary.data"))
     end
+
+    test "Do not allow nested filename", %{conn: conn, image: image} do
+      image = %Plug.Upload{
+        image
+        | filename: "../../../../../nested/file.jpg"
+      }
+
+      desc = "Description of the image"
+
+      media =
+        conn
+        |> put_req_header("content-type", "multipart/form-data")
+        |> post("/api/v1/media", %{"file" => image, "description" => desc})
+        |> json_response_and_validate_schema(:ok)
+
+      refute Regex.match?(~r"/nested/", media["url"])
+    end
   end
 
   describe "Update media description" do
index e9b8825bfb7801f7c5507175ecb2fb9b82dbbf31..4aec31eacd07088edde803686b2ea9c86c7c3a8a 100644 (file)
@@ -396,6 +396,34 @@ defmodule Pleroma.Web.MastodonAPI.UpdateCredentialsTest do
       assert :ok == File.rm(Path.absname("test/tmp/large_binary.data"))
     end
 
+    test "Strip / from upload files", %{user: user, conn: conn} do
+      new_image = %Plug.Upload{
+        content_type: "image/jpeg",
+        path: Path.absname("test/fixtures/image.jpg"),
+        filename: "../../../../nested/an_image.jpg"
+      }
+
+      assert user.avatar == %{}
+
+      res =
+        patch(conn, "/api/v1/accounts/update_credentials", %{
+          "avatar" => new_image,
+          "header" => new_image,
+          "pleroma_background_image" => new_image
+        })
+
+      assert user_response = json_response_and_validate_schema(res, 200)
+      assert user_response["avatar"]
+      assert user_response["header"]
+      assert user_response["pleroma"]["background_image"]
+      refute Regex.match?(~r"/nested/", user_response["avatar"])
+      refute Regex.match?(~r"/nested/", user_response["header"])
+      refute Regex.match?(~r"/nested/", user_response["pleroma"]["background_image"])
+
+      user = User.get_by_id(user.id)
+      refute user.avatar == %{}
+    end
+
     test "requires 'write:accounts' permission" do
       token1 = insert(:oauth_token, scopes: ["read"])
       token2 = insert(:oauth_token, scopes: ["write", "follow"])