diff --git a/CHANGELOG.md b/CHANGELOG.md index 399b2fe084..8c5ec67d85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,31 @@ All notable changes to this project will be documented in this file. +## [4.5.4] - 2026-01-07 + +### Security + +- Fix SSRF protection bypass ([GHSA](https://github.com/mastodon/mastodon/security/advisories/GHSA-xfrj-c749-jxxq)) +- Fix missing ownership check in severed relationships controller ([GHSA](https://github.com/mastodon/mastodon/security/advisories/GHSA-ww85-x9cp-5v24)) + +### Changed + +- Change HTTP Signature verification status from 401 to 503 on temporary failure to get remote actor (#37221 by @ClearlyClaire) + +### Fixed + +- Fix custom emojis not being rendered in profile fields (#37365 by @ClearlyClaire) +- Fix serialization of context pages (#37376 by @ClearlyClaire) +- Fix quotes with CWs but no text not having fallback link (#37361 by @ClearlyClaire) +- Fix outdated link target for “locked” warning (#37366 by @ClearlyClaire) +- Fix local custom emojis sometimes being rendered in remote posts (#37284 by @ChaosExAnima) +- Fix some assets not being loaded from configured CDN (#37310 by @ChaosExAnima) +- Fix notifications page error in Tor browser (#37285 by @diondiondion) +- Fix custom emojis not being displayed in CWs and fav/boost notifications (#37272 and #37306 by @ChaosExAnima and @ClearlyClaire) +- Fix default `Admin` role not including `view_feeds` permission (#37301 by @ClearlyClaire) +- Fix hashtag autocomplete replacing suggestion's first characters with input (#37281 by @ClearlyClaire) +- Fix mentions of domain-blocked users being processed (#37257 by @ClearlyClaire) + ## [4.5.3] - 2025-12-08 ### Security diff --git a/Gemfile.lock b/Gemfile.lock index 743f0d5bcd..d9e2419e64 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -821,7 +821,7 @@ GEM sidekiq-scheduler (6.0.1) rufus-scheduler (~> 3.2) sidekiq (>= 7.3, < 9) - sidekiq-unique-jobs (8.0.12) + sidekiq-unique-jobs (8.0.11) concurrent-ruby (~> 1.0, >= 1.0.5) sidekiq (>= 7.0.0, < 9.0.0) thor (>= 1.0, < 3.0) diff --git a/app/controllers/severed_relationships_controller.rb b/app/controllers/severed_relationships_controller.rb index 817abebf62..9371ebf7d0 100644 --- a/app/controllers/severed_relationships_controller.rb +++ b/app/controllers/severed_relationships_controller.rb @@ -26,7 +26,7 @@ class SeveredRelationshipsController < ApplicationController private def set_event - @event = AccountRelationshipSeveranceEvent.find(params[:id]) + @event = AccountRelationshipSeveranceEvent.where(account: current_account).find(params[:id]) end def following_data diff --git a/app/lib/private_address_check.rb b/app/lib/private_address_check.rb index d00b16e66b..5c4db6ffae 100644 --- a/app/lib/private_address_check.rb +++ b/app/lib/private_address_check.rb @@ -1,9 +1,7 @@ # frozen_string_literal: true module PrivateAddressCheck - module_function - - CIDR_LIST = [ + IP4_CIDR_LIST = [ IPAddr.new('0.0.0.0/8'), # Current network (only valid as source address) IPAddr.new('100.64.0.0/10'), # Shared Address Space IPAddr.new('172.16.0.0/12'), # Private network @@ -16,6 +14,9 @@ module PrivateAddressCheck IPAddr.new('224.0.0.0/4'), # IP multicast (former Class D network) IPAddr.new('240.0.0.0/4'), # Reserved (former Class E network) IPAddr.new('255.255.255.255'), # Broadcast + ].freeze + + CIDR_LIST = (IP4_CIDR_LIST + IP4_CIDR_LIST.map(&:ipv4_mapped) + [ IPAddr.new('64:ff9b::/96'), # IPv4/IPv6 translation (RFC 6052) IPAddr.new('100::/64'), # Discard prefix (RFC 6666) IPAddr.new('2001::/32'), # Teredo tunneling @@ -25,7 +26,9 @@ module PrivateAddressCheck IPAddr.new('2002::/16'), # 6to4 IPAddr.new('fc00::/7'), # Unique local address IPAddr.new('ff00::/8'), # Multicast - ].freeze + ]).freeze + + module_function def private_address?(address) address.private? || address.loopback? || address.link_local? || CIDR_LIST.any? { |cidr| cidr.include?(address) } diff --git a/docker-compose.yml b/docker-compose.yml index fae93955f1..3615b745f1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -59,7 +59,7 @@ services: web: # You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes # build: . - image: ghcr.io/glitch-soc/mastodon:v4.5.3 + image: ghcr.io/glitch-soc/mastodon:v4.5.4 restart: always env_file: .env.production command: bundle exec puma -C config/puma.rb @@ -83,7 +83,7 @@ services: # build: # dockerfile: ./streaming/Dockerfile # context: . - image: ghcr.io/glitch-soc/mastodon-streaming:v4.5.3 + image: ghcr.io/glitch-soc/mastodon-streaming:v4.5.4 restart: always env_file: .env.production command: node ./streaming/index.js @@ -102,7 +102,7 @@ services: sidekiq: # You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes # build: . - image: ghcr.io/glitch-soc/mastodon:v4.5.3 + image: ghcr.io/glitch-soc/mastodon:v4.5.4 restart: always env_file: .env.production command: bundle exec sidekiq diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 9ac54d1b7c..235ac92cbd 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -17,7 +17,7 @@ module Mastodon end def default_prerelease - 'alpha.1' + 'alpha.2' end def prerelease diff --git a/spec/lib/private_address_check_spec.rb b/spec/lib/private_address_check_spec.rb new file mode 100644 index 0000000000..ee9f9295d5 --- /dev/null +++ b/spec/lib/private_address_check_spec.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe PrivateAddressCheck do + describe 'private_address?' do + it 'returns true for private addresses' do + # rubocop:disable RSpec/ExpectActual + expect( + [ + '192.168.1.7', + '0.0.0.0', + '127.0.0.1', + '::ffff:0.0.0.1', + ] + ).to all satisfy('return true') { |addr| described_class.private_address?(IPAddr.new(addr)) } + # rubocop:enable RSpec/ExpectActual + end + end +end diff --git a/spec/requests/severed_relationships_spec.rb b/spec/requests/severed_relationships_spec.rb index ac98ab8f94..e0116120cb 100644 --- a/spec/requests/severed_relationships_spec.rb +++ b/spec/requests/severed_relationships_spec.rb @@ -3,9 +3,10 @@ require 'rails_helper' RSpec.describe 'Severed Relationships' do - let(:account_rs_event) { Fabricate :account_relationship_severance_event } + let(:account_rs_event) { Fabricate(:account_relationship_severance_event) } + let(:user) { account_rs_event.account.user } - before { sign_in Fabricate(:user) } + before { sign_in user } describe 'GET /severed_relationships/:id/following' do it 'returns a CSV file with correct data' do @@ -22,6 +23,17 @@ RSpec.describe 'Severed Relationships' do expect(response.body) .to include('Account address') end + + context 'when the user is not the subject of the event' do + let(:user) { Fabricate(:user) } + + it 'returns a 404' do + get following_severed_relationship_path(account_rs_event, format: :csv) + + expect(response) + .to have_http_status(404) + end + end end describe 'GET /severed_relationships/:id/followers' do @@ -39,5 +51,16 @@ RSpec.describe 'Severed Relationships' do expect(response.body) .to include('Account address') end + + context 'when the user is not the subject of the event' do + let(:user) { Fabricate(:user) } + + it 'returns a 404' do + get followers_severed_relationship_path(account_rs_event, format: :csv) + + expect(response) + .to have_http_status(404) + end + end end end