Files
notifications-admin/app/main/validators.py
Leo Hemsted 5bbbdc3cd9 fix xss with service letter contact blocks
service contact blocks contain new lines - and jinja2 normally ignores
newlines (as in it keeps them as new lines) - but we need to turn them
into `<br>` tags so that we can show the formatting that the user has
added. We were previously just doing `{{ block | nl2br | safe }}`. nl2br
turns the new lines into `<br>` tags, and then `safe` tells jinja that
it doesn't need to escape the html.

this causes issues if the user adds `<script>alert(1)</script>` to their
contact block (or some other evil xss hack), where that will get let
through due to the safe flag

To solve this, use `Markup(html='escape')` to sanitise any html, and
then convert new lines to <br>.

bump utils

another xss
2020-01-21 17:34:49 +00:00

129 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import re
from notifications_utils.field import Field
from notifications_utils.formatters import formatted_list
from notifications_utils.recipients import (
InvalidEmailError,
validate_email_address,
)
from notifications_utils.sanitise_text import SanitiseSMS
from wtforms import ValidationError
from wtforms.validators import Email
from app.main._blacklisted_passwords import blacklisted_passwords
from app.utils import Spreadsheet, is_gov_user
class Blacklist:
def __init__(self, message=None):
if not message:
message = 'Password is blacklisted.'
self.message = message
def __call__(self, form, field):
if field.data in blacklisted_passwords:
raise ValidationError(self.message)
class CsvFileValidator:
def __init__(self, message='Not a csv file'):
self.message = message
def __call__(self, form, field):
if not Spreadsheet.can_handle(field.data.filename):
raise ValidationError("{} is not a spreadsheet that Notify can read".format(field.data.filename))
class ValidGovEmail:
def __call__(self, form, field):
if field.data == '':
return
from flask import url_for
message = (
'Enter a government email address.'
' If you think you should have access'
' <a href="{}">contact us</a>').format(url_for('main.support'))
if not is_gov_user(field.data.lower()):
raise ValidationError(message)
class ValidEmail(Email):
def __init__(self):
super().__init__('Enter a valid email address')
def __call__(self, form, field):
if field.data == '':
return
try:
validate_email_address(field.data)
except InvalidEmailError:
raise ValidationError(self.message)
return super().__call__(form, field)
class NoCommasInPlaceHolders:
def __init__(self, message='You cannot put commas between double brackets'):
self.message = message
def __call__(self, form, field):
if ',' in ''.join(Field(field.data).placeholders):
raise ValidationError(self.message)
class OnlySMSCharacters:
def __call__(self, form, field):
non_sms_characters = sorted(list(SanitiseSMS.get_non_compatible_characters(field.data)))
if non_sms_characters:
raise ValidationError(
'You cannot use {} in text messages. {} will not show up properly on everyones phones.'.format(
formatted_list(non_sms_characters, conjunction='or', before_each='', after_each=''),
('It' if len(non_sms_characters) == 1 else 'They')
)
)
class LettersNumbersAndFullStopsOnly:
regex = re.compile(r'^[a-zA-Z0-9\s\.]+$')
def __init__(self, message='Use letters and numbers only'):
self.message = message
def __call__(self, form, field):
if field.data and not re.match(self.regex, field.data):
raise ValidationError(self.message)
class DoesNotStartWithDoubleZero:
def __init__(self, message="Cannot start with 00"):
self.message = message
def __call__(self, form, field):
if field.data and field.data.startswith("00"):
raise ValidationError(self.message)
class MustContainAlphanumericCharacters:
regex = re.compile(r".*[a-zA-Z0-9].*[a-zA-Z0-9].*")
def __init__(
self,
message="Must include at least two alphanumeric characters"
):
self.message = message
def __call__(self, form, field):
if field.data and not re.match(self.regex, field.data):
raise ValidationError(self.message)