Fixes GHSA-62j4-hvj7-px3f

This commit is contained in:
Juan Hernández Babón
2026-08-26 18:36:00 +02:00
committed by Claire
parent d8e613a35c
commit 63eae9292e
34 changed files with 134 additions and 0 deletions

View File

@@ -4,6 +4,7 @@ module Admin
class BaseController < ApplicationController
include Authorization
include AccountableConcern
include Admin::PermissionsConcern
layout 'admin'

View File

@@ -2,6 +2,7 @@
class Api::V1::Admin::AccountActionsController < Api::BaseController
include Authorization
include Admin::PermissionsConcern
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:accounts' }
before_action :set_account

View File

@@ -3,6 +3,7 @@
class Api::V1::Admin::AccountsController < Api::BaseController
include Authorization
include AccountableConcern
include Admin::PermissionsConcern
LIMIT = 100

View File

@@ -3,6 +3,7 @@
class Api::V1::Admin::CanonicalEmailBlocksController < Api::BaseController
include Authorization
include AccountableConcern
include Admin::PermissionsConcern
LIMIT = 100

View File

@@ -2,6 +2,7 @@
class Api::V1::Admin::DimensionsController < Api::BaseController
include Authorization
include Admin::PermissionsConcern
before_action -> { authorize_if_got_token! :'admin:read' }
before_action :set_dimensions

View File

@@ -3,6 +3,7 @@
class Api::V1::Admin::DomainAllowsController < Api::BaseController
include Authorization
include AccountableConcern
include Admin::PermissionsConcern
LIMIT = 100
MAX_LIMIT = 500

View File

@@ -3,6 +3,7 @@
class Api::V1::Admin::DomainBlocksController < Api::BaseController
include Authorization
include AccountableConcern
include Admin::PermissionsConcern
LIMIT = 100
MAX_LIMIT = 500

View File

@@ -3,6 +3,7 @@
class Api::V1::Admin::EmailDomainBlocksController < Api::BaseController
include Authorization
include AccountableConcern
include Admin::PermissionsConcern
LIMIT = 100

View File

@@ -3,6 +3,7 @@
class Api::V1::Admin::IpBlocksController < Api::BaseController
include Authorization
include AccountableConcern
include Admin::PermissionsConcern
LIMIT = 100

View File

@@ -2,6 +2,7 @@
class Api::V1::Admin::MeasuresController < Api::BaseController
include Authorization
include Admin::PermissionsConcern
before_action -> { authorize_if_got_token! :'admin:read' }
before_action :set_measures

View File

@@ -3,6 +3,7 @@
class Api::V1::Admin::ReportsController < Api::BaseController
include Authorization
include AccountableConcern
include Admin::PermissionsConcern
LIMIT = 100

View File

@@ -2,6 +2,7 @@
class Api::V1::Admin::RetentionController < Api::BaseController
include Authorization
include Admin::PermissionsConcern
before_action -> { authorize_if_got_token! :'admin:read' }
before_action :set_retention

View File

@@ -2,6 +2,7 @@
class Api::V1::Admin::TagsController < Api::BaseController
include Authorization
include Admin::PermissionsConcern
before_action -> { authorize_if_got_token! :'admin:read' }, only: [:index, :show]
before_action -> { authorize_if_got_token! :'admin:write' }, only: :update

View File

@@ -2,6 +2,7 @@
class Api::V1::Admin::Trends::Links::PreviewCardProvidersController < Api::BaseController
include Authorization
include Admin::PermissionsConcern
LIMIT = 100

View File

@@ -2,6 +2,7 @@
class Api::V1::Admin::Trends::LinksController < Api::V1::Trends::LinksController
include Authorization
include Admin::PermissionsConcern
before_action -> { authorize_if_got_token! :'admin:read' }, only: :index
before_action -> { authorize_if_got_token! :'admin:write' }, except: :index

View File

