diff --git a/api_views/users.py b/api_views/users.py index 172540a..a9d5091 100644 --- a/api_views/users.py +++ b/api_views/users.py @@ -1,4 +1,4 @@ -import re +from email.utils import parseaddr import jsonschema import jwt @@ -140,40 +140,21 @@ def update_email(username): return Response(error_message_helper(resp), 401, mimetype="application/json") else: user = User.query.filter_by(username=resp['sub']).first() - if vuln: # Regex DoS - match = re.search( - r"^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@{1}([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$", - str(request_data.get('email'))) - if match: - user.email = request_data.get('email') - db.session.commit() - responseObject = { - 'status': 'success', - 'data': { - 'username': user.username, - 'email': user.email - } - } - return Response(json.dumps(responseObject), 204, mimetype="application/json") - else: - return Response(error_message_helper("Please Provide a valid email address."), 400, - mimetype="application/json") - else: - regex = '^[a-z0-9]+[\._]?[a-z0-9]+[@]\w+[.]\w{2,3}$' - if (re.search(regex, request_data.get('email'))): - user.email = request_data.get('email') - db.session.commit() - responseObject = { - 'status': 'success', - 'data': { - 'username': user.username, - 'email': user.email - } - } - return Response(json.dumps(responseObject), 204, mimetype="application/json") - else: - return Response(error_message_helper("Please Provide a valid email address."), 400, - mimetype="application/json") + email = str(request_data.get('email', '')) + parsed = parseaddr(email)[1] + if len(email) > 254 or parsed != email or '@' not in email or '.' not in email.rsplit('@', 1)[-1]: + return Response(error_message_helper("Please Provide a valid email address."), 400, + mimetype="application/json") + user.email = email + db.session.commit() + responseObject = { + 'status': 'success', + 'data': { + 'username': user.username, + 'email': user.email + } + } + return Response(json.dumps(responseObject), 204, mimetype="application/json") def update_password(username): diff --git a/tests/test_regex_dos.py b/tests/test_regex_dos.py new file mode 100644 index 0000000..dd79c4a --- /dev/null +++ b/tests/test_regex_dos.py @@ -0,0 +1,9 @@ +from pathlib import Path + + +def test_email_update_uses_bounded_validation(): + source = Path("api_views/users.py").read_text() + section = source[source.index("def update_email"):source.index("def update_password")] + assert "parseaddr" in section + assert "len(email) > 254" in section + assert "re.search" not in section