diff roundup/rest.py @ 7155:89a59e46b3af

improve REST interface security When using REST, we reflect the client's origin. If the wildcard '*' is used in allowed_api_origins all origins are allowed. When this is done, it also added an 'Access-Control-Allow-Credentials: true' header. This Credentials header should not be added if the site is matched only by '*'. This header should be provided only for explicit origins (e.g. https://example.org) not for the wildcard. This is now fixed for CORS preflight OPTIONS request as well as normal GET, PUT, DELETE, POST, PATCH and OPTIONS requests. A missing Access-Control-Allow-Credentials will prevent the tracker from being accessed using credentials. This prevents an unauthorized third party web site from using a user's credentials to access information in the tracker that is not publicly available. Added test for this specific case. In addition, allowed_api_origins can include explicit origins in addition to '*'. '*' must be first in the list. Also adapted numerous tests to work with these changes. Doc updates.
author John Rouillard <rouilj@ieee.org>
date Thu, 23 Feb 2023 12:01:33 -0500
parents 626ef84579a3
children 6f09103a6522
line wrap: on
line diff
--- a/roundup/rest.py	Tue Feb 21 23:06:15 2023 -0500
+++ b/roundup/rest.py	Thu Feb 23 12:01:33 2023 -0500
@@ -2201,11 +2201,24 @@
             self.client.request.headers.get("Origin")
         )
 
-        # allow credentials
-        self.client.setHeader(
-            "Access-Control-Allow-Credentials",
-            "true"
-        )
+        # Allow credentials if origin is acceptable.
+        #
+        # If Access-Control-Allow-Credentials header not returned,
+        # but the client request is made with credentials
+        # data will be sent but not made available to the
+        # calling javascript in browser.
+        # Prevents exposure of data to an invalid origin when
+        # credentials are sent by client.
+        #
+        # If admin puts * first in allowed_api_origins
+        # we do not allow credentials but do reflect the origin.
+        # This allows anonymous access.
+        if self.client.is_origin_header_ok(api=True, credentials=True):
+            self.client.setHeader(
+                "Access-Control-Allow-Credentials",
+                "true"
+            )
+
         # set allow header in case of error. 405 handlers below should
         # replace it with a custom version as will OPTIONS handler
         # doing CORS.

Roundup Issue Tracker: http://roundup-tracker.org/