From 79931bf3ae401b2990e09b0232e6ba008978a073 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 6 May 2025 15:02:13 +0200 Subject: [PATCH 1/3] Merge commit from fork * Check scheme in account and post links * Harden media attachments * Client-side mitigation * Client-side mitigation for media attachments --- .../mastodon/actions/importer/normalizer.js | 11 +++++++++++ app/javascript/mastodon/models/account.ts | 1 + app/lib/activitypub/parser/media_attachment_parser.rb | 6 ++++-- app/lib/activitypub/parser/status_parser.rb | 5 ++++- app/lib/activitypub/tag_manager.rb | 3 ++- 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/app/javascript/mastodon/actions/importer/normalizer.js b/app/javascript/mastodon/actions/importer/normalizer.js index c2918ef8d5..2c583f86d4 100644 --- a/app/javascript/mastodon/actions/importer/normalizer.js +++ b/app/javascript/mastodon/actions/importer/normalizer.js @@ -77,6 +77,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.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) { diff --git a/app/javascript/mastodon/models/account.ts b/app/javascript/mastodon/models/account.ts index 4d95d24757..d681ab26c9 100644 --- a/app/javascript/mastodon/models/account.ts +++ b/app/javascript/mastodon/models/account.ts @@ -144,5 +144,6 @@ export function createAccountFromServerJSON(serverJSON: ApiAccountJSON) { ), note_emojified: emojify(accountJSON.note, emojiMap), note_plain: unescapeHTML(accountJSON.note), + url: accountJSON.url.startsWith('http://') || accountJSON.url.startsWith('https://') ? accountJSON.url : accountJSON.uri, }); } diff --git a/app/lib/activitypub/parser/media_attachment_parser.rb b/app/lib/activitypub/parser/media_attachment_parser.rb index 56b8b23f84..bcbf92214f 100644 --- a/app/lib/activitypub/parser/media_attachment_parser.rb +++ b/app/lib/activitypub/parser/media_attachment_parser.rb @@ -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 diff --git a/app/lib/activitypub/parser/status_parser.rb b/app/lib/activitypub/parser/status_parser.rb index ea779b5cbd..9258482bc0 100644 --- a/app/lib/activitypub/parser/status_parser.rb +++ b/app/lib/activitypub/parser/status_parser.rb @@ -29,7 +29,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 diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb index 2fe707e79b..4d83a9b823 100644 --- a/app/lib/activitypub/tag_manager.rb +++ b/app/lib/activitypub/tag_manager.rb @@ -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) From 3bbf3e9709588e370c7bcc7435c3b8a4666ed612 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 6 May 2025 15:35:54 +0200 Subject: [PATCH 2/3] Fix code style issue (#34624) --- app/javascript/mastodon/models/account.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/javascript/mastodon/models/account.ts b/app/javascript/mastodon/models/account.ts index d681ab26c9..2666059b40 100644 --- a/app/javascript/mastodon/models/account.ts +++ b/app/javascript/mastodon/models/account.ts @@ -144,6 +144,10 @@ export function createAccountFromServerJSON(serverJSON: ApiAccountJSON) { ), note_emojified: emojify(accountJSON.note, emojiMap), note_plain: unescapeHTML(accountJSON.note), - url: accountJSON.url.startsWith('http://') || accountJSON.url.startsWith('https://') ? accountJSON.url : accountJSON.uri, + url: + accountJSON.url.startsWith('http://') || + accountJSON.url.startsWith('https://') + ? accountJSON.url + : accountJSON.uri, }); } From fbe9728f36998d3788e71c56bacc803c857fc422 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 6 May 2025 16:17:07 +0200 Subject: [PATCH 3/3] Bump version to v4.3.8 (#34626) --- CHANGELOG.md | 27 ++++++++++++++++++++++++++- docker-compose.yml | 6 +++--- lib/mastodon/version.rb | 2 +- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dd4783597..a9819a6c79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,34 @@ All notable changes to this project will be documented in this file. +## [4.3.8] - 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.3.7] - 2025-04-02 -### Add +### Added - Add delay to profile updates to debounce them (#34137 by @ClearlyClaire) - Add support for paginating partial collections in `SynchronizeFollowersService` (#34272 and #34277 by @ClearlyClaire) diff --git a/docker-compose.yml b/docker-compose.yml index ba34d858a4..75b49709fe 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/mastodon/mastodon:v4.3.7 + image: ghcr.io/mastodon/mastodon:v4.3.8 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/mastodon/mastodon-streaming:v4.3.7 + image: ghcr.io/mastodon/mastodon-streaming:v4.3.8 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/mastodon/mastodon:v4.3.7 + image: ghcr.io/mastodon/mastodon:v4.3.8 restart: always env_file: .env.production command: bundle exec sidekiq diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 88e82a2b58..841472f7de 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -17,7 +17,7 @@ module Mastodon end def default_prerelease - 'alpha.4' + 'alpha.5' end def prerelease