## [Unreleased]
### Added
- MRF: Support for priming the mediaproxy cache (`Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy`)
+- Federation: Support for restricting max. reply-to depth on fetching
## [1.0.0] - 2019-06-29
### Security
},
registrations_open: true,
federating: true,
+ federation_incoming_replies_max_depth: 100,
federation_reachability_timeout_days: 7,
federation_publisher_modules: [
Pleroma.Web.ActivityPub.Publisher,
* `invites_enabled`: Enable user invitations for admins (depends on `registrations_open: false`).
* `account_activation_required`: Require users to confirm their emails before signing in.
* `federating`: Enable federation with other instances
+* `federation_incoming_replies_max_depth`: Max. depth of reply-to activities fetching on incoming federation (to prevent memory leakage on extremely nested incoming threads). If set to `nil`, threads of any depth will be fetched.
* `federation_reachability_timeout_days`: Timeout (in days) of each external federation target being unreachable prior to pausing federating to it.
* `allow_relay`: Enable Pleroma’s Relay, which makes it possible to follow a whole instance
* `rewrite_policy`: Message Rewrite Policy, either one or a list. Here are the ones available by default:
object = Map.put(object, "inReplyToAtomUri", in_reply_to_id)
- if (options[:depth] || 1) <= Federator.max_replies_depth() do
+ if Federator.allowed_incoming_reply_depth?(options[:depth]) do
case get_obj_helper(in_reply_to_id, options) do
{:ok, replied_object} ->
with %Activity{} = _activity <-
def fix_type(%{"inReplyTo" => reply_id} = object, options) when is_binary(reply_id) do
reply =
- if (options[:depth] || 1) <= Federator.max_replies_depth() do
+ if Federator.allowed_incoming_reply_depth?(options[:depth]) do
Object.normalize(reply_id, true)
- else
- nil
end
if reply && (reply.data["type"] == "Question" and object["name"]) do
refresh_subscriptions()
end
- @max_replies_depth 100
-
@doc "Addresses [memory leaks on recursive replies fetching](https://git.pleroma.social/pleroma/pleroma/issues/161)"
# credo:disable-for-previous-line Credo.Check.Readability.MaxLineLength
- def max_replies_depth, do: @max_replies_depth
+ def allowed_incoming_reply_depth?(depth) do
+ max_replies_depth = Pleroma.Config.get([:instance, :federation_incoming_replies_max_depth])
+
+ if max_replies_depth do
+ (depth || 1) <= max_replies_depth
+ else
+ true
+ end
+ end
# Client API
activity
else
_e ->
- with true <- (options[:depth] || 1) <= Federator.max_replies_depth(),
+ with true <- Federator.allowed_incoming_reply_depth?(options[:depth]),
in_reply_to_href when not is_nil(in_reply_to_href) <-
XML.string_from_xpath("//thr:in-reply-to[1]/@href", entry),
{:ok, [activity | _]} <- OStatus.fetch_activity_from_url(in_reply_to_href, options) do
data = Map.put(data, "object", object)
with_mock Pleroma.Web.Federator,
- max_replies_depth: fn -> 0 end do
+ allowed_incoming_reply_depth?: fn _ -> false end do
{:ok, returned_activity} = Transmogrifier.handle_incoming(data)
returned_object = Object.normalize(returned_activity.data["object"], false)
incoming = File.read!("test/fixtures/incoming_note_activity_answer.xml")
with_mock Pleroma.Web.Federator,
- max_replies_depth: fn -> 0 end do
+ allowed_incoming_reply_depth?: fn _ -> false end do
{:ok, [activity]} = OStatus.handle_incoming(incoming)
object = Object.normalize(activity.data["object"], false)