CVE-2022-3457: Origin Validation Error (CWE-346)
value: Origin Validation Error in GitHub repository ikus060/rdiffweb prior to 2.5.0a5.
CWE description: The product does not properly verify that the source of data or communication is valid.
CVSS v3 base score: 9.8
Published: 2022-10-13T20:15Z
Repository: https://github.com/ikus060/rdiffweb
Language: Python
Files changed: README.md, rdiffweb/controller/tests/test_secure_headers.py, rdiffweb/tools/secure_headers.py
Commit date: 2022-10-11 17:21:04 -0400
Commit message: Enforce 'Origin' validation

Diff: diff --git a/README.md b/README.md
index 68558217d..75cfbd712 100644
--- a/README.md
+++ b/README.md
@@ -133,10 +133,11 @@ This next release focus on two-factor-authentication as a measure to increase se
 * Enforce permission on /etc/rdiffweb configuration folder
 * Enforce validation on fullname, username and email
 * Limit incorrect attempts to change the user's password to prevent brute force attacks #225 [CVE-2022-3273](https://nvd.nist.gov/vuln/detail/CVE-2022-3273)
 * Enforce password policy new password cannot be set as new password [CVE-2022-3376](https://nvd.nist.gov/vuln/detail/CVE-2022-3376)
 * Enforce better rate limit on login, mfa, password change and API [CVE-2022-3439](https://nvd.nist.gov/vuln/detail/CVE-2022-3439) [CVE-2022-3456](https://nvd.nist.gov/vuln/detail/CVE-2022-3456)
+* Enforce 'Origin' validation [CVE-2022-3457](https://nvd.nist.gov/vuln/detail/CVE-2022-3457)
 
 Breaking changes:
 
 * Drop Ubuntu Hirsute & Impish (End-of-life)
 * `session-dir` is deprecated and should be replace by `rate-limit-dir`. User's session are stored in database.
diff --git a/rdiffweb/controller/tests/test_secure_headers.py b/rdiffweb/controller/tests/test_secure_headers.py
index e0b2c3dcf..1d2c5dc4e 100644
--- a/rdiffweb/controller/tests/test_secure_headers.py
+++ b/rdiffweb/controller/tests/test_secure_headers.py
@@ -91,10 +91,19 @@ class SecureHeadersTest(rdiffweb.test.WebCase):
         self.getPage('/', headers=[('Origin', 'http://www.examples.com')], method='POST')
         # Then the request is refused with 403 Forbiden
         self.assertStatus(403)
         self.assertInBody('Unexpected Origin header')
 
+    def test_post_with_prefixed_origin(self):
+        # Given a POST request made to rdiffweb
+        # When the request is made using a different origin
+        base = 'http://%s:%s' % (self.HOST + 'anything.com', self.PORT)
+        self.getPage('/dashboard/', headers=[('Origin', base)], method='POST')
+        # Then the request is accepted with 200 OK
+        self.assertStatus(403)
+        self.assertInBody('Unexpected Origin header')
+
     def test_post_with_valid_origin(self):
         # Given a POST request made to rdiffweb
         # When the request is made using a different origin
         base = 'http://%s:%s' % (self.HOST, self.PORT)
         self.getPage('/', headers=[('Origin', base)], method='POST')
diff --git a/rdiffweb/tools/secure_headers.py b/rdiffweb/tools/secure_headers.py
index 48ba1847b..74ee72039 100644
--- a/rdiffweb/tools/secure_headers.py
+++ b/rdiffweb/tools/secure_headers.py
@@ -57,11 +57,11 @@ def set_headers(
     response = cherrypy.serving.response
 
     # Check if Origin matches our target.
     if request.method in ['POST', 'PUT', 'PATCH', 'DELETE']:
         origin = request.headers.get('Origin', None)
-        if origin and not origin.startswith(request.base):
+        if origin and origin != request.base:
             raise cherrypy.HTTPError(403, 'Unexpected Origin header')
 
     # Check if https is enabled
     https = request.base.startswith('https')
 

Vulnerable code:         if origin and not origin.startswith(request.base):
Fixed code: * Enforce 'Origin' validation [CVE-2022-3457](https://nvd.nist.gov/vuln/detail/CVE-2022-3457)
    def test_post_with_prefixed_origin(self):
        # Given a POST request made to rdiffweb
        # When the request is made using a different origin
        base = 'http://%s:%s' % (self.HOST + 'anything.com', self.PORT)
        self.getPage('/dashboard/', headers=[('Origin', base)], method='POST')
        # Then the request is accepted with 200 OK
        self.assertStatus(403)
        self.assertInBody('Unexpected Origin header')

        if origin and origin != request.base: