CVE-2023-47114: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Fides is an open-source privacy engineering platform for managing the fulfillment of data privacy requests in your runtime environment, and the enforcement of privacy regulations in your code. The Fides web application allows data subject users to request access to their personal data. If the request is approved by the data controller user operating the Fides web application, the data subject's personal data can then retrieved from connected systems and data stores before being bundled together as a data subject access request package for the data subject to download. Supported data formats for the package include json and csv, but the most commonly used format is a series of HTML files compressed in a ZIP file. Once downloaded and unzipped, the data subject user can browse the HTML files on their local machine. It was identified that there was no validation of input coming from e.g. the connected systems and data stores which is later reflected in the downloaded data. This can result in an HTML injection that can be abused e.g. for phishing attacks or malicious JavaScript code execution, but only in the context of the data subject's browser accessing a HTML page using the `file://` protocol. Exploitation is limited to rogue Admin UI users, malicious connected system / data store users, and the data subject user if tricked via social engineering into submitting malicious data themselves. This vulnerability has been patched in version 2.23.3.
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-11-08T22:15Z
Repository: https://github.com/ethyca/fides
Language: Python
Files changed: CHANGELOG.md, src/fides/api/service/privacy_request/dsr_package/dsr_report_builder.py
Commit date: 2023-11-07 22:18:32 +0800
Commit message: Merge pull request from GHSA-3vpf-mcj7-5h38

* feat: give the option to escape HTML in templates

* fix: escape HTML in HTML DSR reports

* fix: static checks

* feat: use Jinja autoescape

* docs: update changelog
Diff: diff --git a/CHANGELOG.md b/CHANGELOG.md
index c77c4a75f..f52cf462b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -51,10 +51,11 @@ The types of changes are:
 - Bug where vendor opt-ins would not initialize properly based on a `fides_string` in the TCF overlay [#4368](https://github.com/ethyca/fides/pull/4368)
 
 ## [2.23.0](https://github.com/ethyca/fides/compare/2.22.1...2.23.0)
 
 ### Added
+
 - Added support for 3 additional config variables in Fides.js: fidesEmbed, fidesDisableSaveApi, and fidesTcString [#4262](https://github.com/ethyca/fides/pull/4262)
 - Added support for fidesEmbed, fidesDisableSaveApi, and fidesTcString to be passed into Fides.js via query param, cookie, or window object [#4297](https://github.com/ethyca/fides/pull/4297)
 - New privacy center environment variables `FIDES_PRIVACY_CENTER__IS_FORCED_TCF` which can make the privacy center always return the TCF bundle (`fides-tcf.js`) [#4312](https://github.com/ethyca/fides/pull/4312)
 - Added a `FidesUIChanged` event to Fides.js to track when user preferences change without being saved [#4314](https://github.com/ethyca/fides/pull/4314) and [#4253](https://github.com/ethyca/fides/pull/4253)
 - Add AC Systems to the TCF Overlay under Vendor Consents section [#4266](https://github.com/ethyca/fides/pull/4266/)
@@ -67,10 +68,12 @@ The types of changes are:
 - Access and erasure support for Iterate [#4332](https://github.com/ethyca/fides/pull/4332)
 - SSH Support for MySQL connections [#4310](https://github.com/ethyca/fides/pull/4310)
 - Added served notice history IDs to the TCF privacy preference API calls [#4161](https://github.com/ethyca/fides/pull/4161)
 
 ### Fixed
+
+- Fix an HTML Injection vulnerability in DSR Packages
 - Cleans up CSS for fidesEmbed mode [#4306](https://github.com/ethyca/fides/pull/4306)
 - Stacks that do not have any purposes will no longer render an empty purpose block [#4278](https://github.com/ethyca/fides/pull/4278)
 - Forcing hidden sections to use display none [#4299](https://github.com/ethyca/fides/pull/4299)
 - Handles Hubspot requiring and email to be formatted as email when processing an erasure [#4322](https://github.com/ethyca/fides/pull/4322)
 - Minor CSS improvements for the consent/TCF banners and modals [#4334](https://github.com/ethyca/fides/pull/4334)
diff --git a/src/fides/api/service/privacy_request/dsr_package/dsr_report_builder.py b/src/fides/api/service/privacy_request/dsr_package/dsr_report_builder.py
index 3ba38d79a..682cfe39b 100644
--- a/src/fides/api/service/privacy_request/dsr_package/dsr_report_builder.py
+++ b/src/fides/api/service/privacy_request/dsr_package/dsr_report_builder.py
@@ -43,11 +43,13 @@ class DsrReportBuilder:
         # Jinja template environment initialization
         def pretty_print(value: str, indent: int = 4) -> str:
             return json.dumps(value, indent=indent, default=storage_json_encoder)
 
         jinja2.filters.FILTERS["pretty_print"] = pretty_print
-        self.template_loader = Environment(loader=FileSystemLoader(DSR_DIRECTORY))
+        self.template_loader = Environment(
+            loader=FileSystemLoader(DSR_DIRECTORY), autoescape=True
+        )
 
         # to pass in custom colors in the future
         self.template_data: Dict[str, Any] = {
             "text_color": TEXT_COLOR,
             "header_color": HEADER_COLOR,
@@ -73,11 +75,12 @@ class DsrReportBuilder:
             "data": data,
             "request": self.request_data,
         }
         report_data.update(self.template_data)
         template = self.template_loader.get_template(template_path)
-        return template.render(report_data)
+        rendered_template = template.render(report_data)
+        return rendered_template
 
     def _add_file(self, filename: str, contents: str) -> None:
         """Helper to add a file to the zip archive"""
         if filename and contents:
             self.out.writestr(f"{filename}", contents.encode("utf-8"))

Vulnerable code:         self.template_loader = Environment(loader=FileSystemLoader(DSR_DIRECTORY))
        return template.render(report_data)
Fixed code: 

- Fix an HTML Injection vulnerability in DSR Packages
        self.template_loader = Environment(
            loader=FileSystemLoader(DSR_DIRECTORY), autoescape=True
        )
        rendered_template = template.render(report_data)
        return rendered_template