CVE-2022-41905: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: WsgiDAV is a generic and extendable WebDAV server based on WSGI. Implementations using this library with directory browsing enabled may be susceptible to Cross Site Scripting (XSS) attacks. This issue has been patched, users can upgrade to version 4.1.0. As a workaround, set `dir_browser.enable = False` in the configuration.
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: 2022-11-11T21:15Z
Repository: https://github.com/mar10/wsgidav
Language: Python
Files changed: wsgidav/dir_browser/_dir_browser.py, wsgidav/dir_browser/htdocs/template.html
Commit date: 2022-11-11 16:37:47 +0100
Commit message: Merge pull request from GHSA-xx6g-jj35-pxjv


Diff: diff --git a/wsgidav/dir_browser/_dir_browser.py b/wsgidav/dir_browser/_dir_browser.py
index a15e231..b247653 100644
--- a/wsgidav/dir_browser/_dir_browser.py
+++ b/wsgidav/dir_browser/_dir_browser.py
@@ -8,11 +8,11 @@ WSGI middleware that handles GET requests on collections to display directories.
 import os
 import sys
 from fnmatch import fnmatch
 from urllib.parse import unquote
 
-from jinja2 import Environment, FileSystemLoader
+from jinja2 import Environment, FileSystemLoader, select_autoescape
 
 from wsgidav import __version__, util
 from wsgidav.dav_error import HTTP_MEDIATYPE_NOT_SUPPORTED, HTTP_OK, DAVError
 from wsgidav.mw.base_mw import BaseMiddleware
 from wsgidav.util import get_uri_name, safe_re_encode, send_redirect_response
@@ -71,11 +71,11 @@ class WsgiDavDirBrowser(BaseMiddleware):
             ASSET_SHARE, True
         )
 
         # Prepare a Jinja2 template
         templateLoader = FileSystemLoader(searchpath=self.htdocs_path)
-        templateEnv = Environment(loader=templateLoader)
+        templateEnv = Environment(loader=templateLoader, autoescape=select_autoescape())
         self.template = templateEnv.get_template("template.html")
 
     def is_disabled(self):
         return self.dir_config.get("enable") is False
 
diff --git a/wsgidav/dir_browser/htdocs/template.html b/wsgidav/dir_browser/htdocs/template.html
index 3a9827e..c464492 100644
--- a/wsgidav/dir_browser/htdocs/template.html
+++ b/wsgidav/dir_browser/htdocs/template.html
@@ -79,11 +79,11 @@
             <a class="{{ row.a_class_2 }}" href="{{row.href_2}}" {% if row.ofe_prefix_2%} data-ofe="{{row.ofe_prefix_2}}" {% endif %} >
                 {{row.display_name_2}}
             </a>
           {% endif -%}
           {%- if row.add_link_html %}
-              {{row.add_link_html}}
+              {{row.add_link_html | safe}}
           {% endif -%}
         </td>
         <td>{{ row.display_type }}</td>
         <td>{{ row.str_size }}</td>
         <td>{{ row.str_modified }}</td>
@@ -93,11 +93,11 @@
   </table>
 
   <hr>
 
   {% if trailer %}
-  <p class="trailer">{{ trailer }}</p>
+  <p class="trailer">{{ trailer | safe }}</p>
   {% endif %}
 
   <object id="winFirefoxPlugin" type="application/x-sharepoint"
       width="0" height="0" style="visibility: hidden;"></object>
 

Vulnerable code: from jinja2 import Environment, FileSystemLoader
        templateEnv = Environment(loader=templateLoader)
              {{row.add_link_html}}
  <p class="trailer">{{ trailer }}</p>
Fixed code: from jinja2 import Environment, FileSystemLoader, select_autoescape
        templateEnv = Environment(loader=templateLoader, autoescape=select_autoescape())
              {{row.add_link_html | safe}}
  <p class="trailer">{{ trailer | safe }}</p>