@@ -2,6 +2,7 @@
class Api::V1::Admin::Trends::StatusesController < Api::V1::Trends::StatusesController
include Authorization
include Admin::PermissionsConcern
before_action -> { authorize_if_got_token! :'admin:read' }, only: :index
before_action -> { authorize_if_got_token! :'admin:write' }, except: :index

View File

@@ -2,6 +2,7 @@
class Api::V1::Admin::Trends::TagsController < Api::V1::Trends::TagsController
include Authorization
include Admin::PermissionsConcern
before_action -> { authorize_if_got_token! :'admin:read' }, only: :index
before_action -> { authorize_if_got_token! :'admin:write' }, except: :index

View File

@@ -0,0 +1,16 @@
# frozen_string_literal: true
module Admin::PermissionsConcern
extend ActiveSupport::Concern
included do
before_action :require_moderator_or_admin_permissions
end
private
def require_moderator_or_admin_permissions
# not using #authorize here, so #verify_authorized still makes sure more fine-grained rules are enforced down the line
forbidden unless Admin::BasePolicy.new(current_account, :base).access?
end
end

View File

@@ -19,6 +19,8 @@ class ApplicationPolicy
end
def role
return UserRole.nobody if current_user&.disabled?
current_user&.role || UserRole.nobody
end
end

View File

@@ -0,0 +1,37 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe ApplicationPolicy do
subject do
Class.new(described_class) do
def spec?
role.can?(:manage_users)
end
end
end
let(:admin) { Fabricate(:admin_user).account }
let(:john) { Fabricate(:account) }
let(:alice) { Fabricate(:admin_user, disabled: true).account }
permissions :spec? do
context 'when staff' do
it 'permits' do
expect(subject).to permit(admin)
end
end
context 'when not staff' do
it 'denies' do
expect(subject).to_not permit(john)
end
end
context 'when staff but disabled' do
it 'denies' do
expect(subject).to_not permit(alice)
end
end
end
end

View File

@@ -51,6 +51,7 @@ RSpec.describe 'Account actions' do
it_behaves_like 'forbidden for wrong scope', 'admin:read admin:read:accounts'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it_behaves_like 'a successful notification delivery'
it_behaves_like 'a successful logged action', :disable, :user
@@ -67,6 +68,7 @@ RSpec.describe 'Account actions' do
it_behaves_like 'forbidden for wrong scope', 'admin:read admin:read:accounts'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it_behaves_like 'a successful notification delivery'
it_behaves_like 'a successful logged action', :sensitive, :account
@@ -83,6 +85,7 @@ RSpec.describe 'Account actions' do
it_behaves_like 'forbidden for wrong scope', 'admin:read admin:read:accounts'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it_behaves_like 'a successful notification delivery'
it_behaves_like 'a successful logged action', :silence, :account
@@ -99,6 +102,7 @@ RSpec.describe 'Account actions' do
it_behaves_like 'forbidden for wrong scope', 'admin:read admin:read:accounts'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it_behaves_like 'a successful notification delivery'
it_behaves_like 'a successful logged action', :suspend, :account

View File

