CVE-2020-36644: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: A vulnerability has been found in jamesmartin Inline SVG up to 1.7.1 and classified as problematic. Affected by this vulnerability is an unknown functionality of the file lib/inline_svg/action_view/helpers.rb of the component URL Parameter Handler. The manipulation of the argument filename leads to cross site scripting. The attack can be launched remotely. Upgrading to version 1.7.2 is able to address this issue. The identifier of the patch is f5363b351508486021f99e083c92068cf2943621. It is recommended to upgrade the affected component. The identifier VDB-217597 was assigned to this vulnerability.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2023-01-07T10:15Z
Repository: https://github.com/jamesmartin/inline_svg
Language: Ruby
Files changed: lib/inline_svg/action_view/helpers.rb, spec/helpers/inline_svg_spec.rb
Commit date: 2020-03-03 10:44:06 -0600
Commit message: Escape filename to avoid XSS from malicious input

Because:

* If user input is provided for the file name (as in rendering an SVG
  based on a URL parameter), the blanket marking of the SVG output as
  HTML-safe exposes an app to an XSS attack in the comment listing the
  file that was not found.

Solution:

* HTML-escape the filename rendering the comment that it was not found.

Diff: diff --git a/lib/inline_svg/action_view/helpers.rb b/lib/inline_svg/action_view/helpers.rb
index dcb46d6..8658132 100644
--- a/lib/inline_svg/action_view/helpers.rb
+++ b/lib/inline_svg/action_view/helpers.rb
@@ -53,11 +53,11 @@ module InlineSvg
         end
       end
 
       def placeholder(filename)
         css_class = InlineSvg.configuration.svg_not_found_css_class
-        not_found_message = "'#{filename}' #{extension_hint(filename)}"
+        not_found_message = "'#{ERB::Util.html_escape_once(filename)}' #{extension_hint(filename)}"
 
         if css_class.nil?
           return "<svg><!-- SVG file not found: #{not_found_message}--></svg>".html_safe
         else
           return "<svg class='#{css_class}'><!-- SVG file not found: #{not_found_message}--></svg>".html_safe
diff --git a/spec/helpers/inline_svg_spec.rb b/spec/helpers/inline_svg_spec.rb
index f0291f6..3df23e5 100644
--- a/spec/helpers/inline_svg_spec.rb
+++ b/spec/helpers/inline_svg_spec.rb
@@ -44,10 +44,21 @@ describe InlineSvg::ActionView::Helpers do
         output = helper.send(helper_method, 'some-missing-file.svg')
         expect(output).to eq "<svg><!-- SVG file not found: 'some-missing-file.svg' --></svg>"
         expect(output).to be_html_safe
       end
 
+      it "escapes malicious input" do
+        malicious = "--></svg><script>alert(1)</script><svg>.svg"
+        allow(InlineSvg::AssetFile).to receive(:named).
+          with(malicious).
+          and_raise(InlineSvg::AssetFile::FileNotFound.new)
+
+        output = helper.send(helper_method, malicious)
+        expect(output).to eq "<svg><!-- SVG file not found: '#{ERB::Util.html_escape_once(malicious)}' --></svg>"
+        expect(output).to be_html_safe
+      end
+
       it "gives a helpful hint when no .svg extension is provided in the filename" do
         allow(InlineSvg::AssetFile).to receive(:named).
           with('missing-file-with-no-extension').
           and_raise(InlineSvg::AssetFile::FileNotFound.new)
 

Vulnerable code:         not_found_message = "'#{filename}' #{extension_hint(filename)}"
Fixed code:         not_found_message = "'#{ERB::Util.html_escape_once(filename)}' #{extension_hint(filename)}"
      it "escapes malicious input" do
        malicious = "--></svg><script>alert(1)</script><svg>.svg"
        allow(InlineSvg::AssetFile).to receive(:named).
          with(malicious).
          and_raise(InlineSvg::AssetFile::FileNotFound.new)

        output = helper.send(helper_method, malicious)
        expect(output).to eq "<svg><!-- SVG file not found: '#{ERB::Util.html_escape_once(malicious)}' --></svg>"
        expect(output).to be_html_safe
      end