diff --git a/app/alias_utils.py b/app/alias_utils.py index 77bae501..d05d70ad 100644 --- a/app/alias_utils.py +++ b/app/alias_utils.py @@ -1,3 +1,4 @@ +import re from typing import Optional from sqlalchemy.exc import IntegrityError @@ -207,3 +208,14 @@ def nb_email_log_for_mailbox(mailbox: Mailbox): .filter(Contact.alias_id.in_(alias_ids)) .count() ) + + +# Only lowercase letters, numbers, dashes (-) and underscores (_) are currently supported +_ALIAS_PREFIX_PATTERN = r"[0-9a-z-_]{1,}" + + +def check_alias_prefix(alias_prefix) -> bool: + if re.fullmatch(_ALIAS_PREFIX_PATTERN, alias_prefix) is None: + return False + + return True diff --git a/app/api/views/new_custom_alias.py b/app/api/views/new_custom_alias.py index 244bc9a7..8f72d4b5 100644 --- a/app/api/views/new_custom_alias.py +++ b/app/api/views/new_custom_alias.py @@ -2,6 +2,7 @@ from flask import g from flask import jsonify, request from itsdangerous import SignatureExpired +from app.alias_utils import check_alias_prefix from app.api.base import api_bp, require_api_auth from app.api.serializer import ( serialize_alias_info, @@ -236,6 +237,9 @@ def new_custom_alias_v3(): name = data.get("name") alias_prefix = convert_to_id(alias_prefix) + if not check_alias_prefix(alias_prefix): + return jsonify(error="alias prefix format problem"), 400 + # check if mailbox is not tempered with mailboxes = [] for mailbox_id in mailbox_ids: diff --git a/app/dashboard/views/custom_alias.py b/app/dashboard/views/custom_alias.py index 5440297f..ab9bb4c1 100644 --- a/app/dashboard/views/custom_alias.py +++ b/app/dashboard/views/custom_alias.py @@ -5,6 +5,7 @@ from flask_login import login_required, current_user from itsdangerous import TimestampSigner, SignatureExpired from sqlalchemy.exc import IntegrityError +from app.alias_utils import check_alias_prefix from app.config import ( DISABLE_ALIAS_SUFFIX, CUSTOM_ALIAS_SECRET, @@ -122,6 +123,14 @@ def custom_alias(): mailbox_ids = request.form.getlist("mailboxes") alias_note = request.form.get("note") + if not check_alias_prefix(alias_prefix): + flash( + "Only lowercase letters, numbers, dashes (-) and underscores (_) " + "are currently supported for alias prefix", + "error", + ) + return redirect(url_for("dashboard.custom_alias")) + # check if mailbox is not tempered with mailboxes = [] for mailbox_id in mailbox_ids: diff --git a/app/oauth/views/authorize.py b/app/oauth/views/authorize.py index 79435428..988856a3 100644 --- a/app/oauth/views/authorize.py +++ b/app/oauth/views/authorize.py @@ -5,6 +5,7 @@ from flask import request, render_template, redirect, flash from flask_login import current_user from itsdangerous import SignatureExpired +from app.alias_utils import check_alias_prefix from app.config import EMAIL_DOMAIN from app.dashboard.views.custom_alias import available_suffixes, signer from app.extensions import db @@ -154,6 +155,14 @@ def authorize(): alias_prefix = alias_prefix.strip().lower().replace(" ", "") + if not check_alias_prefix(alias_prefix): + flash( + "Only lowercase letters, numbers, dashes (-) and underscores (_) " + "are currently supported for alias prefix", + "error", + ) + return redirect(request.url) + # hypothesis: user will click on the button in the 600 secs try: alias_suffix = signer.unsign(signed_suffix, max_age=600).decode() diff --git a/tests/test_alias_utils.py b/tests/test_alias_utils.py index ae684617..6ee883e6 100644 --- a/tests/test_alias_utils.py +++ b/tests/test_alias_utils.py @@ -1,4 +1,4 @@ -from app.alias_utils import delete_alias +from app.alias_utils import delete_alias, check_alias_prefix from app.extensions import db from app.models import User, Alias, DeletedAlias @@ -46,3 +46,11 @@ def test_delete_alias_already_in_trash(flask_client): delete_alias(alias, user) assert Alias.get_by(email="first@d1.test") is None + + +def test_check_alias_prefix(flask_client): + assert check_alias_prefix("ab-cd_") + assert not check_alias_prefix("") + assert not check_alias_prefix("éè") + assert not check_alias_prefix("a b") + assert not check_alias_prefix("+👌")