@@ -30,6 +30,7 @@ RSpec.describe 'Accounts' do
it_behaves_like 'forbidden for wrong scope', 'read read:accounts admin:write admin:write:accounts'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
context 'when requesting active local staff accounts' do
let(:expected_results) { [admin_account] }
@@ -107,6 +108,7 @@ RSpec.describe 'Accounts' do
it_behaves_like 'forbidden for wrong scope', 'read read:accounts admin:write admin:write:accounts'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'returns the requested account successfully', :aggregate_failures do
subject
@@ -144,6 +146,7 @@ RSpec.describe 'Accounts' do
it_behaves_like 'forbidden for wrong scope', 'write write:accounts read admin:read'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'approves the user successfully', :aggregate_failures do
subject
@@ -202,6 +205,7 @@ RSpec.describe 'Accounts' do
it_behaves_like 'forbidden for wrong scope', 'write write:accounts read admin:read'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'removes the user successfully and logs action', :aggregate_failures do
subject
@@ -255,6 +259,7 @@ RSpec.describe 'Accounts' do
it_behaves_like 'forbidden for wrong scope', 'write write:accounts read admin:read'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'enables the user successfully', :aggregate_failures do
subject
@@ -290,6 +295,7 @@ RSpec.describe 'Accounts' do
it_behaves_like 'forbidden for wrong scope', 'write write:accounts read admin:read'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'unsuspends the account successfully', :aggregate_failures do
subject
@@ -335,6 +341,7 @@ RSpec.describe 'Accounts' do
it_behaves_like 'forbidden for wrong scope', 'write write:accounts read admin:read'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'unsensitizes the account successfully', :aggregate_failures do
subject
@@ -369,6 +376,7 @@ RSpec.describe 'Accounts' do
it_behaves_like 'forbidden for wrong scope', 'write write:accounts read admin:read'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'unsilences the account successfully', :aggregate_failures do
subject
@@ -404,6 +412,7 @@ RSpec.describe 'Accounts' do
it_behaves_like 'forbidden for wrong scope', 'write write:accounts read admin:read'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'deletes the account successfully', :aggregate_failures do
allow(Admin::AccountDeletionWorker).to receive(:perform_async)

View File

@@ -15,6 +15,7 @@ RSpec.describe 'Canonical Email Blocks' do
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
context 'when there is no canonical email block' do
it 'returns an empty list' do
@@ -90,6 +91,7 @@ RSpec.describe 'Canonical Email Blocks' do
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
context 'when the requested canonical email block exists' do
it 'returns the requested canonical email block data correctly', :aggregate_failures do
@@ -127,6 +129,7 @@ RSpec.describe 'Canonical Email Blocks' do
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
context 'when the required email param is not provided' do
let(:params) { {} }
@@ -178,6 +181,7 @@ RSpec.describe 'Canonical Email Blocks' do
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
it 'returns the canonical_email_hash correctly', :aggregate_failures do
subject
@@ -252,6 +256,7 @@ RSpec.describe 'Canonical Email Blocks' do
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
it 'deletes the canonical email block', :aggregate_failures do
subject

View File

@@ -15,6 +15,7 @@ RSpec.describe 'Domain Allows' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
context 'when there is no allowed domains' do
it 'returns an empty body' do
@@ -73,6 +74,7 @@ RSpec.describe 'Domain Allows' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
it 'returns the expected allowed domain name', :aggregate_failures do
subject
@@ -104,6 +106,7 @@ RSpec.describe 'Domain Allows' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
context 'with a valid domain name' do
it 'returns the expected domain name', :aggregate_failures do
@@ -164,6 +167,7 @@ RSpec.describe 'Domain Allows' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
it 'deletes the allowed domain', :aggregate_failures do
subject

View File

@@ -15,6 +15,7 @@ RSpec.describe 'Domain Blocks' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
context 'when there are no domain blocks' do
it 'returns an empty list' do
@@ -89,6 +90,7 @@ RSpec.describe 'Domain Blocks' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
it 'returns the expected domain block content', :aggregate_failures do
subject
@@ -131,6 +133,7 @@ RSpec.describe 'Domain Blocks' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
it 'creates a domain block with the expected domain name and severity', :aggregate_failures do
subject
@@ -239,6 +242,7 @@ RSpec.describe 'Domain Blocks' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
it 'returns the updated domain block', :aggregate_failures do
subject
@@ -281,6 +285,7 @@ RSpec.describe 'Domain Blocks' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
it 'deletes the domain block', :aggregate_failures do
subject

View File

@@ -15,6 +15,7 @@ RSpec.describe 'Email Domain Blocks' do
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
context 'when there is no email domain block' do
it 'returns an empty list' do
@@ -90,6 +91,7 @@ RSpec.describe 'Email Domain Blocks' do
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
context 'when email domain block exists' do
it 'returns the correct blocked domain', :aggregate_failures do
@@ -123,6 +125,7 @@ RSpec.describe 'Email Domain Blocks' do
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
it 'returns the correct blocked email domain', :aggregate_failures do
subject
@@ -182,6 +185,7 @@ RSpec.describe 'Email Domain Blocks' do
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
it 'deletes email domain block', :aggregate_failures do
subject

