logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://anongit.hacktivis.me/git/pleroma.git/
commit: 51c1d6fb2dd91a1a1ac11fed0f0a4211719e30b8
parent b0c2ec5fb9ca1908dddbc66260861d4743b991b7
Author: Lain Soykaf <lain@lain.com>
Date:   Tue, 11 Mar 2025 16:37:17 +0400

Containment: Never fetch locally

Diffstat:

Achangelog.d/local-fetch-prevention.security2++
Mlib/pleroma/object/containment.ex13+++++++++++++
Mlib/pleroma/object/fetcher.ex4++++
Mtest/pleroma/object/fetcher_test.exs7+++++++
4 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/changelog.d/local-fetch-prevention.security b/changelog.d/local-fetch-prevention.security @@ -0,0 +1 @@ +Security: Block attempts to fetch activities from the local instance to prevent spoofing. +\ No newline at end of file diff --git a/lib/pleroma/object/containment.ex b/lib/pleroma/object/containment.ex @@ -48,6 +48,19 @@ defmodule Pleroma.Object.Containment do 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 """ Checks that an imported AP object's actor matches the host it came from. """ def contain_origin(_id, %{"actor" => nil}), do: :error diff --git a/lib/pleroma/object/fetcher.ex b/lib/pleroma/object/fetcher.ex @@ -148,6 +148,7 @@ defmodule Pleroma.Object.Fetcher do with {:scheme, true} <- {:scheme, String.starts_with?(id, "http")}, {_, true} <- {:mrf, MRF.id_filter(id)}, + {_, :ok} <- {:local_fetch, Containment.contain_local_fetch(id)}, {:ok, body} <- get_object(id), {:ok, data} <- safe_json_decode(body), :ok <- Containment.contain_origin_from_id(id, data) do @@ -160,6 +161,9 @@ defmodule Pleroma.Object.Fetcher do {:scheme, _} -> {:error, "Unsupported URI scheme"} + {:local_fetch, _} -> + {:error, "Trying to fetch local resource"} + {:error, e} -> {:error, e} diff --git a/test/pleroma/object/fetcher_test.exs b/test/pleroma/object/fetcher_test.exs @@ -166,6 +166,13 @@ defmodule Pleroma.Object.FetcherTest do ) 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 # Setup a mock for an object with invalid content-type mock(fn