From 28a2e3650dbdfff61ea5b72f34a2625691196dfc Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Sun, 20 Jul 2025 21:32:57 +0400 Subject: [PATCH 1/3] AdminAPI: Add (failing) test for admin self-revocation --- .../controllers/admin_api_controller_test.exs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs b/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs index 6614d1409..fc578d828 100644 --- a/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs @@ -321,6 +321,36 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do assert ModerationLog.get_log_entry_message(log_entry) == "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{user_two.nickname}" end + + test "/:right DELETE, admin cannot revoke their own admin status (single)", %{ + admin: admin, + conn: conn + } do + conn = + conn + |> put_req_header("accept", "application/json") + |> delete("/api/pleroma/admin/users/#{admin.nickname}/permission_group/admin") + + assert json_response(conn, 403) == %{"error" => "You can't revoke your own admin status."} + end + + test "/:right DELETE, admin cannot revoke their own admin status (multiple)", %{ + admin: admin, + conn: conn + } do + user = insert(:user, is_admin: true) + + conn = + conn + |> put_req_header("accept", "application/json") + |> delete("/api/pleroma/admin/users/permission_group/admin", %{ + nicknames: [admin.nickname, user.nickname] + }) + + assert json_response(conn, 403) == %{ + "error" => "You can't revoke your own admin/moderator status." + } + end end describe "/api/pleroma/admin/users/:nickname/password_reset" do From c38ce20a5d666e861b29fcce07ea80865ec7315d Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Sun, 20 Jul 2025 21:33:39 +0400 Subject: [PATCH 2/3] AdminApiController: Reorder functions to fix admin revocation --- .../web/admin_api/controllers/admin_api_controller.ex | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex index b35f5cdcd..ea852748e 100644 --- a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex @@ -240,6 +240,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do render_error(conn, :not_found, "No such permission_group") end + def right_delete(%{assigns: %{user: %{nickname: nickname}}} = conn, %{"nickname" => nickname}) do + render_error(conn, :forbidden, "You can't revoke your own admin status.") + end + def right_delete( %{assigns: %{user: admin}} = conn, %{ @@ -265,10 +269,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do json(conn, fields) end - def right_delete(%{assigns: %{user: %{nickname: nickname}}} = conn, %{"nickname" => nickname}) do - render_error(conn, :forbidden, "You can't revoke your own admin status.") - end - @doc "Get a password reset token (base64 string) for given nickname" def get_password_reset(conn, %{"nickname" => nickname}) do (%User{local: true} = user) = User.get_cached_by_nickname(nickname) From 606d64ceb6b5d38f40e301f710ebe8a1ba1acc85 Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Sun, 20 Jul 2025 21:37:41 +0400 Subject: [PATCH 3/3] Add changelog entry for admin self-revocation fix --- changelog.d/admin-self-revocation.security | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/admin-self-revocation.security diff --git a/changelog.d/admin-self-revocation.security b/changelog.d/admin-self-revocation.security new file mode 100644 index 000000000..a311ca1ed --- /dev/null +++ b/changelog.d/admin-self-revocation.security @@ -0,0 +1 @@ +Admin API: Fixed self-revocation vulnerability where admins could accidentally revoke their own admin status via the single-user permission endpoint \ No newline at end of file