From f0e6224a2b6f557d7783a99a7612d78bb99ba5ee Mon Sep 17 00:00:00 2001 From: Stephen Abello Date: Wed, 25 Feb 2026 11:38:34 +0100 Subject: [PATCH 1/9] =?UTF-8?q?N=C2=B06977=20-=20Sanitize=20Excel=20formul?= =?UTF-8?q?as=20in=20export=20in=20the=20backoffice?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/csvbulkexport.class.inc.php | 22 ++- core/excelbulkexport.class.inc.php | 14 +- css/backoffice/application/bulk/_all.scss | 1 + .../application/bulk/_bulk-export.scss | 10 ++ .../bulk/cs.dictionary.itop.bulk.php | 3 + .../bulk/da.dictionary.itop.bulk.php | 3 + .../bulk/de.dictionary.itop.bulk.php | 3 + .../bulk/en.dictionary.itop.bulk.php | 3 + .../bulk/en_gb.dictionary.itop.bulk.php | 3 + .../bulk/es_cr.dictionary.itop.bulk.php | 3 + .../bulk/fr.dictionary.itop.bulk.php | 3 + .../bulk/hu.dictionary.itop.bulk.php | 3 + .../bulk/it.dictionary.itop.bulk.php | 3 + .../bulk/ja.dictionary.itop.bulk.php | 3 + .../bulk/nl.dictionary.itop.bulk.php | 3 + .../bulk/pl.dictionary.itop.bulk.php | 3 + .../bulk/pt_br.dictionary.itop.bulk.php | 3 + .../bulk/ru.dictionary.itop.bulk.php | 3 + .../bulk/sk.dictionary.itop.bulk.php | 3 + .../bulk/tr.dictionary.itop.bulk.php | 3 + .../bulk/zh_cn.dictionary.itop.bulk.php | 3 + js/utils.js | 6 + sources/Application/Helper/ExportHelper.php | 81 ++++++++- .../unitary-tests/core/BulkExportTest.php | 169 ++++++++++++++++++ 24 files changed, 350 insertions(+), 4 deletions(-) create mode 100644 css/backoffice/application/bulk/_bulk-export.scss diff --git a/core/csvbulkexport.class.inc.php b/core/csvbulkexport.class.inc.php index bc0d957ace..42b3a7ddb4 100644 --- a/core/csvbulkexport.class.inc.php +++ b/core/csvbulkexport.class.inc.php @@ -5,6 +5,7 @@ * @license http://opensource.org/licenses/AGPL-3.0 */ +use Combodo\iTop\Application\Helper\ExportHelper; use Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory; use Combodo\iTop\Application\UI\Base\Component\Html\Html; use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory; @@ -13,7 +14,6 @@ use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory; use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\Column\ColumnUIBlockFactory; use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\MultiColumnUIBlockFactory; -use Combodo\iTop\Application\Helper\ExportHelper; use Combodo\iTop\Application\WebPage\Page; use Combodo\iTop\Application\WebPage\WebPage; @@ -55,6 +55,8 @@ public function ReadParameters() $this->aStatusInfo['charset'] = strtoupper(utils::ReadParam('charset', 'UTF-8', true, 'raw_data')); $this->aStatusInfo['formatted_text'] = (bool)utils::ReadParam('formatted_text', 0, true); + $this->aStatusInfo['ignore_excel_sanitization'] = (bool)utils::ReadParam('ignore_excel_sanitization', 0, true, utils::ENUM_SANITIZATION_FILTER_INTEGER); + $sDateFormatRadio = utils::ReadParam('csv_date_format_radio', ''); switch ($sDateFormatRadio) { case 'default': @@ -223,6 +225,10 @@ public function GetFormPart(WebPage $oP, $sPartId) $oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetDate->AddSubBlock($oRadioCustom); + $oFieldSetSecurity = FieldSetUIBlockFactory::MakeStandard(Dict::S('Core:BulkExport:Security')); + $oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oFieldSetSecurity)); + $oFieldSetSecurity->AddSubBlock(ExportHelper::GetInputForSanitizeExcelExport()); + $oP->add_ready_script( <<GetAsCSV($sAttCode), '"'); } - return $sRet; + + // If the option to ignore Excel sanitization is set, return the raw value without sanitization + if (array_key_exists('ignore_excel_sanitization', $this->aStatusInfo) && $this->aStatusInfo['ignore_excel_sanitization'] === true) { + return $sRet; + } + + return ExportHelper::SanitizeField($sRet, $this->aStatusInfo['text_qualifier'] ?? ''); } public function GetHeader() @@ -337,6 +349,12 @@ public function GetNextChunk(&$aStatus) $sField = $oObj->GetAsCSV($sAttCode, $this->aStatusInfo['separator'], $this->aStatusInfo['text_qualifier'], $this->bLocalizeOutput, !$this->aStatusInfo['formatted_text']); } } + + // If the option to ignore Excel sanitization is not set or absent, sanitize the field + if (!(array_key_exists('ignore_excel_sanitization', $this->aStatusInfo)) || $this->aStatusInfo['ignore_excel_sanitization'] === false) { + $sField = ExportHelper::SanitizeField($sField, $this->aStatusInfo['text_qualifier']); + } + if ($this->aStatusInfo['charset'] != 'UTF-8') { // Note: due to bugs in the glibc library it's safer to call iconv on the smallest possible string // and thus to convert field by field and not the whole row or file at once (see ticket N°991) diff --git a/core/excelbulkexport.class.inc.php b/core/excelbulkexport.class.inc.php index 6f46329624..8cf9be44e1 100644 --- a/core/excelbulkexport.class.inc.php +++ b/core/excelbulkexport.class.inc.php @@ -5,13 +5,13 @@ * @license http://opensource.org/licenses/AGPL-3.0 */ +use Combodo\iTop\Application\Helper\ExportHelper; use Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory; use Combodo\iTop\Application\UI\Base\Component\Html\Html; use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory; use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory; use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\Column\ColumnUIBlockFactory; use Combodo\iTop\Application\UI\Base\Layout\MultiColumn\MultiColumnUIBlockFactory; -use Combodo\iTop\Application\Helper\ExportHelper; use Combodo\iTop\Application\WebPage\Page; use Combodo\iTop\Application\WebPage\WebPage; @@ -63,6 +63,8 @@ public function ReadParameters() // Export from the command line (or scripted) => default format is SQL, as in previous versions of iTop, unless specified otherwise $this->aStatusInfo['date_format'] = utils::ReadParam('date_format', (string)AttributeDateTime::GetSQLFormat(), true, 'raw_data'); } + + $this->aStatusInfo['ignore_excel_sanitization'] = (bool)utils::ReadParam('ignore_excel_sanitization', 0, true, utils::ENUM_SANITIZATION_FILTER_INTEGER); } public function EnumFormParts() @@ -121,6 +123,10 @@ public function GetFormPart(WebPage $oP, $sPartId) $oRadioCustom->GetInput()->AddCSSClass('ibo-input-checkbox'); $oFieldSetDate->AddSubBlock($oRadioCustom); + $oFieldSetSecurity = FieldSetUIBlockFactory::MakeStandard(Dict::S('Core:BulkExport:Security')); + $oMulticolumn->AddColumn(ColumnUIBlockFactory::MakeForBlock($oFieldSetSecurity)); + $oFieldSetSecurity->AddSubBlock(ExportHelper::GetInputForSanitizeExcelExport()); + $oP->add_ready_script( <<aStatusInfo)) || $this->aStatusInfo['ignore_excel_sanitization'] === false) { + return ExportHelper::SanitizeField($sRet, ''); + } + return $sRet; } diff --git a/css/backoffice/application/bulk/_all.scss b/css/backoffice/application/bulk/_all.scss index 495ed376fb..fcd615d409 100644 --- a/css/backoffice/application/bulk/_all.scss +++ b/css/backoffice/application/bulk/_all.scss @@ -4,3 +4,4 @@ */ @import "bulk-modify"; +@import "bulk-export"; diff --git a/css/backoffice/application/bulk/_bulk-export.scss b/css/backoffice/application/bulk/_bulk-export.scss new file mode 100644 index 0000000000..b595b6c827 --- /dev/null +++ b/css/backoffice/application/bulk/_bulk-export.scss @@ -0,0 +1,10 @@ +/* + * @copyright Copyright (C) 2010-2026 Combodo SAS + * @license http://opensource.org/licenses/AGPL-3.0 + */ + +#form_part_csv_options:has(#ibo-sanitize-excel-export--input:checked), #form_part_xlsx_options:has(#ibo-sanitize-excel-export--input:checked){ + #ibo-sanitize-excel-export--alert { + display: none; + } +} \ No newline at end of file diff --git a/dictionaries/ui/application/bulk/cs.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/cs.dictionary.itop.bulk.php index 4ec8fba4b5..9c2de0b108 100644 --- a/dictionaries/ui/application/bulk/cs.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/cs.dictionary.itop.bulk.php @@ -14,4 +14,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', + 'Core:BulkExport:Security' => 'Security~~', ]); diff --git a/dictionaries/ui/application/bulk/da.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/da.dictionary.itop.bulk.php index 19f984f7d7..959b04c3b8 100644 --- a/dictionaries/ui/application/bulk/da.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/da.dictionary.itop.bulk.php @@ -14,4 +14,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', + 'Core:BulkExport:Security' => 'Security~~', ]); diff --git a/dictionaries/ui/application/bulk/de.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/de.dictionary.itop.bulk.php index 2aa593d274..3340c4f7f5 100644 --- a/dictionaries/ui/application/bulk/de.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/de.dictionary.itop.bulk.php @@ -14,4 +14,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'Dieses Attribut kann in einer Massenänderung nicht bearbeitet werden.', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel-Sicherheitswarnung', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Das Öffnen einer Datei mit nicht vertrauenswürdigen Daten in Microsoft Excel kann zu einer Formel-Injektion führen. Stellen Sie sicher, dass Ihre Excel-Einstellungen so konfiguriert sind, dass Dateien sicher verarbeitet werden. Erfahren Sie mehr in unserer Dokumentation.', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', + 'Core:BulkExport:Security' => 'Security~~', ]); diff --git a/dictionaries/ui/application/bulk/en.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/en.dictionary.itop.bulk.php index a2d8e73f41..fcd606c730 100644 --- a/dictionaries/ui/application/bulk/en.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/en.dictionary.itop.bulk.php @@ -24,4 +24,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.', + 'Core:BulkExport:Security' => 'Security', ]); diff --git a/dictionaries/ui/application/bulk/en_gb.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/en_gb.dictionary.itop.bulk.php index 442855c191..9631331275 100644 --- a/dictionaries/ui/application/bulk/en_gb.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/en_gb.dictionary.itop.bulk.php @@ -11,4 +11,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.', + 'Core:BulkExport:Security' => 'Security', ]); diff --git a/dictionaries/ui/application/bulk/es_cr.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/es_cr.dictionary.itop.bulk.php index 732fca221f..d29c6e816a 100644 --- a/dictionaries/ui/application/bulk/es_cr.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/es_cr.dictionary.itop.bulk.php @@ -12,4 +12,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'Este atributo no se puede editar en contexto masivo', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Advertencia de seguridad de Excel', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Abrir un archivo con datos que no son de confianza en Microsoft Excel puede provocar la inyección de fórmulas. Asegúrese de que la configuración de Excel esté configurada para manejar archivos de forma segura. Obtenga más información en nuestra documentación.', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', + 'Core:BulkExport:Security' => 'Security~~', ]); diff --git a/dictionaries/ui/application/bulk/fr.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/fr.dictionary.itop.bulk.php index fe822187de..9c6838f60f 100644 --- a/dictionaries/ui/application/bulk/fr.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/fr.dictionary.itop.bulk.php @@ -14,4 +14,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'Cet attribut ne peut être édité dans une modification en masse', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Avertissement sur la sécurité d\'Excel', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'L\'ouverture d\'un fichier contenant des données non fiables dans Microsoft Excel peut entraîner l\'injection de formules. Assurez-vous que vos paramètres Excel sont configurés pour traiter les fichiers en toute sécurité. Pour en savoir plus, consultez notre documentation.', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitiser les valeurs potentiellement dangereuses', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'Lorsqu\'elle est activée, les valeurs potentiellement dangereuses seront sanitizées lors de l\'exportation. Cela empêchera Microsoft Excel de les interpréter comme des formules. Notez que cela peut altérer les données originales en les préfixant avec une simple quote (\') pour s\'assurer qu\'elles soient traitées comme du texte.', + 'Core:BulkExport:Security' => 'Securité', ]); diff --git a/dictionaries/ui/application/bulk/hu.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/hu.dictionary.itop.bulk.php index ca88b25d97..eba757d63c 100644 --- a/dictionaries/ui/application/bulk/hu.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/hu.dictionary.itop.bulk.php @@ -14,4 +14,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', + 'Core:BulkExport:Security' => 'Security~~', ]); diff --git a/dictionaries/ui/application/bulk/it.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/it.dictionary.itop.bulk.php index 9a2aaf3a63..91200ed193 100644 --- a/dictionaries/ui/application/bulk/it.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/it.dictionary.itop.bulk.php @@ -14,4 +14,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'Questo attributo non può essere modificato nel contesto di modifica bulk', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Avviso di sicurezza di Excel', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'L\'apertura di un file con dati non fidati in Microsoft Excel potrebbe comportare l\'iniezione di formule. Assicurati che le impostazioni di Excel siano configurate per gestire i file in modo sicuro. Ulteriori informazioni nella nostra documentazione.', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', + 'Core:BulkExport:Security' => 'Security~~', ]); diff --git a/dictionaries/ui/application/bulk/ja.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/ja.dictionary.itop.bulk.php index 2c6029cd0b..f1badb748b 100644 --- a/dictionaries/ui/application/bulk/ja.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/ja.dictionary.itop.bulk.php @@ -14,4 +14,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', + 'Core:BulkExport:Security' => 'Security~~', ]); diff --git a/dictionaries/ui/application/bulk/nl.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/nl.dictionary.itop.bulk.php index 34caf4cf91..f1e9245056 100644 --- a/dictionaries/ui/application/bulk/nl.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/nl.dictionary.itop.bulk.php @@ -14,4 +14,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', + 'Core:BulkExport:Security' => 'Security~~', ]); diff --git a/dictionaries/ui/application/bulk/pl.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/pl.dictionary.itop.bulk.php index ae71e7ee17..523dbc79c7 100644 --- a/dictionaries/ui/application/bulk/pl.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/pl.dictionary.itop.bulk.php @@ -14,4 +14,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'Tego atrybutu nie można edytować zbiorczo', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Ostrzeżenie dotyczące bezpieczeństwa programu Excel', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Otwarcie pliku z niezaufanymi danymi w programie Microsoft Excel może spowodować wstrzyknięcie formuły. Upewnij się, że ustawienia programu Excel są skonfigurowane tak, aby bezpiecznie obsługiwać pliki. Dowiedz się więcej w naszej dokumentacji.', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', + 'Core:BulkExport:Security' => 'Security~~', ]); diff --git a/dictionaries/ui/application/bulk/pt_br.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/pt_br.dictionary.itop.bulk.php index b7347bd711..dfbfc6f70f 100644 --- a/dictionaries/ui/application/bulk/pt_br.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/pt_br.dictionary.itop.bulk.php @@ -14,4 +14,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', + 'Core:BulkExport:Security' => 'Security~~', ]); diff --git a/dictionaries/ui/application/bulk/ru.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/ru.dictionary.itop.bulk.php index 11e539a25d..daa4383eae 100644 --- a/dictionaries/ui/application/bulk/ru.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/ru.dictionary.itop.bulk.php @@ -14,4 +14,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', + 'Core:BulkExport:Security' => 'Security~~', ]); diff --git a/dictionaries/ui/application/bulk/sk.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/sk.dictionary.itop.bulk.php index e3f6792d9b..0affc8d41f 100644 --- a/dictionaries/ui/application/bulk/sk.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/sk.dictionary.itop.bulk.php @@ -14,4 +14,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', + 'Core:BulkExport:Security' => 'Security~~', ]); diff --git a/dictionaries/ui/application/bulk/tr.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/tr.dictionary.itop.bulk.php index 9c93546d05..4a37890caf 100644 --- a/dictionaries/ui/application/bulk/tr.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/tr.dictionary.itop.bulk.php @@ -14,4 +14,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', + 'Core:BulkExport:Security' => 'Security~~', ]); diff --git a/dictionaries/ui/application/bulk/zh_cn.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/zh_cn.dictionary.itop.bulk.php index 08a354d54e..3a2e393f56 100644 --- a/dictionaries/ui/application/bulk/zh_cn.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/zh_cn.dictionary.itop.bulk.php @@ -23,4 +23,7 @@ 'UI:Bulk:modify:IncompatibleAttribute' => '此属性无法在批量操作中编辑', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel 安全警告', 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => '在 Microsoft Excel 中打开不信任的文件可能导致公式注入. 请确保 Excel 设置能够安全的处理该文件. 进入我们的文档了解更多.', + 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', + 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', + 'Core:BulkExport:Security' => 'Security~~', ]); diff --git a/js/utils.js b/js/utils.js index 8bbda0ccf8..c7225e23bd 100644 --- a/js/utils.js +++ b/js/utils.js @@ -487,6 +487,12 @@ function ExportStartExport() { oParams.expression = $('#export-form :input[name=expression]').val(); oParams.query = $('#export-form :input[name=query]').val(); } + + // Read the "sanitize_excel_export" checkbox if it exists, and set the corresponding "ignore_excel_sanitization" parameter + if($(':input[name=sanitize_excel_export]').length > 0) { + oParams.ignore_excel_sanitization = $(':input[name=sanitize_excel_export]').is(':checked') ? 0 : 1; + } + $.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', oParams, function (data) { if (data == null) { ExportError('Export failed (no data provided), please contact your administrator'); diff --git a/sources/Application/Helper/ExportHelper.php b/sources/Application/Helper/ExportHelper.php index 5e76b9d7e0..3e11d171fa 100644 --- a/sources/Application/Helper/ExportHelper.php +++ b/sources/Application/Helper/ExportHelper.php @@ -3,6 +3,9 @@ namespace Combodo\iTop\Application\Helper; use Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory; +use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory; +use Combodo\iTop\Application\UI\Base\Component\Input\InputWithLabel; +use Combodo\iTop\Application\UI\Base\UIBlock; use Dict; use utils; @@ -17,12 +20,88 @@ */ class ExportHelper { + public const EXCEL_FORMULA_CHARACTERS = ['=', '=', '+', '+', '-', '-', '@', '@', '|', ' ', "\t", "\n", "\r"]; + public static function GetAlertForExcelMaliciousInjection() { $sWikiUrl = 'https://www.itophub.io/wiki/page?id='.utils::GetItopVersionWikiSyntax().'%3Auser%3Alists#excel_export'; - $oAlert = AlertUIBlockFactory::MakeForWarning(Dict::S('UI:Bulk:Export:MaliciousInjection:Alert:Title'), Dict::Format('UI:Bulk:Export:MaliciousInjection:Alert:Message', $sWikiUrl), 'ibo-excel-malicious-injection-alert'); + $oAlert = AlertUIBlockFactory::MakeForWarning(Dict::S('UI:Bulk:Export:MaliciousInjection:Alert:Title'), Dict::Format('UI:Bulk:Export:MaliciousInjection:Alert:Message', $sWikiUrl), 'ibo-sanitize-excel-export--alert'); $oAlert->EnableSaveCollapsibleState(true) ->SetIsClosable(false); return $oAlert; } + + /** + * @return InputWithLabel + * + * @since 3.2.3 + */ + public static function GetInputForSanitizeExcelExport(): UIBlock + { + + $oSanitizeInput = InputUIBlockFactory::MakeForInputWithLabel(Dict::S('UI:Bulk:Export:MaliciousInjection:Input:Label'), 'sanitize_excel_export', 1, 'ibo-sanitize-excel-export--input', 'checkbox'); + $oSanitizeInput->GetInput()->SetIsChecked(true); + $oSanitizeInput->SetBeforeInput(false); + $oSanitizeInput->SetDescription(Dict::S('UI:Bulk:Export:MaliciousInjection:Input:Tooltip')); + $oSanitizeInput->GetInput()->AddCSSClass('ibo-input-checkbox'); + + return $oSanitizeInput; + } + + /** + * @param string $sValue + * @return bool + * + * @since 3.2.3 + */ + public static function IsValueFormulaCandidate(string $sValue): bool + { + // An empty value cannot be a formula, so we can skip all the checks in this case + if ($sValue === '') { + return false; + } + + $bHasFormulaCandidate = false; + $sFirstChar = mb_substr($sValue, 0, 1); + $bHasFormulaCandidate |= in_array($sFirstChar, static::EXCEL_FORMULA_CHARACTERS, true); + + // If the string is less than 3 characters long, it cannot start with a url encoded formula character, so we can skip this check in this case + if (mb_strlen($sValue) < 3) { + return $bHasFormulaCandidate; + } + + // Additionally, check if the first three character could be a formula character url encodeded + $sFirstThreeChars = mb_strtoupper(mb_substr($sValue, 0, 3)); + + $aUrlEncodedFormulaCharacters = array_map('urlencode', static::EXCEL_FORMULA_CHARACTERS); + $bHasFormulaCandidate |= in_array($sFirstThreeChars, $aUrlEncodedFormulaCharacters, true); + + return $bHasFormulaCandidate; + } + + /** + * @param string $sField + * @param string $sTextQualifier + * @return string + * + * @since 3.2.3 + */ + public static function SanitizeField(string $sField, string $sTextQualifier = ''): string + { + if ($sField === '') { + return $sField; + } + + $sQualifier = $sTextQualifier; + if ($sQualifier !== '' && str_starts_with($sField, $sQualifier)) { + $sAfterQualifier = substr($sField, strlen($sQualifier)); + if (self::IsValueFormulaCandidate($sAfterQualifier)) { + return $sQualifier."'".$sAfterQualifier; + } + } elseif (self::IsValueFormulaCandidate($sField)) { + return "'".$sField; + } + + return $sField; + } } diff --git a/tests/php-unit-tests/unitary-tests/core/BulkExportTest.php b/tests/php-unit-tests/unitary-tests/core/BulkExportTest.php index 1fbe91ae73..6f45f9921a 100644 --- a/tests/php-unit-tests/unitary-tests/core/BulkExportTest.php +++ b/tests/php-unit-tests/unitary-tests/core/BulkExportTest.php @@ -158,4 +158,173 @@ public function testExportWithShowObsoleteParam( $this->assertEquals($sExpectedValue, $data); } + /** + * @dataProvider OrganizationsForExportSanitizeExcelExportProvider + * + * @param $aListOrg + * @param $aExpectedValues + * @return void + * @throws \CoreCannotSaveObjectException + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \OQLException + * @throws \ReflectionException + */ + public function testExportWithSanitizeExcelExport( + $aListOrg, + $aExpectedValues, + ) { + // Create tests organizations to have enough data + $iFirstOrg = 0; + foreach ($aListOrg as $aOrg) { + $oObj = $this->CreateOrganization($aOrg[0]); + if ($aOrg[1] === false) { + $oObj->Set('status', 'inactive'); + $oObj->DBUpdate(); + } + if ($iFirstOrg === 0) { + $iFirstOrg = $oObj->GetKey(); + } + } + + $aStatusInfo = [ + "fields" => [ + [ + "sFieldSpec" => "name", + "sAlias" => "Organization", + "sClass" => "Organization", + "sAttCode" => "name", + "sLabel" => "Name", + "sColLabel" => "Name", + ], + ], + "text_qualifier" => "\"", + "charset" => "UTF-8", + "separator" => ",", + "date_format" => "Y-m-d H:i:s", + "formatted_text" => false, + "show_obsolete_data" => false, + 'ignore_excel_sanitization' => false, + ]; + $sStatus = []; + $oSearch = DBObjectSearch::FromOQL('SELECT Organization'); + $oExporter = BulkExport::FindExporter('csv', $oSearch); + $oExporter->SetStatusInfo($aStatusInfo); + $oExporter->SetObjectList($oSearch); + $oExporter->SetChunkSize(EXPORTER_DEFAULT_CHUNK_SIZE); + + $data = $oExporter->GetHeader(); + $data .= $oExporter->GetNextChunk($sStatus); + + // Check that the value is sanitized as expected (with a ' prefix) + foreach ($aExpectedValues as $sExpectedValue) { + $this->assertStringContainsString($sExpectedValue, $data, "The value $sExpectedValue is expected to be found in the export result"); + } + } + + /** + * @dataProvider OrganizationsForExportSanitizeExcelExportProvider + * + * @param $aListOrg + * @param $aExpectedValues + * @return void + * @throws \CoreCannotSaveObjectException + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \OQLException + * @throws \ReflectionException + */ + public function testExportWithoutSanitizeExcelExport( + $aListOrg, + $aExpectedValues, + ) { + // Create tests organizations to have enough data + $iFirstOrg = 0; + foreach ($aListOrg as $aOrg) { + $oObj = $this->CreateOrganization($aOrg[0]); + if ($aOrg[1] === false) { + $oObj->Set('status', 'inactive'); + $oObj->DBUpdate(); + } + if ($iFirstOrg === 0) { + $iFirstOrg = $oObj->GetKey(); + } + } + + $aStatusInfo = [ + "fields" => [ + [ + "sFieldSpec" => "name", + "sAlias" => "Organization", + "sClass" => "Organization", + "sAttCode" => "name", + "sLabel" => "Name", + "sColLabel" => "Name", + ], + ], + "text_qualifier" => "\"", + "charset" => "UTF-8", + "separator" => ",", + "date_format" => "Y-m-d H:i:s", + "formatted_text" => false, + "show_obsolete_data" => false, + 'ignore_excel_sanitization' => true, + ]; + $sStatus = []; + $oSearch = DBObjectSearch::FromOQL('SELECT Organization'); + $oExporter = BulkExport::FindExporter('csv', $oSearch); + $oExporter->SetStatusInfo($aStatusInfo); + $oExporter->SetObjectList($oSearch); + $oExporter->SetChunkSize(EXPORTER_DEFAULT_CHUNK_SIZE); + + $data = $oExporter->GetHeader(); + $data .= $oExporter->GetNextChunk($sStatus); + + // Check that the value is not sanitized + foreach ($aListOrg as $sExpectedValue) { + $this->assertStringContainsString($sExpectedValue[0], $data, "The value $sExpectedValue[0] is expected to be found in the export result"); + } + } + + public function OrganizationsForExportSanitizeExcelExportProvider() + { + return [ + 'Page1' => [ + 'list_org' => [ + ['=org1', true], + ['+org2', true], + ['-org3', true], + ['@org4', true], + ["\t=org5", true], + ["\rorg6", true], + ["\r\t\r =org7", true], + ['=org8', true], + ['+org9', true], + ['-org10', true], + ['@org11', true], + ['|org12', true], + ['%3Dorg13', true], + ['%3dorg14', true], + ['org15', true], + ], + 'export_org' => [ + "'=org1", + "'+org2", + "'-org3", + "'@org4", + "'\t=org5", + "\rorg6", + "'\r\t\r =org7", + "'=org8", + "'+org9", + "'-org10", + "'@org11", + "'|org12", + "'%3Dorg13", + "'%3dorg14", + "org14", + ], + ], + ]; + } } From 4be4c9f673f87dbeba2eaf9c699033c59f5e723a Mon Sep 17 00:00:00 2001 From: Stephen Abello Date: Wed, 25 Feb 2026 11:54:10 +0100 Subject: [PATCH 2/9] Update unit test expected return --- tests/php-unit-tests/unitary-tests/core/BulkExportTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/php-unit-tests/unitary-tests/core/BulkExportTest.php b/tests/php-unit-tests/unitary-tests/core/BulkExportTest.php index 6f45f9921a..11e5467ba6 100644 --- a/tests/php-unit-tests/unitary-tests/core/BulkExportTest.php +++ b/tests/php-unit-tests/unitary-tests/core/BulkExportTest.php @@ -313,7 +313,7 @@ public function OrganizationsForExportSanitizeExcelExportProvider() "'-org3", "'@org4", "'\t=org5", - "\rorg6", + "'\rorg6", "'\r\t\r =org7", "'=org8", "'+org9", From ec00c052ddb8a287b5393f41fb18ad1b372a9e02 Mon Sep 17 00:00:00 2001 From: Stephen Abello Date: Wed, 25 Feb 2026 11:54:36 +0100 Subject: [PATCH 3/9] Update unit test expected return --- tests/php-unit-tests/unitary-tests/core/BulkExportTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/php-unit-tests/unitary-tests/core/BulkExportTest.php b/tests/php-unit-tests/unitary-tests/core/BulkExportTest.php index 11e5467ba6..bcdf9b5418 100644 --- a/tests/php-unit-tests/unitary-tests/core/BulkExportTest.php +++ b/tests/php-unit-tests/unitary-tests/core/BulkExportTest.php @@ -322,7 +322,7 @@ public function OrganizationsForExportSanitizeExcelExportProvider() "'|org12", "'%3Dorg13", "'%3dorg14", - "org14", + "org15", ], ], ]; From e0dfab0575a41906bd6824f7b98145ff79f8cf58 Mon Sep 17 00:00:00 2001 From: Stephen Abello Date: Wed, 25 Feb 2026 11:55:24 +0100 Subject: [PATCH 4/9] Update dict entry --- dictionaries/ui/application/bulk/fr.dictionary.itop.bulk.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dictionaries/ui/application/bulk/fr.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/fr.dictionary.itop.bulk.php index 9c6838f60f..70bf6b0958 100644 --- a/dictionaries/ui/application/bulk/fr.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/fr.dictionary.itop.bulk.php @@ -16,5 +16,5 @@ 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'L\'ouverture d\'un fichier contenant des données non fiables dans Microsoft Excel peut entraîner l\'injection de formules. Assurez-vous que vos paramètres Excel sont configurés pour traiter les fichiers en toute sécurité. Pour en savoir plus, consultez notre documentation.', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitiser les valeurs potentiellement dangereuses', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'Lorsqu\'elle est activée, les valeurs potentiellement dangereuses seront sanitizées lors de l\'exportation. Cela empêchera Microsoft Excel de les interpréter comme des formules. Notez que cela peut altérer les données originales en les préfixant avec une simple quote (\') pour s\'assurer qu\'elles soient traitées comme du texte.', - 'Core:BulkExport:Security' => 'Securité', + 'Core:BulkExport:Security' => 'Sécurité', ]); From 43fc6f8d4e4869c8dcc4828daec61d0aab8dc86f Mon Sep 17 00:00:00 2001 From: Stephen Abello Date: Wed, 25 Feb 2026 11:58:44 +0100 Subject: [PATCH 5/9] Remove space character from potential attack vectors --- sources/Application/Helper/ExportHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/Application/Helper/ExportHelper.php b/sources/Application/Helper/ExportHelper.php index 3e11d171fa..2696545f23 100644 --- a/sources/Application/Helper/ExportHelper.php +++ b/sources/Application/Helper/ExportHelper.php @@ -20,7 +20,7 @@ */ class ExportHelper { - public const EXCEL_FORMULA_CHARACTERS = ['=', '=', '+', '+', '-', '-', '@', '@', '|', ' ', "\t", "\n", "\r"]; + public const EXCEL_FORMULA_CHARACTERS = ['=', '=', '+', '+', '-', '-', '@', '@', '|', "\t", "\n", "\r"]; public static function GetAlertForExcelMaliciousInjection() { From 8f39d07271167fbde4bb8c33dcb38391899c33ad Mon Sep 17 00:00:00 2001 From: Stephen Abello Date: Wed, 25 Feb 2026 11:59:15 +0100 Subject: [PATCH 6/9] typo --- sources/Application/Helper/ExportHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/Application/Helper/ExportHelper.php b/sources/Application/Helper/ExportHelper.php index 2696545f23..fdb23cb21c 100644 --- a/sources/Application/Helper/ExportHelper.php +++ b/sources/Application/Helper/ExportHelper.php @@ -70,7 +70,7 @@ public static function IsValueFormulaCandidate(string $sValue): bool return $bHasFormulaCandidate; } - // Additionally, check if the first three character could be a formula character url encodeded + // Additionally, check if the first three character could be a formula character url encoded $sFirstThreeChars = mb_strtoupper(mb_substr($sValue, 0, 3)); $aUrlEncodedFormulaCharacters = array_map('urlencode', static::EXCEL_FORMULA_CHARACTERS); From e47556e73eab6f86c67dda337da3ca666eebbf72 Mon Sep 17 00:00:00 2001 From: Stephen Abello Date: Wed, 25 Feb 2026 12:10:32 +0100 Subject: [PATCH 7/9] Update core/csvbulkexport.class.inc.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- core/csvbulkexport.class.inc.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/csvbulkexport.class.inc.php b/core/csvbulkexport.class.inc.php index 42b3a7ddb4..0e4ded3460 100644 --- a/core/csvbulkexport.class.inc.php +++ b/core/csvbulkexport.class.inc.php @@ -271,12 +271,13 @@ protected function GetValue($oObj, $sAttCode) $sRet = trim($oObj->GetAsCSV($sAttCode), '"'); } - // If the option to ignore Excel sanitization is set, return the raw value without sanitization - if (array_key_exists('ignore_excel_sanitization', $this->aStatusInfo) && $this->aStatusInfo['ignore_excel_sanitization'] === true) { - return $sRet; + // If the option to ignore Excel sanitization is not set or explicitly set to false, apply sanitization + if (!(array_key_exists('ignore_excel_sanitization', $this->aStatusInfo)) || $this->aStatusInfo['ignore_excel_sanitization'] === false) { + return ExportHelper::SanitizeField($sRet, $this->aStatusInfo['text_qualifier'] ?? ''); } - return ExportHelper::SanitizeField($sRet, $this->aStatusInfo['text_qualifier'] ?? ''); + // The option to ignore Excel sanitization is explicitly set to true: return the raw value without sanitization + return $sRet; } public function GetHeader() From 86133b52b2375f24811f76bc4f7812a3ca6d8f22 Mon Sep 17 00:00:00 2001 From: Stephen Abello Date: Wed, 25 Feb 2026 20:31:40 +0100 Subject: [PATCH 8/9] Update sources/Application/Helper/ExportHelper.php Co-authored-by: Molkobain --- sources/Application/Helper/ExportHelper.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sources/Application/Helper/ExportHelper.php b/sources/Application/Helper/ExportHelper.php index fdb23cb21c..8ccc3b189e 100644 --- a/sources/Application/Helper/ExportHelper.php +++ b/sources/Application/Helper/ExportHelper.php @@ -20,6 +20,9 @@ */ class ExportHelper { + /** + * @since 3.2.3 3.3.0 N°6977 + */ public const EXCEL_FORMULA_CHARACTERS = ['=', '=', '+', '+', '-', '-', '@', '@', '|', "\t", "\n", "\r"]; public static function GetAlertForExcelMaliciousInjection() From 80a5d9ce00b14317687beff565feb3b3e70048b3 Mon Sep 17 00:00:00 2001 From: Stephen Abello Date: Thu, 5 Mar 2026 09:51:08 +0100 Subject: [PATCH 9/9] Update alert message in the portal --- .../templates/bricks/manage/popup-export-excel.html.twig | 2 +- dictionaries/ui/application/bulk/cs.dictionary.itop.bulk.php | 3 ++- dictionaries/ui/application/bulk/da.dictionary.itop.bulk.php | 3 ++- dictionaries/ui/application/bulk/de.dictionary.itop.bulk.php | 3 ++- dictionaries/ui/application/bulk/en.dictionary.itop.bulk.php | 3 ++- .../ui/application/bulk/en_gb.dictionary.itop.bulk.php | 3 ++- .../ui/application/bulk/es_cr.dictionary.itop.bulk.php | 3 ++- dictionaries/ui/application/bulk/fr.dictionary.itop.bulk.php | 3 ++- dictionaries/ui/application/bulk/hu.dictionary.itop.bulk.php | 3 ++- dictionaries/ui/application/bulk/it.dictionary.itop.bulk.php | 3 ++- dictionaries/ui/application/bulk/ja.dictionary.itop.bulk.php | 3 ++- dictionaries/ui/application/bulk/nl.dictionary.itop.bulk.php | 3 ++- dictionaries/ui/application/bulk/pl.dictionary.itop.bulk.php | 3 ++- .../ui/application/bulk/pt_br.dictionary.itop.bulk.php | 3 ++- dictionaries/ui/application/bulk/ru.dictionary.itop.bulk.php | 3 ++- dictionaries/ui/application/bulk/sk.dictionary.itop.bulk.php | 3 ++- dictionaries/ui/application/bulk/tr.dictionary.itop.bulk.php | 3 ++- .../ui/application/bulk/zh_cn.dictionary.itop.bulk.php | 3 ++- 18 files changed, 35 insertions(+), 18 deletions(-) diff --git a/datamodels/2.x/itop-portal-base/portal/templates/bricks/manage/popup-export-excel.html.twig b/datamodels/2.x/itop-portal-base/portal/templates/bricks/manage/popup-export-excel.html.twig index c7a528f086..7179d960ec 100644 --- a/datamodels/2.x/itop-portal-base/portal/templates/bricks/manage/popup-export-excel.html.twig +++ b/datamodels/2.x/itop-portal-base/portal/templates/bricks/manage/popup-export-excel.html.twig @@ -11,7 +11,7 @@
- +

