Containment: Never fetch locally

This commit is contained in:
Lain Soykaf 2025-03-11 16:37:17 +04:00
commit 51c1d6fb2d
4 changed files with 25 additions and 0 deletions

View file

@ -0,0 +1 @@
Security: Block attempts to fetch activities from the local instance to prevent spoofing.

View file

@ -47,6 +47,19 @@ defmodule Pleroma.Object.Containment do
defp compare_uris(%URI{host: host} = _id_uri, %URI{host: host} = _other_uri), do: :ok defp compare_uris(%URI{host: host} = _id_uri, %URI{host: host} = _other_uri), do: :ok
defp compare_uris(_id_uri, _other_uri), do: :error defp compare_uris(_id_uri, _other_uri), do: :error
@doc """
Checks whether an URL to fetch from is from the local server.
We never want to fetch from ourselves; if it's not in the database
it can't be authentic and must be a counterfeit.
"""
def contain_local_fetch(id) do
case compare_uris(URI.parse(id), Pleroma.Web.Endpoint.struct_url()) do
:ok -> :error
_ -> :ok
end
end
@doc """ @doc """
Checks that an imported AP object's actor matches the host it came from. Checks that an imported AP object's actor matches the host it came from.
""" """

View file

@ -148,6 +148,7 @@ defmodule Pleroma.Object.Fetcher do
with {:scheme, true} <- {:scheme, String.starts_with?(id, "http")}, with {:scheme, true} <- {:scheme, String.starts_with?(id, "http")},
{_, true} <- {:mrf, MRF.id_filter(id)}, {_, true} <- {:mrf, MRF.id_filter(id)},
{_, :ok} <- {:local_fetch, Containment.contain_local_fetch(id)},
{:ok, body} <- get_object(id), {:ok, body} <- get_object(id),
{:ok, data} <- safe_json_decode(body), {:ok, data} <- safe_json_decode(body),
:ok <- Containment.contain_origin_from_id(id, data) do :ok <- Containment.contain_origin_from_id(id, data) do
@ -160,6 +161,9 @@ defmodule Pleroma.Object.Fetcher do
{:scheme, _} -> {:scheme, _} ->
{:error, "Unsupported URI scheme"} {:error, "Unsupported URI scheme"}
{:local_fetch, _} ->
{:error, "Trying to fetch local resource"}
{:error, e} -> {:error, e} ->
{:error, e} {:error, e}

View file

@ -166,6 +166,13 @@ defmodule Pleroma.Object.FetcherTest do
) )
end end
test "it does not fetch from local instance" do
local_url = Pleroma.Web.Endpoint.url() <> "/objects/local_resource"
assert {:fetch, {:error, "Trying to fetch local resource"}} =
Fetcher.fetch_object_from_id(local_url)
end
test "it validates content-type headers according to ActivityPub spec" do test "it validates content-type headers according to ActivityPub spec" do
# Setup a mock for an object with invalid content-type # Setup a mock for an object with invalid content-type
mock(fn mock(fn