From 7554842b1f3ae4497669d0ae2eb1e715e9125f91 Mon Sep 17 00:00:00 2001 From: zorun Date: Sun, 10 Oct 2021 18:39:03 +0200 Subject: [PATCH] Add URL validation to external link to prevent XSS (#846) Co-authored-by: Baptiste Jonglez --- ihatemoney/forms.py | 3 ++- ihatemoney/tests/budget_test.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/ihatemoney/forms.py b/ihatemoney/forms.py index fe1bdcc7..180619c7 100644 --- a/ihatemoney/forms.py +++ b/ihatemoney/forms.py @@ -13,6 +13,7 @@ from wtforms.fields.core import Label, SelectField, SelectMultipleField from wtforms.fields.html5 import DateField, DecimalField, URLField from wtforms.fields.simple import BooleanField, PasswordField, StringField, SubmitField from wtforms.validators import ( + URL, DataRequired, Email, EqualTo, @@ -292,7 +293,7 @@ class BillForm(FlaskForm): original_currency = SelectField(_("Currency"), validators=[DataRequired()]) external_link = URLField( _("External link"), - validators=[Optional()], + validators=[Optional(), URL()], description=_("A link to an external document, related to this bill"), ) payed_for = SelectMultipleField( diff --git a/ihatemoney/tests/budget_test.py b/ihatemoney/tests/budget_test.py index af33197a..1539ece7 100644 --- a/ihatemoney/tests/budget_test.py +++ b/ihatemoney/tests/budget_test.py @@ -675,6 +675,35 @@ class BudgetTestCase(IhatemoneyTestCase): bill = models.Bill.query.filter(models.Bill.date == "2011-08-01")[0] self.assertEqual(bill.amount, 25.02) + # add a bill with a valid external link + self.client.post( + "/raclette/add", + data={ + "date": "2015-05-05", + "what": "fromage à raclette", + "payer": members_ids[0], + "payed_for": members_ids, + "amount": "42", + "external_link": "https://example.com/fromage", + }, + ) + bill = models.Bill.query.filter(models.Bill.date == "2015-05-05")[0] + self.assertEqual(bill.external_link, "https://example.com/fromage") + + # add a bill with an invalid external link + resp = self.client.post( + "/raclette/add", + data={ + "date": "2015-05-06", + "what": "mauvais fromage à raclette", + "payer": members_ids[0], + "payed_for": members_ids, + "amount": "42000", + "external_link": "javascript:alert('Tu bluffes, Martoni.')", + }, + ) + self.assertIn("Invalid URL", resp.data.decode("utf-8")) + def test_weighted_balance(self): self.post_project("raclette")