Merge tag 'v4.2.15'

This commit is contained in:
bgme 2025-01-16 19:47:39 +08:00
commit 18aa575996
10 changed files with 121 additions and 72 deletions

View file

@ -2,6 +2,18 @@
All notable changes to this project will be documented in this file.
## [4.2.15] - 2025-01-16
### Security
- Fix insufficient validation of account URIs ([GHSA-5wxh-3p65-r4g6](https://github.com/mastodon/mastodon/security/advisories/GHSA-5wxh-3p65-r4g6))
- Update dependencies
### Fixed
- Fix `libyaml` missing from `Dockerfile` build stage (#33591 by @vmstan)
- Fix deletion of unconfirmed users with Webauthn set (#33186 by @ClearlyClaire)
## [4.2.14] - 2024-02-03
### Added

View file

@ -28,6 +28,7 @@ RUN apt-get update && \
libgdbm-dev \
libgmp-dev \
libssl-dev \
libyaml-dev \
libyaml-0-2 \
ca-certificates \
libreadline8 \

View file

@ -28,47 +28,47 @@ GIT
GEM
remote: https://rubygems.org/
specs:
actioncable (7.0.8.6)
actionpack (= 7.0.8.6)
activesupport (= 7.0.8.6)
actioncable (7.0.8.7)
actionpack (= 7.0.8.7)
activesupport (= 7.0.8.7)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (7.0.8.6)
actionpack (= 7.0.8.6)
activejob (= 7.0.8.6)
activerecord (= 7.0.8.6)
activestorage (= 7.0.8.6)
activesupport (= 7.0.8.6)
actionmailbox (7.0.8.7)
actionpack (= 7.0.8.7)
activejob (= 7.0.8.7)
activerecord (= 7.0.8.7)
activestorage (= 7.0.8.7)
activesupport (= 7.0.8.7)
mail (>= 2.7.1)
net-imap
net-pop
net-smtp
actionmailer (7.0.8.6)
actionpack (= 7.0.8.6)
actionview (= 7.0.8.6)
activejob (= 7.0.8.6)
activesupport (= 7.0.8.6)
actionmailer (7.0.8.7)
actionpack (= 7.0.8.7)
actionview (= 7.0.8.7)
activejob (= 7.0.8.7)
activesupport (= 7.0.8.7)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.0)
actionpack (7.0.8.6)
actionview (= 7.0.8.6)
activesupport (= 7.0.8.6)
actionpack (7.0.8.7)
actionview (= 7.0.8.7)
activesupport (= 7.0.8.7)
rack (~> 2.0, >= 2.2.4)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (7.0.8.6)
actionpack (= 7.0.8.6)
activerecord (= 7.0.8.6)
activestorage (= 7.0.8.6)
activesupport (= 7.0.8.6)
actiontext (7.0.8.7)
actionpack (= 7.0.8.7)
activerecord (= 7.0.8.7)
activestorage (= 7.0.8.7)
activesupport (= 7.0.8.7)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.0.8.6)
activesupport (= 7.0.8.6)
actionview (7.0.8.7)
activesupport (= 7.0.8.7)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
@ -78,22 +78,22 @@ GEM
activemodel (>= 4.1, < 7.1)
case_transform (>= 0.2)
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
activejob (7.0.8.6)
activesupport (= 7.0.8.6)
activejob (7.0.8.7)
activesupport (= 7.0.8.7)
globalid (>= 0.3.6)
activemodel (7.0.8.6)
activesupport (= 7.0.8.6)
activerecord (7.0.8.6)
activemodel (= 7.0.8.6)
activesupport (= 7.0.8.6)
activestorage (7.0.8.6)
actionpack (= 7.0.8.6)
activejob (= 7.0.8.6)
activerecord (= 7.0.8.6)
activesupport (= 7.0.8.6)
activemodel (7.0.8.7)
activesupport (= 7.0.8.7)
activerecord (7.0.8.7)
activemodel (= 7.0.8.7)
activesupport (= 7.0.8.7)
activestorage (7.0.8.7)
actionpack (= 7.0.8.7)
activejob (= 7.0.8.7)
activerecord (= 7.0.8.7)
activesupport (= 7.0.8.7)
marcel (~> 1.0)
mini_mime (>= 1.1.0)
activesupport (7.0.8.6)
activesupport (7.0.8.7)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
@ -469,7 +469,7 @@ GEM
net-protocol
net-ssh (7.1.0)
nio4r (2.7.4)
nokogiri (1.16.7)
nokogiri (1.16.8)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
nsa (0.3.0)
@ -550,20 +550,20 @@ GEM
rack
rack-test (2.1.0)
rack (>= 1.3)
rails (7.0.8.6)
actioncable (= 7.0.8.6)
actionmailbox (= 7.0.8.6)
actionmailer (= 7.0.8.6)
actionpack (= 7.0.8.6)
actiontext (= 7.0.8.6)
actionview (= 7.0.8.6)
activejob (= 7.0.8.6)
activemodel (= 7.0.8.6)
activerecord (= 7.0.8.6)
activestorage (= 7.0.8.6)
activesupport (= 7.0.8.6)
rails (7.0.8.7)
actioncable (= 7.0.8.7)
actionmailbox (= 7.0.8.7)
actionmailer (= 7.0.8.7)
actionpack (= 7.0.8.7)
actiontext (= 7.0.8.7)
actionview (= 7.0.8.7)
activejob (= 7.0.8.7)
activemodel (= 7.0.8.7)
activerecord (= 7.0.8.7)
activestorage (= 7.0.8.7)
activesupport (= 7.0.8.7)
bundler (>= 1.15.0)
railties (= 7.0.8.6)
railties (= 7.0.8.7)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
@ -572,15 +572,15 @@ GEM
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.0)
rails-html-sanitizer (1.6.2)
loofah (~> 2.21)
nokogiri (~> 1.14)
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
rails-i18n (7.0.7)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8)
railties (7.0.8.6)
actionpack (= 7.0.8.6)
activesupport (= 7.0.8.6)
railties (7.0.8.7)
actionpack (= 7.0.8.7)
activesupport (= 7.0.8.7)
method_source
rake (>= 12.2)
thor (~> 1.0)
@ -743,7 +743,7 @@ GEM
test-prof (1.2.3)
thor (1.3.2)
tilt (2.2.0)
timeout (0.4.2)
timeout (0.4.3)
tpm-key_attestation (0.12.0)
bindata (~> 2.4)
openssl (> 2.0)
@ -800,7 +800,8 @@ GEM
railties (>= 5.2)
semantic_range (>= 2.3.0)
websocket (1.2.9)
websocket-driver (0.7.6)
websocket-driver (0.7.7)
base64
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
wisper (2.0.1)

