From d7185be38c2d386c1826d7e0aefacf15828d7050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 26 Dec 2012 17:25:05 +0100 Subject: [PATCH 1/3] [IMP] html_sanitize: now uses the builtin cleaner of lxml.html. We also allows style attribute; the cleaner ensures no javascript or malicious code goes through those attributes. Updated and added tests for the sanitizer, especially about malicious code, and EDI-like html code. bzr revid: tde@openerp.com-20121226162505-8rq060p375z1k9il --- openerp/tests/test_mail.py | 115 +++++++++++++++++++++++++++++++++---- openerp/tools/mail.py | 74 +++++------------------- 2 files changed, 118 insertions(+), 71 deletions(-) diff --git a/openerp/tests/test_mail.py b/openerp/tests/test_mail.py index b3c11a13bfe..69f4b5f8bcc 100644 --- a/openerp/tests/test_mail.py +++ b/openerp/tests/test_mail.py @@ -43,6 +43,47 @@ test12

test link """ +EDI_LIKE_HTML_SOURCE = """
+

Hello ${object.partner_id.name},

+

A new invoice is available for you:

+

+   REFERENCES
+   Invoice number: ${object.number}
+   Invoice total: ${object.amount_total} ${object.currency_id.name}
+   Invoice date: ${object.date_invoice}
+   Order reference: ${object.origin}
+   Your contact: ${object.user_id.name} +

+
+

It is also possible to directly pay with Paypal:

+ + + +
+

If you have any question, do not hesitate to contact us.

+

Thank you for choosing ${object.company_id.name or 'us'}!

+
+
+
+

+ ${object.company_id.name}

+
+
+ + ${object.company_id.street}
+ ${object.company_id.street2}
+ ${object.company_id.zip} ${object.company_id.city}
+ ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}
+
+
+ Phone:  ${object.company_id.phone} +
+ +
+
""" + TEXT_MAIL1 = """I contact you about our meeting for tomorrow. Here is the schedule I propose: 9 AM: brainstorming about our new amazing business app 9.45 AM: summary @@ -126,23 +167,76 @@ bert.tartopoils@miam.miam class TestSanitizer(unittest2.TestCase): """ Test the html sanitizer that filters html to remove unwanted attributes """ - def test_simple(self): - x = "yop" - self.assertEqual(x, html_sanitize(x)) + def test_basic_sanitizer(self): + cases = [ + ("yop", "

yop

"), # simple + ("lala

yop

xxx", "

lala

yop

xxx
"), # trailing text + ("Merci à l'intérêt pour notre produit.nous vous contacterons bientôt. Merci", + u"

Merci à l'intérêt pour notre produit.nous vous contacterons bientôt. Merci

"), # unicode + ] + for content, expected in cases: + html = html_sanitize(content) + self.assertEqual(html, expected, 'html_sanitize is broken') - def test_trailing_text(self): - x = 'lala

yop

xxx' - self.assertEqual(x, html_sanitize(x)) + def test_evil_malicious_code(self): + cases = [ + (""), # no quotes and semicolons + (""), # UTF-8 Unicode encoding + (""), # hex encoding + (""), # embedded carriage return + (""), # embedded newline + (""), # embedded tab + (""), # embedded encoded tab + (""), # spaces and meta-characters + ("\">"), # malformed tag + (""), # non-alpha-non-digits + (""), # non-alpha-non-digits + ("<"), # extraneous open brackets + (" in test_mail) try: cleaner = clean.Cleaner(page_structure=True, style=False, safe_attrs_only=False, forms=False, kill_tags=tags_to_kill, remove_tags=tags_to_remove) cleaned = cleaner.clean_html(src) except: - cleaned = 'Impossible to parse' + _logger.debug('Failed to parse %s' % (src)) + cleaned = '

Impossible to parse

' return cleaned From 1c7b1b53d49fb48de3f3784e3a41e806ba35f135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 27 Dec 2012 10:26:14 +0100 Subject: [PATCH 3/3] [IMP] sanitizer: improved logger message if crashed during sanitize. bzr revid: tde@openerp.com-20121227092614-0ihi5sw5uuyboahk --- openerp/tools/mail.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/tools/mail.py b/openerp/tools/mail.py index e00d1fbda2e..10656e9797c 100644 --- a/openerp/tools/mail.py +++ b/openerp/tools/mail.py @@ -54,7 +54,7 @@ def html_sanitize(src): cleaner = clean.Cleaner(page_structure=True, style=False, safe_attrs_only=False, forms=False, kill_tags=tags_to_kill, remove_tags=tags_to_remove) cleaned = cleaner.clean_html(src) except: - _logger.debug('Failed to parse %s' % (src)) + _logger.warning('html_sanitize failed to parse %s' % (src)) cleaned = '

Impossible to parse

' return cleaned