federation/in: fix activity addressing of Pleroma unlisted

While the object itself has the expected adressing for an
"unlisted" post, we always use the Create activity’s
adressing fields for permission checks.

To avoid unintended effects on legacy objects
we will continue to use the activity for access perm checks,
but fix its addressing fields based on its object data.

Ref: https://git.pleroma.social/pleroma/pleroma/-/issues/3323
This commit is contained in:
Oneric 2025-03-17 22:21:19 +01:00
parent 74182abb5b
commit cdf576b951
2 changed files with 44 additions and 1 deletions

View file

@ -118,7 +118,7 @@ defp normalise_addressing_public_list(%{} = map, [field | fields]) do
Map.put(map, field, new_fval)
else
map
Map.put(map, field, [])
end
normalise_addressing_public_list(map, fields)
@ -208,6 +208,20 @@ def fix_in_reply_to(%{"inReplyTo" => in_reply_to} = object, options)
def fix_in_reply_to(object, _options), do: object
# Pleroma sends unlisted posts without addressing public scope in the enclosing activity
# but we only use the ativity for access perm cheks, see:
# https://git.pleroma.social/pleroma/pleroma/-/issues/3323
defp fix_create_visibility(%{"type" => "Create", "object" => %{"cc" => occ}} = activity) do
acc = activity["cc"]
if Pleroma.Constants.as_public() in occ and not (Pleroma.Constants.as_public() in acc) do
Map.put(activity, "cc", [Pleroma.Constants.as_public() | acc])
else
activity
end
end
defp fix_create_visibility(activity), do: activity
def fix_quote_url(object, options \\ [])
def fix_quote_url(%{"quoteUri" => quote_url} = object, options)
@ -513,6 +527,7 @@ defp handle_incoming_normalised(
)
when objtype in ~w{Question Answer Audio Video Event Article Note Page} do
fetch_options = Keyword.put(options, :depth, (options[:depth] || 0) + 1)
data = fix_create_visibility(data)
object =
data["object"]

View file

@ -17,6 +17,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
import Mock
import Pleroma.Factory
require Pleroma.Constants
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
@ -276,6 +278,32 @@ test "it ensures that address fields become lists" do
refute is_nil(data["cc"])
end
test "it fixes Pleroma unlisted" do
# https://git.pleroma.social/pleroma/pleroma/-/issues/3323
user1 = insert(:user)
user2 = insert(:user)
data =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Jason.decode!()
|> Map.put("actor", user1.ap_id)
|> Map.put("cc", [])
|> Map.put("to", [user2.ap_id, user1.follower_address])
object =
data["object"]
|> Map.put("attributedTo", user1.ap_id)
|> Map.put("cc", [Pleroma.Constants.as_public()])
|> Map.put("to", [user2.ap_id, user1.follower_address])
|> Map.put("id", user1.ap_id <> "/activities/12345678")
data = Map.put(data, "object", object)
{:ok, %Activity{} = activity} = Transmogrifier.handle_incoming(data)
assert "unlisted" == Pleroma.Web.ActivityPub.Visibility.get_visibility(activity)
end
test "it strips internal likes" do
data =
File.read!("test/fixtures/mastodon-post-activity.json")