CVE-2023-27494: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Streamlit, software for turning data scripts into web applications, had a cross-site scripting (XSS) vulnerability in versions 0.63.0 through 0.80.0. Users of hosted Streamlit app(s) were vulnerable to a reflected XSS vulnerability. An attacker could craft a malicious URL with Javascript payloads to a Streamlit app. The attacker could then trick the user into visiting the malicious URL and, if successful, the server would render the malicious javascript payload as-is, leading to XSS. Version 0.81.0 contains a patch for 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-03-16T21:15Z
Repository: https://github.com/streamlit/streamlit
Language: Python
Files changed: lib/streamlit/components/v1/components.py, lib/streamlit/server/routes.py, lib/tests/streamlit/components_test.py
Commit date: 2021-04-21 17:25:32 -0700
Commit message: Remove path from 404 response (#3165)

* Remove path from 404 response

* Remove exception output
Diff: diff --git a/lib/streamlit/components/v1/components.py b/lib/streamlit/components/v1/components.py
index c6a88fd8..9787024f 100644
--- a/lib/streamlit/components/v1/components.py
+++ b/lib/streamlit/components/v1/components.py
@@ -312,11 +312,11 @@ class ComponentRequestHandler(tornado.web.RequestHandler):
     def get(self, path: str) -> None:
         parts = path.split("/")
         component_name = parts[0]
         component_root = self._registry.get_component_path(component_name)
         if component_root is None:
-            self.write(f"{path} not found")
+            self.write("not found")
             self.set_status(404)
             return
 
         filename = "/".join(parts[1:])
         abspath = os.path.join(component_root, filename)
@@ -325,11 +325,12 @@ class ComponentRequestHandler(tornado.web.RequestHandler):
 
         try:
             with open(abspath, "r", encoding="utf-8") as file:
                 contents = file.read()
         except (OSError, UnicodeDecodeError) as e:
-            self.write(f"{path} read error: {e}")
+            LOGGER.error(f"ComponentRequestHandler: GET {path} read error", exc_info=e)
+            self.write("read error")
             self.set_status(404)
             return
 
         self.write(contents)
         self.set_header("Content-Type", self.get_content_type(abspath))
diff --git a/lib/streamlit/server/routes.py b/lib/streamlit/server/routes.py
index e79b0cc3..44e83e51 100644
--- a/lib/streamlit/server/routes.py
+++ b/lib/streamlit/server/routes.py
@@ -82,11 +82,11 @@ class MediaFileHandler(tornado.web.StaticFileHandler):
     def validate_absolute_path(self, root, absolute_path):
         try:
             media_file_manager.get(absolute_path)
         except KeyError:
             LOGGER.error("MediaFileManager: Missing file %s" % absolute_path)
-            raise tornado.web.HTTPError(404, "%s not found", absolute_path)
+            raise tornado.web.HTTPError(404, "not found")
 
         return absolute_path
 
     def get_content_size(self):
         media = media_file_manager.get(self.absolute_path)
diff --git a/lib/tests/streamlit/components_test.py b/lib/tests/streamlit/components_test.py
index aee156d2..04eb7820 100644
--- a/lib/tests/streamlit/components_test.py
+++ b/lib/tests/streamlit/components_test.py
@@ -409,11 +409,11 @@ class ComponentRequestHandlerTest(tornado.testing.AsyncHTTPTestCase):
     def test_invalid_component_request(self):
         """Test request failure when invalid component name is provided."""
 
         response = self._request_component("invalid_component")
         self.assertEqual(404, response.code)
-        self.assertEqual(b"invalid_component not found", response.body)
+        self.assertEqual(b"not found", response.body)
 
     def test_invalid_content_request(self):
         """Test request failure when invalid content (file) is provided."""
 
         with mock.patch("streamlit.components.v1.components.os.path.isdir"):
@@ -423,11 +423,11 @@ class ComponentRequestHandlerTest(tornado.testing.AsyncHTTPTestCase):
             m.side_effect = OSError("Invalid content")
             response = self._request_component("components_test.test")
 
         self.assertEqual(404, response.code)
         self.assertEqual(
-            b"components_test.test read error: Invalid content",
+            b"read error",
             response.body,
         )
 
     def test_invalid_encoding_request(self):
         """Test request failure when invalid encoded file is provided."""
@@ -441,11 +441,11 @@ class ComponentRequestHandlerTest(tornado.testing.AsyncHTTPTestCase):
             )
             response = self._request_component("components_test.test")
 
         self.assertEqual(404, response.code)
         self.assertEqual(
-            b"components_test.test read error: 'utf-8' codec can't decode bytes in position 9-10: unexpected end of data",
+            b"read error",
             response.body,
         )
 
 
 class IFrameTest(testutil.DeltaGeneratorTestCase):

Vulnerable code:             self.write(f"{path} not found")
            self.write(f"{path} read error: {e}")
            raise tornado.web.HTTPError(404, "%s not found", absolute_path)
        self.assertEqual(b"invalid_component not found", response.body)
            b"components_test.test read error: Invalid content",
            b"components_test.test read error: 'utf-8' codec can't decode bytes in position 9-10: unexpected end of data",
Fixed code:             self.write("not found")
            LOGGER.error(f"ComponentRequestHandler: GET {path} read error", exc_info=e)
            self.write("read error")
            raise tornado.web.HTTPError(404, "not found")
        self.assertEqual(b"not found", response.body)
            b"read error",
            b"read error",