View file

@ -46,6 +46,8 @@ class DeliveryFailureTracker
urls.reject do |url|
host = Addressable::URI.parse(url).normalized_host
unavailable_domains_map[host]
rescue Addressable::URI::InvalidURIError, IDN::Idna::IdnaError
true
end
end

View file

@ -9,6 +9,8 @@ class ActivityPub::ProcessAccountService < BaseService
SUBDOMAINS_RATELIMIT = 10
DISCOVERIES_PER_REQUEST = 400
VALID_URI_SCHEMES = %w(http https).freeze
# Should be called with confirmed valid JSON
# and WebFinger-resolved username and domain
def call(username, domain, json, options = {})
@ -96,16 +98,28 @@ class ActivityPub::ProcessAccountService < BaseService
end
def set_immediate_protocol_attributes!
@account.inbox_url = @json['inbox'] || ''
@account.outbox_url = @json['outbox'] || ''
@account.shared_inbox_url = (@json['endpoints'].is_a?(Hash) ? @json['endpoints']['sharedInbox'] : @json['sharedInbox']) || ''
@account.followers_url = @json['followers'] || ''
@account.inbox_url = valid_collection_uri(@json['inbox'])
@account.outbox_url = valid_collection_uri(@json['outbox'])
@account.shared_inbox_url = valid_collection_uri(@json['endpoints'].is_a?(Hash) ? @json['endpoints']['sharedInbox'] : @json['sharedInbox'])
@account.followers_url = valid_collection_uri(@json['followers'])
@account.url = url || @uri
@account.uri = @uri
@account.actor_type = actor_type
@account.created_at = @json['published'] if @json['published'].present?
end
def valid_collection_uri(uri)
uri = uri.first if uri.is_a?(Array)
uri = uri['id'] if uri.is_a?(Hash)
return '' unless uri.is_a?(String)
parsed_uri = Addressable::URI.parse(uri)
VALID_URI_SCHEMES.include?(parsed_uri.scheme) && parsed_uri.host.present? ? parsed_uri : ''
rescue Addressable::URI::InvalidURIError
''
end
def set_immediate_attributes!
@account.featured_collection_url = @json['featured'] || ''
@account.devices_url = @json['devices'] || ''
@ -268,10 +282,11 @@ class ActivityPub::ProcessAccountService < BaseService
end
def collection_info(type)
return [nil, nil] if @json[type].blank?
collection_uri = valid_collection_uri(@json[type])
return [nil, nil] if collection_uri.blank?
return @collections[type] if @collections.key?(type)
collection = fetch_resource_without_id_validation(@json[type])
collection = fetch_resource_without_id_validation(collection_uri)
total_items = collection.is_a?(Hash) && collection['totalItems'].present? && collection['totalItems'].is_a?(Numeric) ? collection['totalItems'] : nil
has_first_page = collection.is_a?(Hash) && collection['first'].present?

