Merge tag 'v4.2.21'

This commit is contained in:
bgme 2025-05-07 11:09:29 +08:00
commit e0fefefc26
18 changed files with 123 additions and 40 deletions

View file

@ -2,6 +2,31 @@
All notable changes to this project will be documented in this file.
## [4.2.21] - 2025-05-06
### Security
- Update dependencies
- Check scheme on account, profile, and media URLs ([GHSA-x2rc-v5wx-g3m5](https://github.com/mastodon/mastodon/security/advisories/GHSA-x2rc-v5wx-g3m5))
### Added
- Add warning for REDIS_NAMESPACE deprecation at startup (#34581 by @ClearlyClaire)
- Add built-in context for interaction policies (#34574 by @ClearlyClaire)
### Changed
- Change activity distribution error handling to skip retrying for deleted accounts (#33617 by @ClearlyClaire)
### Removed
- Remove double-query for signed query strings (#34610 by @ClearlyClaire)
### Fixed
- Fix incorrect redirect in response to unauthenticated API requests in limited federation mode (#34549 by @ClearlyClaire)
- Fix sign-up e-mail confirmation page reloading on error or redirect (#34548 by @ClearlyClaire)
## [4.2.20] - 2025-04-02
### Add

View file

@ -215,7 +215,7 @@ GEM
activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1)
date (3.3.4)
date (3.4.1)
debug_inspector (1.1.0)
devise (4.9.2)
bcrypt (~> 3.0)
@ -455,7 +455,7 @@ GEM
uri
net-http-persistent (4.0.2)
connection_pool (~> 2.2)
net-imap (0.3.8)
net-imap (0.5.8)
date
net-protocol
net-ldap (0.18.0)
@ -469,7 +469,7 @@ GEM
net-protocol
net-ssh (7.1.0)
nio4r (2.7.4)
nokogiri (1.18.3)
nokogiri (1.18.8)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
nsa (0.3.0)

View file

@ -13,9 +13,8 @@ A "vulnerability in Mastodon" is a vulnerability in the code distributed through
## Supported Versions
| Version | Supported |
| ------- | ---------------- |
| 4.3.x | Yes |
| 4.2.x | Yes |
| 4.1.x | Until 2025-04-08 |
| < 4.1 | No |
| Version | Supported |
| ------- | --------- |
| 4.3.x | Yes |
| 4.2.x | Yes |
| < 4.2 | No |

View file

@ -141,6 +141,13 @@ class Api::BaseController < ApplicationController
end
end
# Redefine `require_functional!` to properly output JSON instead of HTML redirects
def require_functional!
return if current_user.functional?
require_user!
end
def render_empty
render json: {}, status: 200
end

View file

@ -68,7 +68,23 @@ class ApplicationController < ActionController::Base
end
def require_functional!
redirect_to edit_user_registration_path unless current_user.functional?
return if current_user.functional?
respond_to do |format|
format.any do
redirect_to edit_user_registration_path
end
format.json do
if !current_user.confirmed?
render json: { error: 'Your login is missing a confirmed e-mail address' }, status: 403
elsif !current_user.approved?
render json: { error: 'Your login is currently pending approval' }, status: 403
elsif !current_user.functional?
render json: { error: 'Your login is currently disabled' }, status: 403
end
end
end
end
def skip_csrf_meta_tags?

View file

@ -32,6 +32,13 @@ module ContextHelper
'messageFranking' => 'toot:messageFranking', 'messageType' => 'toot:messageType', 'cipherText' => 'toot:cipherText'
},
suspended: { 'toot' => 'http://joinmastodon.org/ns#', 'suspended' => 'toot:suspended' },
interaction_policies: {
'gts' => 'https://gotosocial.org/ns#',
'interactionPolicy' => { '@id' => 'gts:interactionPolicy', '@type' => '@id' },
'canQuote' => { '@id' => 'gts:canQuote', '@type' => '@id' },
'automaticApproval' => { '@id' => 'gts:automaticApproval', '@type' => '@id' },
'manualApproval' => { '@id' => 'gts:manualApproval', '@type' => '@id' },
},
}.freeze
def full_context

View file

@ -40,6 +40,10 @@ export function normalizeAccount(account) {
account.moved = account.moved.id;
}
if (!(account.url.startsWith('http://') || account.url.startsWith('https://'))) {
account.url = account.uri;
}
return account;
}
@ -96,6 +100,17 @@ export function normalizeStatus(status, normalOldStatus) {
normalStatus.contentHtml = emojify(normalStatus.content, emojiMap);
normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap);
normalStatus.hidden = expandSpoilers ? false : spoilerText.length > 0 || normalStatus.sensitive;
if (normalStatus.url && !(normalStatus.url.startsWith('http://') || normalStatus.url.startsWith('https://'))) {
normalStatus.url = null;
}
normalStatus.url = normalStatus.url || normalStatus.uri;
normalStatus.media_attachments.forEach(item => {
if (item.remote_url && !(item.remote_url.startsWith('http://') || item.remote_url.startsWith('https://')))
item.remote_url = null;
});
}
if (normalOldStatus) {

View file

@ -5,8 +5,11 @@ import ready from '../mastodon/ready';
ready(() => {
setInterval(() => {
axios.get('/api/v1/emails/check_confirmation').then((response) => {
if (response.data) {
axios.get('/api/v1/emails/check_confirmation', {
headers: { Accept: 'application/json' },
withCredentials: true,
}).then((response) => {
if (response.status === 200 && response.data === true) {
window.location = '/start';
}
}).catch(error => {

View file

@ -15,13 +15,15 @@ class ActivityPub::Parser::MediaAttachmentParser
end
def remote_url
Addressable::URI.parse(@json['url'])&.normalize&.to_s
url = Addressable::URI.parse(@json['url'])&.normalize&.to_s
url unless unsupported_uri_scheme?(url)
rescue Addressable::URI::InvalidURIError
nil
end
def thumbnail_remote_url
Addressable::URI.parse(@json['icon'].is_a?(Hash) ? @json['icon']['url'] : @json['icon'])&.normalize&.to_s
url = Addressable::URI.parse(@json['icon'].is_a?(Hash) ? @json['icon']['url'] : @json['icon'])&.normalize&.to_s
url unless unsupported_uri_scheme?(url)
rescue Addressable::URI::InvalidURIError
nil
end

View file

@ -27,7 +27,10 @@ class ActivityPub::Parser::StatusParser
end
def url
url_to_href(@object['url'], 'text/html') if @object['url'].present?
return if @object['url'].blank?
url = url_to_href(@object['url'], 'text/html')
url unless unsupported_uri_scheme?(url)
end
def text

View file

@ -4,6 +4,7 @@ require 'singleton'
class ActivityPub::TagManager
include Singleton
include JsonLdHelper
include RoutingHelper
CONTEXT = 'https://www.w3.org/ns/activitystreams'
@ -17,7 +18,7 @@ class ActivityPub::TagManager
end
def url_for(target)
return target.url if target.respond_to?(:local?) && !target.local?
return unsupported_uri_scheme?(target.url) ? nil : target.url if target.respond_to?(:local?) && !target.local?
return unless target.respond_to?(:object_type)

View file

@ -6,14 +6,13 @@
class HttpSignatureDraft
REQUEST_TARGET = '(request-target)'
def initialize(keypair, key_id, full_path: true)
def initialize(keypair, key_id)
@keypair = keypair
@key_id = key_id
@full_path = full_path
end
def request_target(verb, url)
if url.query.nil? || !@full_path
if url.query.nil?
"#{verb} #{url.path}"
else
"#{verb} #{url.path}?#{url.query}"

View file

@ -75,7 +75,6 @@ class Request
@url = Addressable::URI.parse(url).normalize
@http_client = options.delete(:http_client)
@allow_local = options.delete(:allow_local)
@full_path = !options.delete(:omit_query_string)
@options = {
follow: {
max_hops: 3,
@ -102,7 +101,7 @@ class Request
key_id = ActivityPub::TagManager.instance.key_uri_for(actor)
keypair = sign_with.present? ? OpenSSL::PKey::RSA.new(sign_with) : actor.keypair
@signing = HttpSignatureDraft.new(keypair, key_id, full_path: @full_path)
@signing = HttpSignatureDraft.new(keypair, key_id)
self
end

View file

@ -37,20 +37,7 @@ class ActivityPub::FetchRepliesService < BaseService
return unless @allow_synchronous_requests
return if non_matching_uri_hosts?(@account.uri, collection_or_uri)
# NOTE: For backward compatibility reasons, Mastodon signs outgoing
# queries incorrectly by default.
#
# While this is relevant for all URLs with query strings, this is
# the only code path where this happens in practice.
#
# Therefore, retry with correct signatures if this fails.
begin
fetch_resource_without_id_validation(collection_or_uri, nil, true)
rescue Mastodon::UnexpectedResponseError => e
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: { omit_query_string: false })
end
fetch_resource_without_id_validation(collection_or_uri, nil, true)
end
def filtered_replies

View file

@ -62,7 +62,7 @@ class ActivityPub::DeliveryWorker
light = Stoplight(@inbox_url) do
request_pool.with(@host) do |http_client|
build_request(http_client).perform do |response|
raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response)
raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) || unsalvageable_authorization_failure?(response)
@performed = true
end
@ -74,6 +74,10 @@ class ActivityPub::DeliveryWorker
.run
end
def unsalvageable_authorization_failure?(response)
@source_account.suspended_permanently? && response.code == 401
end
def failure_tracker
@failure_tracker ||= DeliveryFailureTracker.new(@inbox_url)
end

View file

@ -0,0 +1,16 @@
# frozen_string_literal: true
if ENV['REDIS_NAMESPACE']
es_configured = ENV['ES_ENABLED'] == 'true' || ENV.fetch('ES_HOST', 'localhost') != 'localhost' || ENV.fetch('ES_PORT', '9200') != '9200' || ENV.fetch('ES_PASS', 'password') != 'password'
warn <<~MESSAGE
WARNING: the REDIS_NAMESPACE environment variable is deprecated and will be removed in Mastodon 4.4.0.
Please update to Mastodon 4.3 and see documentation at https://github.com/mastodon/redis_namespace_migration
MESSAGE
warn <<~MESSAGE if es_configured && !ENV['ES_PREFIX']
In addition, as REDIS_NAMESPACE is being used as a prefix for Elasticsearch, please do not forget to set ES_PREFIX to "#{ENV.fetch('REDIS_NAMESPACE')}".
MESSAGE
end

View file

@ -56,7 +56,7 @@ services:
web:
build: .
image: ghcr.io/mastodon/mastodon:v4.2.20
image: ghcr.io/mastodon/mastodon:v4.2.21
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.20
image: ghcr.io/mastodon/mastodon:v4.2.21
restart: always
env_file: .env.production
command: node ./streaming
@ -95,7 +95,7 @@ services:
sidekiq:
build: .
image: ghcr.io/mastodon/mastodon:v4.2.20
image: ghcr.io/mastodon/mastodon:v4.2.21
restart: always
env_file: .env.production
command: bundle exec sidekiq

View file

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