diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index f37bcab3e752493f090c671ef2955ed3ae2159c3..c86f9a7a69c8761183856634bc739205b7529b34 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -883,6 +883,23 @@ def prepare_outgoing(%{"type" => "Announce", "actor" => ap_id, "object" => objec
     {:ok, data}
   end
 
+  # Mastodon Undo requires the object to be inlined.
+  def prepare_outgoing(%{"type" => "Undo"} = data) do
+    with activity <- Activity.normalize(data["object"]) do
+      object =
+        activity.data
+        |> strip_internal_fields
+
+      data =
+        data
+        |> Map.put("object", object)
+        |> strip_internal_fields
+        |> Map.merge(Utils.make_json_ld_header())
+
+      {:ok, data}
+    end
+  end
+
   # Mastodon Accept/Reject requires a non-normalized object containing the actor URIs,
   # because of course it does.
   def prepare_outgoing(%{"type" => "Accept"} = data) do
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index 248b410c641cebb290746f5279d932922102a3a3..d47c99704eb4ec49deaf564542cee1eabe853659 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -925,6 +925,20 @@ test "it inlines private announced objects" do
       assert modified["object"]["actor"] == modified["object"]["attributedTo"]
     end
 
+    test "it inlines blocks in undo objects" do
+      blocker = insert(:user)
+      blocked = insert(:user)
+
+      {:ok, block_activity} = CommonAPI.block(blocker, blocked)
+      {:ok, activity} = CommonAPI.unblock(blocker, blocked)
+
+      assert activity.data["type"] == "Undo"
+
+      {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
+
+      assert modified["object"]["type"] == "Block"
+    end
+
     test "it turns mentions into tags" do
       user = insert(:user)
       other_user = insert(:user)