From 5d7e3bbd17484bc2bf4a0d3f3c2a304ce5c457b2 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 27 Jul 2026 16:02:01 +0200 Subject: [PATCH] Merge commit from fork * Fix GHSA-7jvv-fhmg-wpfw * Fix GHSA-hx34-2pfw-2qfj * Fix GHSA-vwhj-3g83-v276 * Bump version to v4.6.4 --- CHANGELOG.md | 39 +++++++++++++++++++ .../admin/collections_controller.rb | 2 +- .../api/v1/admin/measures_controller.rb | 6 +-- .../api/v1/admin/retention_controller.rb | 14 +++---- .../admin/metrics/dimension/base_dimension.rb | 2 + app/lib/admin/metrics/measure/base_measure.rb | 6 ++- app/lib/admin/metrics/retention.rb | 7 +++- app/lib/private_address_check.rb | 2 +- lib/mastodon/version.rb | 2 +- spec/requests/api/v1/admin/measures_spec.rb | 2 + spec/requests/api/v1/admin/retention_spec.rb | 4 +- 11 files changed, 67 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a40d94fe80..ed1f8c50c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,45 @@ All notable changes to this project will be documented in this file. +## [4.6.4] - 2026-07-27 + +### Security + +- Fix incorrect permission enforcement ([GHSA-7jvv-fhmg-wpfw](https://github.com/mastodon/mastodon/security/advisories/GHSA-7jvv-fhmg-wpfw), [GHSA-hx34-2pfw-2qfj](https://github.com/mastodon/mastodon/security/advisories/GHSA-hx34-2pfw-2qfj)) +- Fix SSRF protection bypass via IPv4-compatible IPv6 addresses ([GHSA-vwhj-3g83-v276](https://github.com/mastodon/mastodon/security/advisories/GHSA-vwhj-3g83-v276)) +- Update dependencies + +### Changed + +- Change autosuggestions to include second word in web UI (#39622 and #39696 by @Gargron and @zunda) + +### Fixed + +- Fix being unable to vote in polls without an expiration date (#39949 by @ClearlyClaire) +- Fix “Hide media with a warning” filters not being applied correctly (#39946 by @ClearlyClaire) +- Fix performance of user-focused queries in admin dashboard (#39929 by @ClearlyClaire) +- Fix Web Push subscription deletion endpoint incorrectly expecting anti-CSRF tokens (#39918 by @ClearlyClaire) +- Fix `ActivityPub::Activity::Create` trying to re-create known statuses when author changes (#39916 by @ClearlyClaire) +- Fix typo in quotes list error handling (#39904 by @shleeable) +- Fix lax relevancy check in inbound activity processing (#39892 by @ClearlyClaire) +- Fix `Account::Merging` concern not supporting Quotes or Collections, refactor it (#39884 by @ClearlyClaire) +- Fix various emoji search issues (#39815 by @ChaosExAnima) +- Fix swapped order of "accept/reject" actions in follow requests (#39862 by @diondiondion) +- Fix suspended accounts not being removed from follow request count in `/api/v1/accounts/verify_credentials` (#39858 by @ClearlyClaire) +- Fix "Learn more" link target in column post privacy hint (#39829 by @diondiondion) +- Fix page refresh when trying to save custom profile fields (#39828 by @diondiondion) +- Fix followed tags not being properly cleaned up when an account is deleted (#39824 by @shleeable) +- Fix CW being copied to body when editing quote posts with empty text (#39823 and #39837 by @shleeable and @ClearlyClaire) +- Fix handling of `QuoteRequest` rejections when those can't be found by `id` (#39820 by @shleeable) +- Fix autofollow option being ignored in invite moderation interface (#39819 by @shleeable) +- Fix pagination overlapping announcement reactions bar (#39814 by @diondiondion) +- Fix very wide images overflowing posts horizontally (#39812 by @diondiondion) +- Fix collections not being removed when an account is deleted (#39809 by @oneiros) +- Fix account followed languages selector (#39801 by @ChaosExAnima) +- Fix error handling in `ActivityPub::ProcessFeaturedItemService` (#39787 by @ClearlyClaire) +- Fix display of past relative times (#39742 by @ClearlyClaire) +- Fix pinned post button width (#39724 by @ChaosExAnima) + ## [4.6.3] - 2026-07-03 ### Security diff --git a/app/controllers/admin/collections_controller.rb b/app/controllers/admin/collections_controller.rb index 405c779e3d..78ac9f0e8b 100644 --- a/app/controllers/admin/collections_controller.rb +++ b/app/controllers/admin/collections_controller.rb @@ -14,7 +14,7 @@ module Admin end def show - authorize @collection, :show? + authorize [:admin, @collection], :show? end def batch diff --git a/app/controllers/api/v1/admin/measures_controller.rb b/app/controllers/api/v1/admin/measures_controller.rb index d78d7e10b3..d879cca926 100644 --- a/app/controllers/api/v1/admin/measures_controller.rb +++ b/app/controllers/api/v1/admin/measures_controller.rb @@ -17,9 +17,9 @@ class Api::V1::Admin::MeasuresController < Api::BaseController def set_measures @measures = Admin::Metrics::Measure.retrieve( - params[:keys], - params[:start_at], - params[:end_at], + params.require(:keys), + params.require(:start_at), + params.require(:end_at), params ) end diff --git a/app/controllers/api/v1/admin/retention_controller.rb b/app/controllers/api/v1/admin/retention_controller.rb index 59d6b83883..41f1be7edb 100644 --- a/app/controllers/api/v1/admin/retention_controller.rb +++ b/app/controllers/api/v1/admin/retention_controller.rb @@ -4,22 +4,22 @@ class Api::V1::Admin::RetentionController < Api::BaseController include Authorization before_action -> { authorize_if_got_token! :'admin:read' } - before_action :set_cohorts + before_action :set_retention after_action :verify_authorized def create authorize :dashboard, :index? - render json: @cohorts, each_serializer: REST::Admin::CohortSerializer + render json: @retention.cohorts, each_serializer: REST::Admin::CohortSerializer end private - def set_cohorts - @cohorts = Admin::Metrics::Retention.new( - params[:start_at], - params[:end_at], + def set_retention + @retention = Admin::Metrics::Retention.new( + params.require(:start_at), + params.require(:end_at), params[:frequency] - ).cohorts + ) end end diff --git a/app/lib/admin/metrics/dimension/base_dimension.rb b/app/lib/admin/metrics/dimension/base_dimension.rb index 0e055e0e75..0dbf55a27a 100644 --- a/app/lib/admin/metrics/dimension/base_dimension.rb +++ b/app/lib/admin/metrics/dimension/base_dimension.rb @@ -17,6 +17,8 @@ class Admin::Metrics::Dimension::BaseDimension @limit = limit&.to_i @params = params @loaded = false + + @start_at = [@start_at, @end_at - 2.years].max if @start_at.present? && @end_at.present? end def key diff --git a/app/lib/admin/metrics/measure/base_measure.rb b/app/lib/admin/metrics/measure/base_measure.rb index 88a7cb09a0..27916024d1 100644 --- a/app/lib/admin/metrics/measure/base_measure.rb +++ b/app/lib/admin/metrics/measure/base_measure.rb @@ -12,10 +12,12 @@ class Admin::Metrics::Measure::BaseMeasure alias loaded? loaded def initialize(start_at, end_at, params) - @start_at = start_at&.to_datetime - @end_at = end_at&.to_datetime + @start_at = start_at.to_datetime + @end_at = end_at.to_datetime @params = params @loaded = false + + @start_at = [@start_at, @end_at - 2.years].max end def cache_key diff --git a/app/lib/admin/metrics/retention.rb b/app/lib/admin/metrics/retention.rb index e5ce549609..64635eaf8e 100644 --- a/app/lib/admin/metrics/retention.rb +++ b/app/lib/admin/metrics/retention.rb @@ -16,10 +16,13 @@ class Admin::Metrics::Retention alias loaded? loaded def initialize(start_at, end_at, frequency) - @start_at = start_at&.to_date - @end_at = end_at&.to_date + @start_at = start_at.to_date + @end_at = end_at.to_date + @frequency = %w(day month).include?(frequency) ? frequency : 'day' @loaded = false + + @start_at = [@start_at, @end_at - (@frequency == 'day' ? 31.days : 12.months)].max end def cache_key diff --git a/app/lib/private_address_check.rb b/app/lib/private_address_check.rb index e0ba017ba3..8802d06e82 100644 --- a/app/lib/private_address_check.rb +++ b/app/lib/private_address_check.rb @@ -34,7 +34,7 @@ module PrivateAddressCheck module_function def private_address?(address) - address = address.native if address.ipv6? && address.ipv4_mapped? + address = address.native if address.ipv6? && (address.ipv4_mapped? || address.ipv4_compat?) address.private? || address.loopback? || address.link_local? || CIDR_LIST.any? { |cidr| cidr.include?(address) } end end diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 9f27debc13..17eff7285a 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -13,7 +13,7 @@ module Mastodon end def patch - 3 + 4 end def default_prerelease diff --git a/spec/requests/api/v1/admin/measures_spec.rb b/spec/requests/api/v1/admin/measures_spec.rb index 6c35da5656..7607dc17c5 100644 --- a/spec/requests/api/v1/admin/measures_spec.rb +++ b/spec/requests/api/v1/admin/measures_spec.rb @@ -20,6 +20,8 @@ RSpec.describe 'Admin Measures' do domain: 'mastodon.social', include_subdomains: true, }, + start_at: '2026-01-01', + end_at: '2026-07-01', } end diff --git a/spec/requests/api/v1/admin/retention_spec.rb b/spec/requests/api/v1/admin/retention_spec.rb index 9c7be0981d..2c5736540b 100644 --- a/spec/requests/api/v1/admin/retention_spec.rb +++ b/spec/requests/api/v1/admin/retention_spec.rb @@ -10,7 +10,7 @@ RSpec.describe 'Admin Retention' do describe 'GET /api/v1/admin/retention' do context 'when not authorized' do it 'returns http forbidden' do - post '/api/v1/admin/retention', params: { account_id: account.id, limit: 2 } + post '/api/v1/admin/retention', params: { start_at: '2025-01-04', end_at: '2025-07-05', frequency: 'month' } expect(response) .to have_http_status(403) @@ -23,7 +23,7 @@ RSpec.describe 'Admin Retention' do let(:scopes) { 'admin:read' } it 'returns http success and status json' do - post '/api/v1/admin/retention', params: { account_id: account.id, limit: 2 }, headers: headers + post '/api/v1/admin/retention', params: { start_at: '2025-01-04', end_at: '2025-07-05', frequency: 'month' }, headers: headers expect(response) .to have_http_status(200)