View File

@@ -15,6 +15,7 @@ RSpec.describe 'IP Blocks' do
it_behaves_like 'forbidden for wrong scope', 'admin:write:ip_blocks'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
context 'when there is no ip block' do
it 'returns an empty body' do
@@ -83,6 +84,7 @@ RSpec.describe 'IP Blocks' do
it_behaves_like 'forbidden for wrong scope', 'admin:write:ip_blocks'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
it 'returns the correct ip block', :aggregate_failures do
subject
@@ -119,6 +121,7 @@ RSpec.describe 'IP Blocks' do
it_behaves_like 'forbidden for wrong scope', 'admin:read:ip_blocks'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for wrong role', 'Moderator'
it_behaves_like 'forbidden for disabled user'
it 'returns the correct ip block', :aggregate_failures do
subject

View File

@@ -14,6 +14,7 @@ RSpec.describe 'Reports' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
context 'when there are no reports' do
it 'returns an empty list' do
@@ -132,6 +133,7 @@ RSpec.describe 'Reports' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'returns the requested report content', :aggregate_failures do
subject
@@ -199,6 +201,7 @@ RSpec.describe 'Reports' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'marks report as resolved', :aggregate_failures do
expect { subject }
@@ -219,6 +222,7 @@ RSpec.describe 'Reports' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'marks report as unresolved', :aggregate_failures do
expect { subject }
@@ -239,6 +243,7 @@ RSpec.describe 'Reports' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'assigns report to the requesting user', :aggregate_failures do
expect { subject }
@@ -259,6 +264,7 @@ RSpec.describe 'Reports' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'unassigns report from assignee', :aggregate_failures do
expect { subject }

View File

@@ -17,6 +17,7 @@ RSpec.describe 'Tags' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
context 'when there are no tags' do
it 'returns an empty list' do
@@ -74,6 +75,7 @@ RSpec.describe 'Tags' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'returns http success and expected tag content' do
subject
@@ -111,6 +113,7 @@ RSpec.describe 'Tags' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong scope', 'admin:read'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'returns http success and updates tag' do
subject

View File

@@ -28,6 +28,7 @@ RSpec.describe 'Links' do
it_behaves_like 'forbidden for wrong scope', 'read write'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'returns http success' do
expect { subject }
@@ -87,6 +88,7 @@ RSpec.describe 'Links' do
it_behaves_like 'forbidden for wrong scope', 'read write'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'returns http success' do
expect { subject }

View File

@@ -25,6 +25,7 @@ RSpec.describe 'API V1 Admin Trends Links Preview Card Providers' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -40,6 +41,7 @@ RSpec.describe 'API V1 Admin Trends Links Preview Card Providers' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'returns http success' do
expect(response).to have_http_status(200)

View File

@@ -25,6 +25,7 @@ RSpec.describe 'API V1 Admin Trends Statuses' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -40,6 +41,7 @@ RSpec.describe 'API V1 Admin Trends Statuses' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'returns http success' do
expect(response).to have_http_status(200)

View File

@@ -25,6 +25,7 @@ RSpec.describe 'API V1 Admin Trends Tags' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -40,6 +41,7 @@ RSpec.describe 'API V1 Admin Trends Tags' do
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
it_behaves_like 'forbidden for wrong role', ''
it_behaves_like 'forbidden for disabled user'
it 'returns http success' do
expect(response).to have_http_status(200)

View File

@@ -22,3 +22,14 @@ RSpec.shared_examples 'forbidden for wrong role' do |wrong_role|
expect(response).to have_http_status(403)
end
end
RSpec.shared_examples 'forbidden for disabled user' do
let(:user) { Fabricate(:admin_user, disabled: true) }
it 'returns http forbidden' do
# Some examples have a subject which needs to be called to make a request
subject if request.nil?
expect(response).to have_http_status(403)
end
end