{{ 'ExcelExport:PreparingExport'|dict_s }}

'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.~~', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', 'Core:BulkExport:Security' => 'Security~~', diff --git a/dictionaries/ui/application/bulk/da.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/da.dictionary.itop.bulk.php index 959b04c3b8..8ccf872300 100644 --- a/dictionaries/ui/application/bulk/da.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/da.dictionary.itop.bulk.php @@ -13,7 +13,8 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.~~', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', 'Core:BulkExport:Security' => 'Security~~', diff --git a/dictionaries/ui/application/bulk/de.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/de.dictionary.itop.bulk.php index 3340c4f7f5..08d2ee3585 100644 --- a/dictionaries/ui/application/bulk/de.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/de.dictionary.itop.bulk.php @@ -13,7 +13,8 @@ Dict::Add('DE DE', 'German', 'Deutsch', [ 'UI:Bulk:modify:IncompatibleAttribute' => 'Dieses Attribut kann in einer Massenänderung nicht bearbeitet werden.', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel-Sicherheitswarnung', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Das Öffnen einer Datei mit nicht vertrauenswürdigen Daten in Microsoft Excel kann zu einer Formel-Injektion führen. Stellen Sie sicher, dass Ihre Excel-Einstellungen so konfiguriert sind, dass Dateien sicher verarbeitet werden. Erfahren Sie mehr in unserer Dokumentation.', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Das Öffnen einer Datei mit nicht vertrauenswürdigen Daten in Microsoft Excel kann zu einer Formel-Injektion führen. Stellen Sie sicher, dass Ihre Excel-Einstellungen so konfiguriert sind, dass Dateien sicher verarbeitet werden. Erfahren Sie mehr in unserer Dokumentation.', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.~~', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', 'Core:BulkExport:Security' => 'Security~~', diff --git a/dictionaries/ui/application/bulk/en.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/en.dictionary.itop.bulk.php index fcd606c730..909f799267 100644 --- a/dictionaries/ui/application/bulk/en.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/en.dictionary.itop.bulk.php @@ -23,7 +23,8 @@ // Bulk modify 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.', 'Core:BulkExport:Security' => 'Security', diff --git a/dictionaries/ui/application/bulk/en_gb.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/en_gb.dictionary.itop.bulk.php index 9631331275..e5f910ffe6 100644 --- a/dictionaries/ui/application/bulk/en_gb.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/en_gb.dictionary.itop.bulk.php @@ -10,7 +10,8 @@ // Bulk modify 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.', 'Core:BulkExport:Security' => 'Security', diff --git a/dictionaries/ui/application/bulk/es_cr.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/es_cr.dictionary.itop.bulk.php index d29c6e816a..64d08840f7 100644 --- a/dictionaries/ui/application/bulk/es_cr.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/es_cr.dictionary.itop.bulk.php @@ -11,7 +11,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [ 'UI:Bulk:modify:IncompatibleAttribute' => 'Este atributo no se puede editar en contexto masivo', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Advertencia de seguridad de Excel', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Abrir un archivo con datos que no son de confianza en Microsoft Excel puede provocar la inyección de fórmulas. Asegúrese de que la configuración de Excel esté configurada para manejar archivos de forma segura. Obtenga más información en nuestra documentación.', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Abrir un archivo con datos que no son de confianza en Microsoft Excel puede provocar la inyección de fórmulas. Asegúrese de que la configuración de Excel esté configurada para manejar archivos de forma segura. Obtenga más información en nuestra documentación.', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.~~', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', 'Core:BulkExport:Security' => 'Security~~', diff --git a/dictionaries/ui/application/bulk/fr.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/fr.dictionary.itop.bulk.php index 70bf6b0958..b350194823 100644 --- a/dictionaries/ui/application/bulk/fr.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/fr.dictionary.itop.bulk.php @@ -13,7 +13,8 @@ Dict::Add('FR FR', 'French', 'Français', [ 'UI:Bulk:modify:IncompatibleAttribute' => 'Cet attribut ne peut être édité dans une modification en masse', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Avertissement sur la sécurité d\'Excel', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'L\'ouverture d\'un fichier contenant des données non fiables dans Microsoft Excel peut entraîner l\'injection de formules. Assurez-vous que vos paramètres Excel sont configurés pour traiter les fichiers en toute sécurité. Pour en savoir plus, consultez notre documentation.', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'L\'ouverture d\'un fichier contenant des données non fiables dans Microsoft Excel peut entraîner l\'injection de formules. Assurez-vous que vos paramètres Excel sont configurés pour traiter les fichiers en toute sécurité. Pour en savoir plus, consultez notre documentation.', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Certaines valeurs ont été échappées pour prévenir de potentielles failles de sécurités dans Microsoft Excel. Pour en savoir plus, consultez notre documentation', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitiser les valeurs potentiellement dangereuses', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'Lorsqu\'elle est activée, les valeurs potentiellement dangereuses seront sanitizées lors de l\'exportation. Cela empêchera Microsoft Excel de les interpréter comme des formules. Notez que cela peut altérer les données originales en les préfixant avec une simple quote (\') pour s\'assurer qu\'elles soient traitées comme du texte.', 'Core:BulkExport:Security' => 'Sécurité', diff --git a/dictionaries/ui/application/bulk/hu.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/hu.dictionary.itop.bulk.php index eba757d63c..478a85e1b7 100644 --- a/dictionaries/ui/application/bulk/hu.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/hu.dictionary.itop.bulk.php @@ -13,7 +13,8 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', [ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.~~', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', 'Core:BulkExport:Security' => 'Security~~', diff --git a/dictionaries/ui/application/bulk/it.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/it.dictionary.itop.bulk.php index 91200ed193..185c9e7bec 100644 --- a/dictionaries/ui/application/bulk/it.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/it.dictionary.itop.bulk.php @@ -13,7 +13,8 @@ Dict::Add('IT IT', 'Italian', 'Italiano', [ 'UI:Bulk:modify:IncompatibleAttribute' => 'Questo attributo non può essere modificato nel contesto di modifica bulk', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Avviso di sicurezza di Excel', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'L\'apertura di un file con dati non fidati in Microsoft Excel potrebbe comportare l\'iniezione di formule. Assicurati che le impostazioni di Excel siano configurate per gestire i file in modo sicuro. Ulteriori informazioni nella nostra documentazione.', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'L\'apertura di un file con dati non fidati in Microsoft Excel potrebbe comportare l\'iniezione di formule. Assicurati che le impostazioni di Excel siano configurate per gestire i file in modo sicuro. Ulteriori informazioni nella nostra documentazione.', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.~~', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', 'Core:BulkExport:Security' => 'Security~~', diff --git a/dictionaries/ui/application/bulk/ja.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/ja.dictionary.itop.bulk.php index f1badb748b..cc5bf01633 100644 --- a/dictionaries/ui/application/bulk/ja.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/ja.dictionary.itop.bulk.php @@ -13,7 +13,8 @@ Dict::Add('JA JP', 'Japanese', '日本語', [ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.~~', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', 'Core:BulkExport:Security' => 'Security~~', diff --git a/dictionaries/ui/application/bulk/nl.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/nl.dictionary.itop.bulk.php index f1e9245056..f47b0ca6c7 100644 --- a/dictionaries/ui/application/bulk/nl.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/nl.dictionary.itop.bulk.php @@ -13,7 +13,8 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', [ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.~~', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', 'Core:BulkExport:Security' => 'Security~~', diff --git a/dictionaries/ui/application/bulk/pl.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/pl.dictionary.itop.bulk.php index 523dbc79c7..c7cee27e96 100644 --- a/dictionaries/ui/application/bulk/pl.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/pl.dictionary.itop.bulk.php @@ -13,7 +13,8 @@ Dict::Add('PL PL', 'Polish', 'Polski', [ 'UI:Bulk:modify:IncompatibleAttribute' => 'Tego atrybutu nie można edytować zbiorczo', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Ostrzeżenie dotyczące bezpieczeństwa programu Excel', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Otwarcie pliku z niezaufanymi danymi w programie Microsoft Excel może spowodować wstrzyknięcie formuły. Upewnij się, że ustawienia programu Excel są skonfigurowane tak, aby bezpiecznie obsługiwać pliki. Dowiedz się więcej w naszej dokumentacji.', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Otwarcie pliku z niezaufanymi danymi w programie Microsoft Excel może spowodować wstrzyknięcie formuły. Upewnij się, że ustawienia programu Excel są skonfigurowane tak, aby bezpiecznie obsługiwać pliki. Dowiedz się więcej w naszej dokumentacji.', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.~~', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', 'Core:BulkExport:Security' => 'Security~~', diff --git a/dictionaries/ui/application/bulk/pt_br.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/pt_br.dictionary.itop.bulk.php index dfbfc6f70f..b79f59c64f 100644 --- a/dictionaries/ui/application/bulk/pt_br.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/pt_br.dictionary.itop.bulk.php @@ -13,7 +13,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', [ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.~~', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', 'Core:BulkExport:Security' => 'Security~~', diff --git a/dictionaries/ui/application/bulk/ru.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/ru.dictionary.itop.bulk.php index daa4383eae..8b3de319c2 100644 --- a/dictionaries/ui/application/bulk/ru.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/ru.dictionary.itop.bulk.php @@ -13,7 +13,8 @@ Dict::Add('RU RU', 'Russian', 'Русский', [ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.~~', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', 'Core:BulkExport:Security' => 'Security~~', diff --git a/dictionaries/ui/application/bulk/sk.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/sk.dictionary.itop.bulk.php index 0affc8d41f..d87bfa6a74 100644 --- a/dictionaries/ui/application/bulk/sk.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/sk.dictionary.itop.bulk.php @@ -13,7 +13,8 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', [ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.~~', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', 'Core:BulkExport:Security' => 'Security~~', diff --git a/dictionaries/ui/application/bulk/tr.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/tr.dictionary.itop.bulk.php index 4a37890caf..a7376494c7 100644 --- a/dictionaries/ui/application/bulk/tr.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/tr.dictionary.itop.bulk.php @@ -13,7 +13,8 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', [ 'UI:Bulk:modify:IncompatibleAttribute' => 'This attribute can\'t be edited in bulk context~~', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel security warning~~', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. Learn more in our documentation.~~', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.~~', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', 'Core:BulkExport:Security' => 'Security~~', diff --git a/dictionaries/ui/application/bulk/zh_cn.dictionary.itop.bulk.php b/dictionaries/ui/application/bulk/zh_cn.dictionary.itop.bulk.php index 3a2e393f56..9cab4e886e 100644 --- a/dictionaries/ui/application/bulk/zh_cn.dictionary.itop.bulk.php +++ b/dictionaries/ui/application/bulk/zh_cn.dictionary.itop.bulk.php @@ -22,7 +22,8 @@ // Bulk modify 'UI:Bulk:modify:IncompatibleAttribute' => '此属性无法在批量操作中编辑', 'UI:Bulk:Export:MaliciousInjection:Alert:Title' => 'Excel 安全警告', - 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => '在 Microsoft Excel 中打开不信任的文件可能导致公式注入. 请确保 Excel 设置能够安全的处理该文件. 进入我们的文档了解更多.', + 'UI:Bulk:Export:MaliciousInjection:Alert:Message' => '在 Microsoft Excel 中打开不信任的文件可能导致公式注入. 请确保 Excel 设置能够安全的处理该文件. 进入我们的文档了解更多.', + 'UI:Bulk:Export:MaliciousInjection:Sanitization:Alert:Message' => 'Some values have been sanitized to prevent potential security issues in Microsoft Excel. Learn more in our documentation.~~', 'UI:Bulk:Export:MaliciousInjection:Input:Label' => 'Sanitize potentially dangerous values~~', 'UI:Bulk:Export:MaliciousInjection:Input:Tooltip' => 'When enabled, potentially dangerous values will be sanitized during export. This will prevent Microsoft Excel from interpreting them as formulas. Note that this may alter the original data by prefixing it with a single quote (\') to ensure it is treated as text.~~', 'Core:BulkExport:Security' => 'Security~~',