From 041c068cec516474d61862faf3910b26c7e10073 Mon Sep 17 00:00:00 2001
From: Ryan Grove <ryan@wonko.com>
Date: Mon, 26 Jun 2023 11:31:55 -0700
Subject: [PATCH 1/3] Escape `</` to prevent a style element from being closed
 prematurely

---
 lib/sanitize/transformers/clean_css.rb |  1 +
 test/test_malicious_css.rb             | 13 +++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/lib/sanitize/transformers/clean_css.rb b/lib/sanitize/transformers/clean_css.rb
index 4203bf6..fc26c61 100644
--- a/lib/sanitize/transformers/clean_css.rb
+++ b/lib/sanitize/transformers/clean_css.rb
@@ -48,6 +48,7 @@ def call(env)
     if css.strip.empty?
       node.unlink
     else
+      css.gsub!('</', '<\/')
       node.children.unlink
       node << Nokogiri::XML::Text.new(css, node.document)
     end
diff --git a/test/test_malicious_css.rb b/test/test_malicious_css.rb
index 52c9539..eecedbd 100644
--- a/test/test_malicious_css.rb
+++ b/test/test_malicious_css.rb
@@ -39,4 +39,17 @@
   it 'should not allow behaviors' do
     _(@s.properties(%[behavior: url(xss.htc);])).must_equal ''
   end
+
+  describe 'sanitization bypass via CSS at-rule in HTML <style> element' do
+    before do
+      @s = Sanitize.new(Sanitize::Config::RELAXED)
+    end
+
+    it 'is not possible to prematurely end a <style> element' do
+      assert_equal(
+        %[<style>@media<\\/style><iframe srcdoc='<script>alert(document.domain)<\\/script>'>{}</style>],
+        @s.fragment(%[<style>@media</sty/**/le><iframe srcdoc='<script>alert(document.domain)</script>'></style>])
+      )
+    end
+  end
 end