View file

@ -16,6 +16,7 @@ class Scheduler::UserCleanupScheduler
User.where('confirmed_at is NULL AND confirmation_sent_at <= ?', 2.days.ago).reorder(nil).find_in_batches do |batch|
# We have to do it separately because of missing database constraints
AccountModerationNote.where(target_account_id: batch.map(&:account_id)).delete_all
WebauthnCredential.where(user_id: batch.map(&:id)).delete_all
Account.where(id: batch.map(&:account_id)).delete_all
User.where(id: batch.map(&:id)).delete_all
end

View file

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

View file

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

View file

@ -42,8 +42,8 @@ describe DeliveryFailureTracker do
Fabricate(:unavailable_domain, domain: 'foo.bar')
end
it 'removes URLs that are unavailable' do
results = described_class.without_unavailable(['http://example.com/good/inbox', 'http://foo.bar/unavailable/inbox'])
it 'removes URLs that are bogus or unavailable' do
results = described_class.without_unavailable(['http://example.com/good/inbox', 'http://foo.bar/unavailable/inbox', '{foo:'])
expect(results).to include('http://example.com/good/inbox')
expect(results).to_not include('http://foo.bar/unavailable/inbox')

View file

@ -9,6 +9,7 @@ describe Scheduler::UserCleanupScheduler do
let!(:old_unconfirmed_user) { Fabricate(:user) }
let!(:confirmed_user) { Fabricate(:user) }
let!(:moderation_note) { Fabricate(:account_moderation_note, account: Fabricate(:account), target_account: old_unconfirmed_user.account) }
let!(:webauthn_credential) { Fabricate(:webauthn_credential, user_id: old_unconfirmed_user.id) }
describe '#perform' do
before do
@ -18,8 +19,24 @@ describe Scheduler::UserCleanupScheduler do
confirmed_user.update!(confirmed_at: 1.day.ago)
end
it 'deletes the old unconfirmed user' do
expect { subject.perform }.to change { User.exists?(old_unconfirmed_user.id) }.from(true).to(false)
it 'deletes the old unconfirmed user and metadata while preserving confirmed user and newer unconfirmed user' do
expect { subject.perform }
.to change { User.exists?(old_unconfirmed_user.id) }
.from(true).to(false)
.and change { Account.exists?(old_unconfirmed_user.account_id) }
.from(true).to(false)
expect { moderation_note.reload }
.to raise_error(ActiveRecord::RecordNotFound)
expect { webauthn_credential.reload }
.to raise_error(ActiveRecord::RecordNotFound)
expect(User.exists?(new_unconfirmed_user.id))
.to be true
expect(User.exists?(confirmed_user.id))
.to be true
expect(Account.exists?(new_unconfirmed_user.account_id))
.to be true
expect(Account.exists?(confirmed_user.account_id))
.to be true
end
it "deletes the old unconfirmed user's account" do