From 56a53e907925a8afa1108bf603eb253d529e9fdc Mon Sep 17 00:00:00 2001
From: "Merel Geens (mege)" <mege@odoo.com>
Date: Fri, 4 Aug 2023 08:49:52 +0000
Subject: [PATCH] [IMP] odoo: prevent unsafe import from file

It's possible to specify an existing module as the xml id prefix when
importing records from a file. This will result in `ir_module_data`
records being created with `noupdate` set to False. When the module is
upgraded, these records will be deleted.

This can lead to undesired side effects like journal items for
accounts imported this way being deleted.

This change prevents creating new records linked to existing modules
when importing from a file. Instead, the user should either use no
prefix or the name of a non-existent module, like `__import__`.

opw-3231987

closes odoo/odoo#130825

Signed-off-by: Merel Geens <mege@odoo.com>
---
 odoo/models.py | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/odoo/models.py b/odoo/models.py
index 76248db22c3d..6dbdc1827df3 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -1071,6 +1071,10 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
                     # Failed to write, log to messages, rollback savepoint (to
                     # avoid broken transaction) and keep going
                     errors += 1
+                except UserError as e:
+                    info = rec_data['info']
+                    messages.append(dict(info, type='error', message=str(e)))
+                    errors += 1
                 except Exception as e:
                     _logger.debug("Error while loading record", exc_info=True)
                     info = rec_data['info']
@@ -4240,6 +4244,17 @@ Fields:
                 if data.get('xml_id') and not data['xml_id'].startswith(prefix):
                     _logger.warning("Creating record %s in module %s.", data['xml_id'], module)
 
+        if self.env.context.get('import_file'):
+            existing_modules = self.env['ir.module.module'].search([]).mapped('name')
+            for data in to_create:
+                xml_id = data.get('xml_id')
+                if xml_id:
+                    module_name, sep, record_id = xml_id.partition('.')
+                    if sep and module_name in existing_modules:
+                        raise UserError(
+                            _("The record %(xml_id)s has the module prefix %(module_name)s. This is the part before the '.' in the external id. Because the prefix refers to an existing module, the record would be deleted when the module is upgraded. Use either no prefix and no dot or a prefix that isn't an existing module. For example, __import__, resulting in the external id __import__.%(record_id)s.",
+                              xml_id=xml_id, module_name=module_name, record_id=record_id))
+
         # create records
         records = self._load_records_create([data['values'] for data in to_create])
         for data, record in zip(to_create, records):
-- 
GitLab