Merge tag 'v4.2.13'

This commit is contained in:
Mike Barnes 2024-10-02 10:18:05 +10:00
commit 01436cf161
15 changed files with 68 additions and 38 deletions

View file

@ -4,3 +4,7 @@ ignore:
# We have rate-limits on authentication endpoints in place (including second # We have rate-limits on authentication endpoints in place (including second
# factor verification) since Mastodon v3.2.0 # factor verification) since Mastodon v3.2.0
- CVE-2024-0227 - CVE-2024-0227
# devise-two-factor advisory about generated secrets being weaker than expected
# We call `generate_otp_secret` ourselves with a requested length of 32 characters,
# which exceeds the recommended remediation of 26 characters, so we're safe
- CVE-2024-8796

View file

@ -2,6 +2,27 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [4.2.13] - 2024-09-30
### Security
- Fix ReDoS vulnerability on some Ruby versions ([GHSA-jpxp-r43f-rhvx](https://github.com/mastodon/mastodon/security/advisories/GHSA-jpxp-r43f-rhvx))
- Update dependencies
### Added
- Add “A Mastodon update is available.” message on admin dashboard for non-bugfix updates (#32106 by @ClearlyClaire)
### Changed
- Change Mastodon to issue correct HTTP signatures by default (#31994 by @ClearlyClaire)
### Fixed
- Fix replies collection being cached improperly
- Fix security context sometimes not being added in LD-Signed activities (#31871 by @ClearlyClaire)
- Fix error when encountering reblog of deleted post in feed rebuild (#32001 by @ClearlyClaire)
## [4.2.12] - 2024-08-19 ## [4.2.12] - 2024-08-19
### Fixed ### Fixed

View file

@ -201,7 +201,7 @@ GEM
climate_control (0.2.0) climate_control (0.2.0)
cocoon (1.2.15) cocoon (1.2.15)
color_diff (0.1) color_diff (0.1)
concurrent-ruby (1.2.3) concurrent-ruby (1.3.4)
connection_pool (2.4.1) connection_pool (2.4.1)
cose (1.3.0) cose (1.3.0)
cbor (~> 0.5.9) cbor (~> 0.5.9)
@ -256,7 +256,7 @@ GEM
multi_json multi_json
encryptor (3.0.0) encryptor (3.0.0)
erubi (1.12.0) erubi (1.12.0)
et-orbi (1.2.7) et-orbi (1.2.11)
tzinfo tzinfo
excon (0.100.0) excon (0.100.0)
fabrication (2.30.0) fabrication (2.30.0)
@ -306,8 +306,8 @@ GEM
fog-json (>= 1.0) fog-json (>= 1.0)
ipaddress (>= 0.8) ipaddress (>= 0.8)
formatador (0.3.0) formatador (0.3.0)
fugit (1.8.1) fugit (1.11.1)
et-orbi (~> 1, >= 1.2.7) et-orbi (~> 1, >= 1.2.11)
raabro (~> 1.4) raabro (~> 1.4)
fuubar (2.5.1) fuubar (2.5.1)
rspec-core (~> 3.0) rspec-core (~> 3.0)
@ -469,7 +469,7 @@ GEM
net-protocol net-protocol
net-ssh (7.1.0) net-ssh (7.1.0)
nio4r (2.7.3) nio4r (2.7.3)
nokogiri (1.16.6) nokogiri (1.16.7)
mini_portile2 (~> 2.8.2) mini_portile2 (~> 2.8.2)
racc (~> 1.4) racc (~> 1.4)
nsa (0.3.0) nsa (0.3.0)
@ -478,16 +478,16 @@ GEM
sidekiq (>= 3.5) sidekiq (>= 3.5)
statsd-ruby (~> 1.4, >= 1.4.0) statsd-ruby (~> 1.4, >= 1.4.0)
oj (3.16.1) oj (3.16.1)
omniauth (2.1.1) omniauth (2.1.2)
hashie (>= 3.4.6) hashie (>= 3.4.6)
rack (>= 2.2.3) rack (>= 2.2.3)
rack-protection rack-protection
omniauth-rails_csrf_protection (1.0.1) omniauth-rails_csrf_protection (1.0.1)
actionpack (>= 4.2) actionpack (>= 4.2)
omniauth (~> 2.0) omniauth (~> 2.0)
omniauth-saml (2.1.0) omniauth-saml (2.1.2)
omniauth (~> 2.0) omniauth (~> 2.1)
ruby-saml (~> 1.12) ruby-saml (~> 1.17)
omniauth_openid_connect (0.6.1) omniauth_openid_connect (0.6.1)
omniauth (>= 1.9, < 3) omniauth (>= 1.9, < 3)
openid_connect (~> 1.1) openid_connect (~> 1.1)
@ -527,12 +527,12 @@ GEM
premailer (~> 1.7, >= 1.7.9) premailer (~> 1.7, >= 1.7.9)
private_address_check (0.5.0) private_address_check (0.5.0)
public_suffix (5.0.3) public_suffix (5.0.3)
puma (6.4.2) puma (6.4.3)
nio4r (~> 2.0) nio4r (~> 2.0)
pundit (2.3.0) pundit (2.3.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
raabro (1.4.0) raabro (1.4.0)
racc (1.7.3) racc (1.8.1)
rack (2.2.9) rack (2.2.9)
rack-attack (6.7.0) rack-attack (6.7.0)
rack (>= 1.0, < 4) rack (>= 1.0, < 4)
@ -544,7 +544,7 @@ GEM
httpclient httpclient
json-jwt (>= 1.11.0) json-jwt (>= 1.11.0)
rack (>= 2.1.0) rack (>= 2.1.0)
rack-protection (3.0.5) rack-protection (3.0.6)
rack rack
rack-proxy (0.7.6) rack-proxy (0.7.6)
rack rack
@ -604,8 +604,7 @@ GEM
responders (3.1.0) responders (3.1.0)
actionpack (>= 5.2) actionpack (>= 5.2)
railties (>= 5.2) railties (>= 5.2)
rexml (3.3.5) rexml (3.3.7)
strscan
rotp (6.3.0) rotp (6.3.0)
rouge (4.1.2) rouge (4.1.2)
rpam2 (4.0.2) rpam2 (4.0.2)
@ -667,7 +666,7 @@ GEM
rubocop-factory_bot (~> 2.22) rubocop-factory_bot (~> 2.22)
ruby-prof (1.6.3) ruby-prof (1.6.3)
ruby-progressbar (1.13.0) ruby-progressbar (1.13.0)
ruby-saml (1.15.0) ruby-saml (1.17.0)
nokogiri (>= 1.13.10) nokogiri (>= 1.13.10)
rexml rexml
ruby2_keywords (0.0.5) ruby2_keywords (0.0.5)
@ -732,7 +731,6 @@ GEM
redlock (~> 1.0) redlock (~> 1.0)
strong_migrations (0.8.0) strong_migrations (0.8.0)
activerecord (>= 5.2) activerecord (>= 5.2)
strscan (3.1.0)
swd (1.3.0) swd (1.3.0)
activesupport (>= 3) activesupport (>= 3)
attr_required (>= 0.0.5) attr_required (>= 0.0.5)

View file

@ -14,7 +14,7 @@ class ActivityPub::RepliesController < ActivityPub::BaseController
before_action :set_replies before_action :set_replies
def index def index
expires_in 0, public: public_fetch_mode? expires_in 0, public: @status.distributable? && public_fetch_mode?
render json: replies_collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json', skip_activities: true render json: replies_collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json', skip_activities: true
end end

View file

@ -4,6 +4,7 @@ class ActivityPub::LinkedDataSignature
include JsonLdHelper include JsonLdHelper
CONTEXT = 'https://w3id.org/identity/v1' CONTEXT = 'https://w3id.org/identity/v1'
SIGNATURE_CONTEXT = 'https://w3id.org/security/v1'
def initialize(json) def initialize(json)
@json = json.with_indifferent_access @json = json.with_indifferent_access
@ -46,7 +47,13 @@ class ActivityPub::LinkedDataSignature
signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest.new('SHA256'), to_be_signed)) signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest.new('SHA256'), to_be_signed))
@json.merge('signature' => options.merge('signatureValue' => signature)) # Mastodon's context is either an array or a single URL
context_with_security = Array(@json['@context'])
context_with_security << 'https://w3id.org/security/v1'
context_with_security.uniq!
context_with_security = context_with_security.first if context_with_security.size == 1
@json.merge('signature' => options.merge('signatureValue' => signature), '@context' => context_with_security)
end end
private private

View file

@ -14,14 +14,16 @@ class Admin::SystemCheck::SoftwareVersionCheck < Admin::SystemCheck::BaseCheck
def message def message
if software_updates.any?(&:urgent?) if software_updates.any?(&:urgent?)
Admin::SystemCheck::Message.new(:software_version_critical_check, nil, admin_software_updates_path, true) Admin::SystemCheck::Message.new(:software_version_critical_check, nil, admin_software_updates_path, true)
else elsif software_updates.any?(&:patch_type?)
Admin::SystemCheck::Message.new(:software_version_patch_check, nil, admin_software_updates_path) Admin::SystemCheck::Message.new(:software_version_patch_check, nil, admin_software_updates_path)
else
Admin::SystemCheck::Message.new(:software_version_check, nil, admin_software_updates_path)
end end
end end
private private
def software_updates def software_updates
@software_updates ||= SoftwareUpdate.pending_to_a.filter { |update| update.urgent? || update.patch_type? } @software_updates ||= SoftwareUpdate.pending_to_a
end end
end end

View file

@ -557,7 +557,7 @@ class FeedManager
arr = crutches[:active_mentions][s.id] || [] arr = crutches[:active_mentions][s.id] || []
arr.push(s.account_id) arr.push(s.account_id)
if s.reblog? if s.reblog? && s.reblog.present?
arr.push(s.reblog.account_id) arr.push(s.reblog.account_id)
arr.concat(crutches[:active_mentions][s.reblog_of_id] || []) arr.concat(crutches[:active_mentions][s.reblog_of_id] || [])
end end

View file

@ -77,7 +77,7 @@ class Request
@url = Addressable::URI.parse(url).normalize @url = Addressable::URI.parse(url).normalize
@http_client = options.delete(:http_client) @http_client = options.delete(:http_client)
@allow_local = options.delete(:allow_local) @allow_local = options.delete(:allow_local)
@full_path = options.delete(:with_query_string) @full_path = !options.delete(:omit_query_string)
@options = options.merge(socket_class: use_proxy? || @allow_local ? ProxySocket : Socket) @options = options.merge(socket_class: use_proxy? || @allow_local ? ProxySocket : Socket)
@options = @options.merge(timeout_class: PerOperationWithDeadline, timeout_options: TIMEOUT) @options = @options.merge(timeout_class: PerOperationWithDeadline, timeout_options: TIMEOUT)
@options = @options.merge(proxy_url) if use_proxy? @options = @options.merge(proxy_url) if use_proxy?

View file

@ -65,8 +65,8 @@ class Account < ApplicationRecord
BACKGROUND_REFRESH_INTERVAL = 1.week.freeze BACKGROUND_REFRESH_INTERVAL = 1.week.freeze
USERNAME_RE = /[a-z0-9_]+([a-z0-9_.-]+[a-z0-9_]+)?/i USERNAME_RE = /[a-z0-9_]+([.-]+[a-z0-9_]+)*/i
MENTION_RE = %r{(?<![=/[:word:]])@((#{USERNAME_RE})(?:@[[:word:].-]+[[:word:]]+)?)} MENTION_RE = %r{(?<![=/[:word:]])@((#{USERNAME_RE})(?:@[[:word:]]+([.-]+[[:word:]]+)*)?)}
URL_PREFIX_RE = %r{\Ahttp(s?)://[^/]+} URL_PREFIX_RE = %r{\Ahttp(s?)://[^/]+}
USERNAME_ONLY_RE = /\A#{USERNAME_RE}\z/i USERNAME_ONLY_RE = /\A#{USERNAME_RE}\z/i

View file

@ -49,7 +49,7 @@ class ActivityPub::FetchRepliesService < BaseService
rescue Mastodon::UnexpectedResponseError => e rescue Mastodon::UnexpectedResponseError => e
raise unless e.response && e.response.code == 401 && Addressable::URI.parse(collection_or_uri).query.present? raise unless e.response && e.response.code == 401 && Addressable::URI.parse(collection_or_uri).query.present?
fetch_resource_without_id_validation(collection_or_uri, nil, true, request_options: { with_query_string: true }) fetch_resource_without_id_validation(collection_or_uri, nil, true, request_options: { omit_query_string: false })
end end
end end

View file

@ -858,6 +858,9 @@ en:
message_html: You haven't defined any server rules. message_html: You haven't defined any server rules.
sidekiq_process_check: sidekiq_process_check:
message_html: No Sidekiq process running for the %{value} queue(s). Please review your Sidekiq configuration message_html: No Sidekiq process running for the %{value} queue(s). Please review your Sidekiq configuration
software_version_check:
action: See available updates
message_html: A Mastodon update is available.
software_version_critical_check: software_version_critical_check:
action: See available updates action: See available updates
message_html: A critical Mastodon update is available, please update as quickly as possible. message_html: A critical Mastodon update is available, please update as quickly as possible.

View file

@ -56,7 +56,7 @@ services:
web: web:
build: . build: .
image: ghcr.io/mastodon/mastodon:v4.2.12 image: ghcr.io/mastodon/mastodon:v4.2.13
restart: always restart: always
env_file: .env.production env_file: .env.production
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000" command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
@ -77,7 +77,7 @@ services:
streaming: streaming:
build: . build: .
image: ghcr.io/mastodon/mastodon:v4.2.12 image: ghcr.io/mastodon/mastodon:v4.2.13
restart: always restart: always
env_file: .env.production env_file: .env.production
command: node ./streaming command: node ./streaming
@ -95,7 +95,7 @@ services:
sidekiq: sidekiq:
build: . build: .
image: ghcr.io/mastodon/mastodon:v4.2.12 image: ghcr.io/mastodon/mastodon:v4.2.13
restart: always restart: always
env_file: .env.production env_file: .env.production
command: bundle exec sidekiq command: bundle exec sidekiq

View file

@ -13,7 +13,7 @@ module Mastodon
end end
def patch def patch
12 13
end end
def default_prerelease def default_prerelease

View file

@ -99,16 +99,11 @@ RSpec.describe ActivityPub::LinkedDataSignature do
describe '#sign!' do describe '#sign!' do
subject { described_class.new(raw_json).sign!(sender) } subject { described_class.new(raw_json).sign!(sender) }
it 'returns a hash' do it 'returns a hash with a signature, the expected context, and the signature can be verified', :aggregate_failures do
expect(subject).to be_a Hash expect(subject).to be_a Hash
end
it 'contains signature' do
expect(subject['signature']).to be_a Hash expect(subject['signature']).to be_a Hash
expect(subject['signature']['signatureValue']).to be_present expect(subject['signature']['signatureValue']).to be_present
end expect(Array(subject['@context'])).to include('https://w3id.org/security/v1')
it 'can be verified again' do
expect(described_class.new(subject).verify_actor!).to eq sender expect(described_class.new(subject).verify_actor!).to eq sender
end end
end end

View file

@ -51,8 +51,8 @@ describe Admin::SystemCheck::SoftwareVersionCheck do
Fabricate(:software_update, version: '99.99.99', type: 'major', urgent: false) Fabricate(:software_update, version: '99.99.99', type: 'major', urgent: false)
end end
it 'returns true' do it 'returns false' do
expect(check.pass?).to be true expect(check.pass?).to be false
end end
end end