From 6f072b42e8debf34ff726c797b8206a3c45d4f4d Mon Sep 17 00:00:00 2001 From: dgtlmoon Date: Fri, 5 Aug 2022 00:05:43 +0200 Subject: [PATCH] Security update - Password could be unset from settings form unexpectedly (#808) --- changedetectionio/__init__.py | 9 ++++- .../tests/test_access_control.py | 36 ++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/changedetectionio/__init__.py b/changedetectionio/__init__.py index c2fe2b90..3b40bf2a 100644 --- a/changedetectionio/__init__.py +++ b/changedetectionio/__init__.py @@ -703,7 +703,14 @@ def changedetection_app(config=None, datastore_o=None): return redirect(url_for('settings_page')) if form.validate(): - datastore.data['settings']['application'].update(form.data['application']) + # Don't set password to False when a password is set - should be only removed with the `removepassword` button + app_update = dict(deepcopy(form.data['application'])) + + # Never update password with '' or False (Added by wtforms when not in submission) + if 'password' in app_update and not app_update['password']: + del (app_update['password']) + + datastore.data['settings']['application'].update(app_update) datastore.data['settings']['requests'].update(form.data['requests']) if not os.getenv("SALTED_PASS", False) and len(form.application.form.password.encrypted_password): diff --git a/changedetectionio/tests/test_access_control.py b/changedetectionio/tests/test_access_control.py index 8b36923e..bb109982 100644 --- a/changedetectionio/tests/test_access_control.py +++ b/changedetectionio/tests/test_access_control.py @@ -19,7 +19,6 @@ def test_check_access_control(app, client): ) assert b"Password protection enabled." in res.data - assert b"LOG OUT" not in res.data # Check we hit the login res = c.get(url_for("index"), follow_redirects=True) @@ -38,7 +37,42 @@ def test_check_access_control(app, client): follow_redirects=True ) + # Yes we are correctly logged in assert b"LOG OUT" in res.data + + # 598 - Password should be set and not accidently removed + res = c.post( + url_for("settings_page"), + data={ + "requests-time_between_check-minutes": 180, + 'application-fetch_backend': "html_requests"}, + follow_redirects=True + ) + + res = c.get(url_for("logout"), + follow_redirects=True) + + res = c.get(url_for("settings_page"), + follow_redirects=True) + + + assert b"Login" in res.data + + res = c.get(url_for("login")) + assert b"Login" in res.data + + + res = c.post( + url_for("login"), + data={"password": "foobar"}, + follow_redirects=True + ) + + # Yes we are correctly logged in + assert b"LOG OUT" in res.data + return + + res = c.get(url_for("settings_page")) # Menu should be available now