From 69378eac99c013a0db7d2d5ff9a54dfcc287d9ce Mon Sep 17 00:00:00 2001
From: David Leadbeater <dgl@dgl.cx>
Date: Mon, 21 Nov 2022 05:28:13 +1100
Subject: [PATCH] Don't allow URLs that contain non-normalized paths to be
 verified (#20999)

* Don't allow URLs that contain non-normalized paths to be verified

This stops things like https://example.com/otheruser/../realuser where
"/otheruser" appears to be the verified URL, but the actual URL being
verified is "/realuser" due to the "/../".

Also fix a test to use 'https', so it is testing the right thing, now
that since #20304 https is required.

* missing do
---
 app/models/account/field.rb       |  3 ++-
 spec/models/account/field_spec.rb | 10 +++++++++-
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/app/models/account/field.rb b/app/models/account/field.rb
index ffc8dce80..4db4cac30 100644
--- a/app/models/account/field.rb
+++ b/app/models/account/field.rb
@@ -46,7 +46,8 @@ class Account::Field < ActiveModelSerializers::Model
       parsed_url.user.nil? &&
       parsed_url.password.nil? &&
       parsed_url.host.present? &&
-      parsed_url.normalized_host == parsed_url.host
+      parsed_url.normalized_host == parsed_url.host &&
+      (parsed_url.path.empty? || parsed_url.path == parsed_url.normalized_path)
   rescue Addressable::URI::InvalidURIError, IDN::Idna::IdnaError
     false
   end
diff --git a/spec/models/account/field_spec.rb b/spec/models/account/field_spec.rb
index b4beec048..0ac9769bc 100644
--- a/spec/models/account/field_spec.rb
+++ b/spec/models/account/field_spec.rb
@@ -67,7 +67,15 @@ RSpec.describe Account::Field, type: :model do
       end
 
       context 'for an IDN URL' do
-        let(:value) { 'http://twitter.com∕dougallj∕status∕1590357240443437057.ê.cc/twitter.html' }
+        let(:value) { 'https://twitter.com∕dougallj∕status∕1590357240443437057.ê.cc/twitter.html' }
+
+        it 'returns false' do
+          expect(subject.verifiable?).to be false
+        end
+      end
+
+      context 'for a URL with a non-normalized path' do
+        let(:value) { 'https://github.com/octocatxxxxxxxx/../mastodon' }
 
         it 'returns false' do
           expect(subject.verifiable?).to be false