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 05fe4bc066
commit e1e5803a28
34 changed files with 135 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,8 @@
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

@@ -55,6 +55,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
@@ -71,6 +72,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
@@ -87,6 +89,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
@@ -103,6 +106,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

@@ -34,6 +34,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] }
@@ -111,6 +112,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
@@ -148,6 +150,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
@@ -206,6 +209,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
@@ -259,6 +263,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
@@ -294,6 +299,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
@@ -339,6 +345,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
@@ -373,6 +380,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
@@ -408,6 +416,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

@@ -19,6 +19,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
@@ -94,6 +95,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
@@ -131,6 +133,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) { {} }
@@ -182,6 +185,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
@@ -256,6 +260,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

@@ -19,6 +19,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
@@ -77,6 +78,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
@@ -108,6 +110,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
@@ -168,6 +171,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

@@ -19,6 +19,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
@@ -93,6 +94,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
@@ -135,6 +137,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
@@ -243,6 +246,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
@@ -285,6 +289,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

@@ -20,6 +20,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
@@ -95,6 +96,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
@@ -128,6 +130,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
@@ -187,6 +190,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

@@ -19,6 +19,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
@@ -87,6 +88,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
@@ -123,6 +125,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

@@ -18,6 +18,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
@@ -125,6 +126,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
@@ -192,6 +194,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 }
@@ -212,6 +215,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 }
@@ -232,6 +236,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 }
@@ -252,6 +257,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

@@ -19,6 +19,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
@@ -76,6 +77,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
@@ -113,6 +115,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

@@ -32,6 +32,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 }
@@ -91,6 +92,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

@@ -28,6 +28,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)
@@ -43,6 +44,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

@@ -28,6 +28,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)
@@ -43,6 +44,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

@@ -28,6 +28,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)
@@ -43,6 +44,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

@@ -21,3 +21,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