Merge branch 'improve_anti_followbot_policy' into 'develop'

Also use actor_type to determine if an account is a bot in antiFollowbotPolicy

Closes #2561

See merge request pleroma/pleroma!3498
This commit is contained in:
Haelwenn 2022-05-08 18:10:40 +00:00
commit 4605efe272
4 changed files with 65 additions and 15 deletions

View File

@ -97,6 +97,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Improved Twittercard and OpenGraph meta tag generation including thumbnails and image dimension metadata when available. - Improved Twittercard and OpenGraph meta tag generation including thumbnails and image dimension metadata when available.
- AdminAPI: sort users so the newest are at the top. - AdminAPI: sort users so the newest are at the top.
- ActivityPub Client-to-Server(C2S): Limitation on the type of Activity/Object are lifted as they are now passed through ObjectValidators - ActivityPub Client-to-Server(C2S): Limitation on the type of Activity/Object are lifted as they are now passed through ObjectValidators
- MRF (`AntiFollowbotPolicy`): Bot accounts are now also considered followbots. Users can still allow bots to follow them by first following the bot.
### Added ### Added

View File

@ -125,6 +125,7 @@ To add configuration to your config file, you can copy it from the base config.
* `Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy`: Sets a default expiration on all posts made by users of the local instance. Requires `Pleroma.Workers.PurgeExpiredActivity` to be enabled for processing the scheduled delections. * `Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy`: Sets a default expiration on all posts made by users of the local instance. Requires `Pleroma.Workers.PurgeExpiredActivity` to be enabled for processing the scheduled delections.
* `Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy`: Makes all bot posts to disappear from public timelines. * `Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy`: Makes all bot posts to disappear from public timelines.
* `Pleroma.Web.ActivityPub.MRF.FollowBotPolicy`: Automatically follows newly discovered users from the specified bot account. Local accounts, locked accounts, and users with "#nobot" in their bio are respected and excluded from being followed. * `Pleroma.Web.ActivityPub.MRF.FollowBotPolicy`: Automatically follows newly discovered users from the specified bot account. Local accounts, locked accounts, and users with "#nobot" in their bio are respected and excluded from being followed.
* `Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy`: Drops follow requests from followbots. Users can still allow bots to follow them by first following the bot.
* `Pleroma.Web.ActivityPub.MRF.KeywordPolicy`: Rejects or removes from the federated timeline or replaces keywords. (See [`:mrf_keyword`](#mrf_keyword)). * `Pleroma.Web.ActivityPub.MRF.KeywordPolicy`: Rejects or removes from the federated timeline or replaces keywords. (See [`:mrf_keyword`](#mrf_keyword)).
* `Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent`: Forces every mentioned user to be reflected in the post content. * `Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent`: Forces every mentioned user to be reflected in the post content.
* `transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo). * `transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo).

View File

@ -24,7 +24,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy do
defp score_displayname("fedibot"), do: 1.0 defp score_displayname("fedibot"), do: 1.0
defp score_displayname(_), do: 0.0 defp score_displayname(_), do: 0.0
defp determine_if_followbot(%User{nickname: nickname, name: displayname}) do defp determine_if_followbot(%User{nickname: nickname, name: displayname, actor_type: actor_type}) do
# nickname will be a binary string except when following a relay # nickname will be a binary string except when following a relay
nick_score = nick_score =
if is_binary(nickname) do if is_binary(nickname) do
@ -45,19 +45,32 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy do
0.0 0.0
end end
nick_score + name_score # actor_type "Service" is a Bot account
actor_type_score =
if actor_type == "Service" do
1.0
else
0.0
end
nick_score + name_score + actor_type_score
end end
defp determine_if_followbot(_), do: 0.0 defp determine_if_followbot(_), do: 0.0
defp bot_allowed?(%{"object" => target}, bot_actor) do
%User{} = user = normalize_by_ap_id(target)
User.following?(user, bot_actor)
end
@impl true @impl true
def filter(%{"type" => "Follow", "actor" => actor_id} = message) do def filter(%{"type" => "Follow", "actor" => actor_id} = message) do
%User{} = actor = normalize_by_ap_id(actor_id) %User{} = actor = normalize_by_ap_id(actor_id)
score = determine_if_followbot(actor) score = determine_if_followbot(actor)
# TODO: scan biography data for keywords and score it somehow. if score < 0.8 || bot_allowed?(message, actor) do
if score < 0.8 do
{:ok, message} {:ok, message}
else else
{:reject, "[AntiFollowbotPolicy] Scored #{actor_id} as #{score}"} {:reject, "[AntiFollowbotPolicy] Scored #{actor_id} as #{score}"}

View File

@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do
use Pleroma.DataCase, async: true use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory
alias Pleroma.User
alias Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy alias Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy
describe "blocking based on attributes" do describe "blocking based on attributes" do
@ -38,21 +39,55 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do
assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message) assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)
end end
test "matches followbots by actor_type" do
actor = insert(:user, %{actor_type: "Service"})
target = insert(:user)
message = %{
"@context" => "https://www.w3.org/ns/activitystreams",
"type" => "Follow",
"actor" => actor.ap_id,
"object" => target.ap_id,
"id" => "https://example.com/activities/1234"
}
assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)
end
end end
test "it allows non-followbots" do describe "it allows" do
actor = insert(:user) test "non-followbots" do
target = insert(:user) actor = insert(:user)
target = insert(:user)
message = %{ message = %{
"@context" => "https://www.w3.org/ns/activitystreams", "@context" => "https://www.w3.org/ns/activitystreams",
"type" => "Follow", "type" => "Follow",
"actor" => actor.ap_id, "actor" => actor.ap_id,
"object" => target.ap_id, "object" => target.ap_id,
"id" => "https://example.com/activities/1234" "id" => "https://example.com/activities/1234"
} }
{:ok, _} = AntiFollowbotPolicy.filter(message) {:ok, _} = AntiFollowbotPolicy.filter(message)
end
test "bots if the target follows the bots" do
actor = insert(:user, %{actor_type: "Service"})
target = insert(:user)
User.follow(target, actor)
message = %{
"@context" => "https://www.w3.org/ns/activitystreams",
"type" => "Follow",
"actor" => actor.ap_id,
"object" => target.ap_id,
"id" => "https://example.com/activities/1234"
}
{:ok, _} = AntiFollowbotPolicy.filter(message)
end
end end
test "it gracefully handles nil display names" do test "it gracefully handles nil display names" do