Sanitize filenames when uploading
This commit is contained in:
parent
5d34fe1868
commit
e4925f813a
|
@ -1453,13 +1453,22 @@ def fetch_activities_bounded(
|
||||||
|
|
||||||
@spec upload(Upload.source(), keyword()) :: {:ok, Object.t()} | {:error, any()}
|
@spec upload(Upload.source(), keyword()) :: {:ok, Object.t()} | {:error, any()}
|
||||||
def upload(file, opts \\ []) do
|
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])
|
obj_data = Maps.put_if_present(data, "actor", opts[:actor])
|
||||||
|
|
||||||
Repo.insert(%Object{data: obj_data})
|
Repo.insert(%Object{data: obj_data})
|
||||||
end
|
end
|
||||||
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
|
@spec get_actor_url(any()) :: binary() | nil
|
||||||
defp get_actor_url(url) when is_binary(url), do: url
|
defp get_actor_url(url) when is_binary(url), do: url
|
||||||
defp get_actor_url(%{"href" => href}) when is_binary(href), do: href
|
defp get_actor_url(%{"href" => href}) when is_binary(href), do: href
|
||||||
|
|
|
@ -1342,6 +1342,14 @@ test "returns reblogs for users for whom reblogs have not been muted" do
|
||||||
%{test_file: test_file}
|
%{test_file: test_file}
|
||||||
end
|
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
|
test "sets a description if given", %{test_file: file} do
|
||||||
{:ok, %Object{} = object} = ActivityPub.upload(file, description: "a cool file")
|
{:ok, %Object{} = object} = ActivityPub.upload(file, description: "a cool file")
|
||||||
assert object.data["name"] == "a cool file"
|
assert object.data["name"] == "a cool file"
|
||||||
|
|
|
@ -122,6 +122,23 @@ test "/api/v2/media, upload_limit", %{conn: conn, user: user} do
|
||||||
|
|
||||||
assert :ok == File.rm(Path.absname("test/tmp/large_binary.data"))
|
assert :ok == File.rm(Path.absname("test/tmp/large_binary.data"))
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
describe "Update media description" do
|
describe "Update media description" do
|
||||||
|
|
|
@ -383,6 +383,34 @@ test "updates the user's background, upload_limit, returns a HTTP 413", %{
|
||||||
assert :ok == File.rm(Path.absname("test/tmp/large_binary.data"))
|
assert :ok == File.rm(Path.absname("test/tmp/large_binary.data"))
|
||||||
end
|
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
|
test "requires 'write:accounts' permission" do
|
||||||
token1 = insert(:oauth_token, scopes: ["read"])
|
token1 = insert(:oauth_token, scopes: ["read"])
|
||||||
token2 = insert(:oauth_token, scopes: ["write", "follow"])
|
token2 = insert(:oauth_token, scopes: ["write", "follow"])
|
||||||
|
|
Loading…
Reference in New Issue