From 4e110638f09f2d2acf16d3d727a98fdd11d8446a Mon Sep 17 00:00:00 2001 From: bram1000 Date: Wed, 31 Jan 2024 16:20:35 +0100 Subject: [PATCH] [FIX] website: HTML-escape submitted form fields When fields are submitted through the website form, their values are used as they are. Because of this it is possible to include HTML in the sent email while this is not desired. To avoid this, this commit HTML-encodes the values received for custom fields and html fields. Steps to reproduce (with default_field): - Go to the "Contact us" page with form untouched (it should send mail) - Fill in the form - In the name put John Smith - Submit the form - You will see that Smith will be in bold in the received mail Steps to reproduce (no default_field): - Install website_recruitment - Go to the "Contact us" page - Enter edit mode - Change the form type to apply for a job (and select a job to apply in the right panel option, like "Consultant") - In debug mode in the backend, go to ir.model fields - Find "Applicant (hr.applicant) record and edit it - Remove the website_form_default_field_id in the "Website Forms" tab of the form view of this record - Back to the "contactus page", add a new custom field to the form - Now, out of edit mode, add "Something" in the custom field and submit the form - Find the job application in the backend in the recruitment module, it should be inside the "Consultant" job. - You will see the "Something" in bold in the chatter Note: In Odoo 16.2, commit [1] is already doing something similar for one of the 2 places fixed here. [1]: https://github.com/odoo/odoo/commit/3e7acff8d9302c3332fe3011f75374170484c61d task-3650953 closes odoo/odoo#152170 X-original-commit: c2e934f421a8afee4ce537b1e03871a1bcef99d1 Signed-off-by: Romain Derie (rde) Signed-off-by: Bram Van Gaal (brvg) Co-authored-by: bram1000 Co-authored-by: Benoit Socias --- addons/website/controllers/form.py | 3 +-- .../website/tests/test_website_form_editor.py | 25 +++++++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/addons/website/controllers/form.py b/addons/website/controllers/form.py index a2d1a00212b..00f6ed05b44 100644 --- a/addons/website/controllers/form.py +++ b/addons/website/controllers/form.py @@ -232,7 +232,6 @@ class WebsiteForm(http.Controller): record = request.env[model_name].with_user(SUPERUSER_ID).with_context( mail_create_nosubscribe=True, ).create(values) - if custom or meta: _custom_label = "%s\n___________\n\n" % _("Other Information:") # Title for custom fields if model_name == 'mail.mail': @@ -247,7 +246,7 @@ class WebsiteForm(http.Controller): # If there isn't, put the custom data in a message instead if default_field.name: if default_field.ttype == 'html' or model_name == 'mail.mail': - custom_content = nl2br(custom_content) + custom_content = nl2br_enclose(custom_content) record.update({default_field.name: custom_content}) elif hasattr(record, '_message_log'): record._message_log( diff --git a/addons/website/tests/test_website_form_editor.py b/addons/website/tests/test_website_form_editor.py index b807e0b1b62..2df90e51856 100644 --- a/addons/website/tests/test_website_form_editor.py +++ b/addons/website/tests/test_website_form_editor.py @@ -1,11 +1,14 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. # -*- coding: utf-8 -*- -import odoo.tests +from odoo.http import request from odoo.addons.base.tests.common import HttpCaseWithUserPortal +from odoo.addons.website.controllers.form import WebsiteForm +from odoo.addons.website.tools import MockRequest +from odoo.tests.common import tagged, TransactionCase -@odoo.tests.tagged('post_install', '-at_install') +@tagged('post_install', '-at_install') class TestWebsiteFormEditor(HttpCaseWithUserPortal): @classmethod def setUpClass(cls): @@ -50,3 +53,21 @@ class TestWebsiteFormEditor(HttpCaseWithUserPortal): self.start_tour('/contactus', 'website_form_contactus_change_random_option', login="admin") self.env.company.email = 'after.change@mail.com' self.start_tour('/contactus', 'website_form_contactus_check_changed_email', login="portal") + + +@tagged('post_install', '-at_install') +class TestWebsiteForm(TransactionCase): + + def test_website_form_html_escaping(self): + website = self.env['website'].browse(1) + WebsiteFormController = WebsiteForm() + with MockRequest(self.env, website=website): + WebsiteFormController.insert_record( + request, + self.env['ir.model'].search([('model', '=', 'mail.mail')]), + {'email_from': 'odoobot@example.com', 'subject': 'John Smith', 'email_to': 'company@company.company'}, + "John Smith", + ) + mail = self.env['mail.mail'].search([], order='id desc', limit=1) + self.assertNotIn('', mail.body_html, "HTML should be escaped in website form") + self.assertIn('<b>', mail.body_html, "HTML should be escaped in website form (2)")