From c81b1261dc930dbec5d6e9f6b8f569db578a2762 Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Tue, 27 Oct 2026 22:02:31 +0400 Subject: [PATCH] fix(federation): treat empty actor fields as missing An empty inbox, collection or key id was rejected as being on another host. Treat empty strings like null and only check fields with a value. --- .../activity_pub/object_validators/user_validator.ex | 5 +++-- .../object_validators/user_validator_test.exs | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/web/activity_pub/object_validators/user_validator.ex b/lib/pleroma/web/activity_pub/object_validators/user_validator.ex index 183be4940..a368ccc16 100644 --- a/lib/pleroma/web/activity_pub/object_validators/user_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/user_validator.ex @@ -10,7 +10,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UserValidator do addressing and visibility checks, and map signature key ids back to the actor. If an actor could point any of these at another host, it could redirect our signed deliveries or claim another actor's - collections. Optional fields are only checked when present. + collections. Optional fields are only checked when present; null and + empty strings count as missing. Based on Akkoma's UserValidator. """ @@ -38,7 +39,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UserValidator do def validate(_data, _meta), do: {:error, "Actor has no id"} - defp same_origin?(_id, nil), do: true + defp same_origin?(_id, value) when value in [nil, ""], do: true defp same_origin?(id, %{"id" => value}), do: same_origin?(id, value) defp same_origin?(id, value), do: Containment.same_origin(id, value) == :ok diff --git a/test/pleroma/web/activity_pub/object_validators/user_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/user_validator_test.exs index 91b33b9e2..fbc89462e 100644 --- a/test/pleroma/web/activity_pub/object_validators/user_validator_test.exs +++ b/test/pleroma/web/activity_pub/object_validators/user_validator_test.exs @@ -32,6 +32,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UserValidatorTest do end end + test "treats empty and null fields as missing" do + data = + actor() + |> Map.merge(%{"inbox" => "", "followers" => nil, "following" => "", "featured" => ""}) + |> put_in(["endpoints", "sharedInbox"], "") + |> put_in(["publicKey", "id"], "") + + assert {:ok, _, _} = UserValidator.validate(data, []) + end + for field <- ["inbox", "followers", "following", "featured"] do test "rejects an actor whose #{field} is on another host" do data = Map.put(actor(), unquote(field), "https://victim.example/users/lain/x")