From 79931bf3ae401b2990e09b0232e6ba008978a073 Mon Sep 17 00:00:00 2001
From: Claire <claire.github-309c@sitedethib.com>
Date: Tue, 6 May 2025 15:02:13 +0200
Subject: [PATCH] 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)