From bbe6aba7ff9562844d97b6c6eecec8f43c2a5f2c Mon Sep 17 00:00:00 2001 From: Aline Marques Date: Thu, 29 Oct 2026 17:53:54 -0300 Subject: [PATCH 1/3] AO3-7637 Blank out invalid hrefs that break eBook downloads --- config/config.yml | 2 +- .../gem-plugin_config/sanitizer_config.rb | 9 +++++++++ lib/html_cleaner.rb | 3 ++- spec/lib/html_cleaner_spec.rb | 12 ++++++++++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/config/config.yml b/config/config.yml index 4cbdc38edfe..9d565b6481c 100644 --- a/config/config.yml +++ b/config/config.yml @@ -334,7 +334,7 @@ COMMENT_MODERATION_THRESHOLD: 10 EDITED_COMMENT_SPAM_CHECK_THRESHOLD: 10 # SANITIZER VERSION -SANITIZER_VERSION: 4 +SANITIZER_VERSION: 5 # parameters that must be natural integers and their default values NONZERO_INTEGER_PARAMETERS: diff --git a/config/initializers/gem-plugin_config/sanitizer_config.rb b/config/initializers/gem-plugin_config/sanitizer_config.rb index 65e8be78caa..9fc6b2f4463 100644 --- a/config/initializers/gem-plugin_config/sanitizer_config.rb +++ b/config/initializers/gem-plugin_config/sanitizer_config.rb @@ -67,5 +67,14 @@ module Config rescue URI::InvalidURIError # do nothing, the sanitizer will handle it end + + # On a elements, blank out hrefs that aren't valid URLs + INVALID_HREF_TRANSFORMER = lambda do |env| + return unless env[:node_name] == "a" && env[:node]["href"] + + URI.parse(env[:node]["href"]) + rescue URI::InvalidURIError + env[:node]["href"] = "" + end end end diff --git a/lib/html_cleaner.rb b/lib/html_cleaner.rb index 249a0775dc2..20962acf26c 100644 --- a/lib/html_cleaner.rb +++ b/lib/html_cleaner.rb @@ -59,7 +59,8 @@ def sanitize_value(field, value) # We're allowing users to use HTML in this field transformers = [ Sanitize::Config::OPEN_ATTRIBUTE_TRANSFORMER, - Sanitize::Config::RELATIVE_IMAGE_PATH_TRANSFORMER + Sanitize::Config::RELATIVE_IMAGE_PATH_TRANSFORMER, + Sanitize::Config::INVALID_HREF_TRANSFORMER ] if ArchiveConfig.FIELDS_ALLOWING_MEDIA_EMBEDS.include?(field.to_s) transformers << OtwSanitize::EmbedSanitizer.transformer diff --git a/spec/lib/html_cleaner_spec.rb b/spec/lib/html_cleaner_spec.rb index 4aec90672c1..0a674cda6c7 100644 --- a/spec/lib/html_cleaner_spec.rb +++ b/spec/lib/html_cleaner_spec.rb @@ -444,6 +444,18 @@ def one_cell_table(content) end end + context "when given an tag with an invalid href" do + it "should clean up an invalid href while preserving the link text" do + result = sanitize_value(field, "testy") + expect(result).to eq("

testy

") + end + + it "should not clean up a valid href" do + result = sanitize_value(field, "testy") + expect(result).to eq("

testy

") + end + end + # These are from https://github.com/rgrove/sanitize/commit/a11498de9e283cd457b35ee252983662f7452aa9 it 'should not preserve the content of removed `math` elements' do content = sanitize_value(field, 'hello! ') From c843b77c9b400f22aeb374aa8a04b0f8a2215f59 Mon Sep 17 00:00:00 2001 From: Aline Marques Date: Thu, 29 Oct 2026 18:13:13 -0300 Subject: [PATCH 2/3] AO3-7637 Only blank out hrefs with unclosed brackets in the host --- config/initializers/gem-plugin_config/sanitizer_config.rb | 8 ++++---- spec/lib/html_cleaner_spec.rb | 7 ++++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/config/initializers/gem-plugin_config/sanitizer_config.rb b/config/initializers/gem-plugin_config/sanitizer_config.rb index 9fc6b2f4463..7b0b21a5ad2 100644 --- a/config/initializers/gem-plugin_config/sanitizer_config.rb +++ b/config/initializers/gem-plugin_config/sanitizer_config.rb @@ -71,10 +71,10 @@ module Config # On a elements, blank out hrefs that aren't valid URLs INVALID_HREF_TRANSFORMER = lambda do |env| return unless env[:node_name] == "a" && env[:node]["href"] - - URI.parse(env[:node]["href"]) - rescue URI::InvalidURIError - env[:node]["href"] = "" + + host = Addressable::URI.parse(env[:node]["href"]).host + + env[:node]["href"] = "" if host&.start_with?("[") && !host&.end_with?("]") end end end diff --git a/spec/lib/html_cleaner_spec.rb b/spec/lib/html_cleaner_spec.rb index 0a674cda6c7..9ff53f1c402 100644 --- a/spec/lib/html_cleaner_spec.rb +++ b/spec/lib/html_cleaner_spec.rb @@ -450,10 +450,15 @@ def one_cell_table(content) expect(result).to eq("

testy

") end - it "should not clean up a valid href" do + it "should not clean up a valid href" do result = sanitize_value(field, "testy") expect(result).to eq("

testy

") end + + it "should not clean up a valid href with non-ASCII characters" do + result = sanitize_value(field, "testy") + expect(result).to eq("

testy

") + end end # These are from https://github.com/rgrove/sanitize/commit/a11498de9e283cd457b35ee252983662f7452aa9 From 39172b7f6676cfce00dd75d060e2bc5f5f9b050b Mon Sep 17 00:00:00 2001 From: Aline Marques Date: Thu, 29 Oct 2026 18:20:56 -0300 Subject: [PATCH 3/3] AO3-7637 Handle hrefs that Addressable can't parse --- config/initializers/gem-plugin_config/sanitizer_config.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/initializers/gem-plugin_config/sanitizer_config.rb b/config/initializers/gem-plugin_config/sanitizer_config.rb index 7b0b21a5ad2..c0b12c76b18 100644 --- a/config/initializers/gem-plugin_config/sanitizer_config.rb +++ b/config/initializers/gem-plugin_config/sanitizer_config.rb @@ -75,6 +75,8 @@ module Config host = Addressable::URI.parse(env[:node]["href"]).host env[:node]["href"] = "" if host&.start_with?("[") && !host&.end_with?("]") + rescue Addressable::URI::InvalidURIError + env[:node]["href"] = "" end end end