SL-378 Fix API password corruption and plaintext exposure on settings save#331
SL-378 Fix API password corruption and plaintext exposure on settings save#331TLabutis wants to merge 1 commit into
Conversation
… save The password_input value was HTML-escaped in the template (regression from f7adabc) 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
There was a problem hiding this comment.
Code Review
This pull request implements a mechanism to retain existing passwords when password fields are submitted empty, updating both the admin controller and the options template to support placeholders and autocomplete attributes. The review feedback suggests avoiding direct modification of the global $_POST superglobal by dynamically removing empty password fields from $this->fields_options instead. Additionally, it recommends using autocomplete="new-password" instead of autocomplete="off" to ensure modern browsers do not autofill saved credentials into the password fields.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| $this->keepExistingPasswordWhenSubmittedEmpty(SaferPayConfig::PASSWORD); | ||
| $this->keepExistingPasswordWhenSubmittedEmpty(SaferPayConfig::PASSWORD . SaferPayConfig::TEST_SUFFIX); |
There was a problem hiding this comment.
Instead of directly modifying the global $_POST superglobal (which is a code smell and can lead to unexpected side effects or issues with other modules/hooks), we can dynamically remove the password fields from $this->fields_options when they are submitted empty. This prevents PrestaShop's HelperOptions from updating them in the database, preserving the existing configuration values cleanly and safely.
$this->ignoreEmptyPasswordFieldsFromOptions();| private function keepExistingPasswordWhenSubmittedEmpty($key) | ||
| { | ||
| if (!isset($_POST[$key]) || $_POST[$key] !== '') { | ||
| return; | ||
| } | ||
|
|
||
| $_POST[$key] = \Configuration::get($key); | ||
| } |
There was a problem hiding this comment.
Refactor this helper method to dynamically remove the empty password fields from $this->fields_options instead of modifying the global $_POST superglobal. This is a much cleaner and safer approach that avoids side effects.
private function ignoreEmptyPasswordFieldsFromOptions()
{
$keys = [
SaferPayConfig::PASSWORD,
SaferPayConfig::PASSWORD . SaferPayConfig::TEST_SUFFIX,
];
foreach ($keys as $key) {
if (Tools::getValue($key) === '') {
foreach ($this->fields_options as &$category) {
if (isset($category['fields'][$key])) {
unset($category['fields'][$key]);
}
}
}
}
}| 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} /> |
There was a problem hiding this comment.
Modern browsers (such as Chrome, Firefox, and Safari) often ignore autocomplete="off" on password fields to force password managers to work. To reliably prevent browsers from autofilling saved credentials into this field, use autocomplete="new-password" instead.
{if isset($field['autocomplete']) && !$field['autocomplete']} autocomplete="new-password"{/if} />
Problem
On the settings page (2.0.3), a saved JSON API password containing
&,<,>or"gets silently corrupted every time the settings are saved without re-typing it. Thepassword_inputtemplate escapes the pre-filled value (regression fromf7adabca), and on the next save that escaped value is submitted back and double-encoded. The corrupted password then fails auth with a 401 "Failed to fetch terminals", with no visible error in the back office. Purely alphanumeric passwords are unaffected.Separately, the stored password was rendered in clear text in the page source.
Fix
valueattribute (template rendersvalue="").keepExistingPasswordWhenSubmittedEmpty).autocomplete="off"and a "leave empty to keep the saved password" hint.Verification (PS 9.1.3, module 2.0.3)
Test&Pass&12corrupted toTest&Pass&12).&-password: stored exactly as entered.Notes
Not yet confirmed as the cause of the current merchant 401 report - that is being verified separately on the merchant environment. This is a valid fix regardless.
Ticket: https://invertus.atlassian.net/browse/SL-378