From bdce477d2f269d3d8d6d8f0576658a77799f9ccd Mon Sep 17 00:00:00 2001 From: Tadas Labutis Date: Wed, 1 Jul 2026 17:22:07 +0300 Subject: [PATCH] SL-378 Fix API password corruption and plaintext exposure on settings save The password_input value was HTML-escaped in the template (regression from f7adabca) and pre-filled from the stored value. On save without re-typing, the escaped value was submitted back and double-encoded, silently corrupting passwords containing & < > " and causing 401 errors. The stored password was also exposed in clear text in the page source. - Stop pre-filling the password into the value attribute - Keep the stored password when the field is submitted empty - Add autocomplete off and a 'leave empty to keep' hint --- ...dminSaferPayOfficialSettingsController.php | 22 +++++++++++++++++-- .../helpers/options/options.tpl | 3 ++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/controllers/admin/AdminSaferPayOfficialSettingsController.php b/controllers/admin/AdminSaferPayOfficialSettingsController.php index 701ffa41..bfb843c6 100644 --- a/controllers/admin/AdminSaferPayOfficialSettingsController.php +++ b/controllers/admin/AdminSaferPayOfficialSettingsController.php @@ -56,6 +56,9 @@ public function initContent() public function postProcess() { + $this->keepExistingPasswordWhenSubmittedEmpty(SaferPayConfig::PASSWORD); + $this->keepExistingPasswordWhenSubmittedEmpty(SaferPayConfig::PASSWORD . SaferPayConfig::TEST_SUFFIX); + parent::postProcess(); /** @var Configuration $configuration */ @@ -82,6 +85,15 @@ public function postProcess() return true; } + private function keepExistingPasswordWhenSubmittedEmpty($key) + { + if (!isset($_POST[$key]) || $_POST[$key] !== '') { + return; + } + + $_POST[$key] = \Configuration::get($key); + } + private function validateTerminalId() { try { @@ -489,7 +501,10 @@ private function displayTestEnvironmentConfiguration() 'title' => $this->module->l('JSON API Password'), 'type' => 'password_input', 'class' => 'fixed-width-xl', - 'value' => \Configuration::get(SaferPayConfig::PASSWORD . SaferPayConfig::TEST_SUFFIX), + 'autocomplete' => false, + 'placeholder' => \Configuration::get(SaferPayConfig::PASSWORD . SaferPayConfig::TEST_SUFFIX) + ? $this->module->l('Leave empty to keep the saved password') + : '', ], SaferPayConfig::CUSTOMER_ID . SaferPayConfig::TEST_SUFFIX => [ 'title' => $this->module->l('Customer ID'), @@ -557,7 +572,10 @@ private function displayLiveEnvironmentConfiguration() 'title' => $this->module->l('JSON API Password'), 'type' => 'password_input', 'class' => 'fixed-width-xl', - 'value' => \Configuration::get(SaferPayConfig::PASSWORD), + 'autocomplete' => false, + 'placeholder' => \Configuration::get(SaferPayConfig::PASSWORD) + ? $this->module->l('Leave empty to keep the saved password') + : '', ], SaferPayConfig::CUSTOMER_ID => [ 'title' => $this->module->l('Customer ID'), diff --git a/views/templates/admin/field-option-settings/helpers/options/options.tpl b/views/templates/admin/field-option-settings/helpers/options/options.tpl index a51d8345..b5f50ec3 100644 --- a/views/templates/admin/field-option-settings/helpers/options/options.tpl +++ b/views/templates/admin/field-option-settings/helpers/options/options.tpl @@ -31,7 +31,8 @@ class="{if isset($field['class'])}{$field['class']|escape:'htmlall':'UTF-8'}{/if}" size="{if isset($field['size'])}{$field['size']|intval}{else}5{/if}" name="{$key|escape:'htmlall':'UTF-8'}" - value="{$field['value']|escape:'htmlall':'UTF-8'}" + value="" + {if isset($field['placeholder']) && $field['placeholder']} placeholder="{$field['placeholder']|escape:'htmlall':'UTF-8'}"{/if} {if isset($field['autocomplete']) && !$field['autocomplete']} autocomplete="off"{/if} /> {/if}