fix(containment): return nil for actor shapes without an id

Containment.get_actor raised on remote shapes it did not know, such as
an attributedTo object without an id. This crashed object fetches and
poll refetches. Return nil, so containment rejects the object.
This commit is contained in:
Lain Soykaf 2026-10-27 22:03:13 +04:00
commit 90e330e5b3
No known key found for this signature in database
4 changed files with 59 additions and 0 deletions

View file

@ -128,6 +128,24 @@ defmodule Pleroma.Object.ContainmentTest do
end
end
describe "get_actor/1" do
test "returns nil for actor shapes without an id" do
for actor <- [%{"type" => "Person"}, %{"id" => 1}, 1, true] do
assert nil == Containment.get_actor(%{"actor" => actor})
assert nil == Containment.get_actor(%{"actor" => nil, "attributedTo" => actor})
end
assert nil == Containment.get_actor(%{})
end
test "contain_origin/2 rejects actor shapes without an id" do
assert :error ==
Containment.contain_origin("https://a.test/o/1", %{
"attributedTo" => %{"type" => "Person"}
})
end
end
describe "contain_id_to_fetch/2" do
test "matches the exact id" do
assert :ok =

View file

@ -488,6 +488,24 @@ defmodule Pleroma.Object.FetcherTest do
assert Object.get_by_ap_id("https://mastodon.social/1").data["content"] == "test 1"
end
test "it rejects a refetched object whose author has no id", %{object1: object1} do
{:ok, o} = Object.create(object1)
mock(fn %{method: :get, url: "https://mastodon.social/1"} ->
%Tesla.Env{
status: 200,
headers: [{"content-type", "application/activity+json"}],
body:
object1
|> Map.delete("actor")
|> Map.put("attributedTo", %{"type" => "Person"})
|> Jason.encode!()
}
end)
assert {:error, _} = Fetcher.refetch_object(o)
end
test "it rejects a refetched object whose id changed", %{object1: object1} do
{:ok, o} = Object.create(object1)
@ -909,6 +927,25 @@ defmodule Pleroma.Object.FetcherTest do
)
end
test "it rejects objects whose author has no id" do
mock(fn %{method: :get, url: "https://host.test/objects/anon" = url} ->
%Tesla.Env{
status: 200,
headers: [{"content-type", "application/activity+json"}],
body:
Jason.encode!(%{
"id" => url,
"type" => "Note",
"content" => "anon",
"attributedTo" => %{"type" => "Person", "name" => "nobody"}
})
}
end)
assert {:containment, :error} =
Fetcher.fetch_object_from_id("https://host.test/objects/anon")
end
test "it rejects documents without an id" do
assert {:error, _} =
Fetcher.fetch_and_contain_remote_object_from_id("https://host.test/objects/no-id")