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.
This commit is contained in:
Lain Soykaf 2026-10-27 22:02:31 +04:00
commit c81b1261dc
No known key found for this signature in database
2 changed files with 13 additions and 2 deletions

View file

@ -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

View file

@ -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")