From 7d2381916a087d8933c563b0f83d66281f9d2c8c Mon Sep 17 00:00:00 2001 From: Mathieu Ducharme Date: Tue, 8 Sep 2026 08:49:58 -0400 Subject: [PATCH 1/3] fix: replace deprecated FILTER_SANITIZE_STRING with a compatible Sanitizer utility --- .../src/Charcoal/Admin/AdminTemplate.php | 5 +- .../Docs/Template/Object/DocTemplate.php | 5 +- .../src/Charcoal/Admin/Support/Sanitizer.php | 64 +++++++++++++++++++ .../Admin/Template/ElfinderTemplate.php | 11 ++-- .../Template/Object/CollectionTemplate.php | 5 +- .../Admin/Template/Object/CreateTemplate.php | 3 +- .../Admin/Template/Object/EditTemplate.php | 5 +- .../Admin/Ui/ActionContainerTrait.php | 5 +- .../Admin/Widget/FormGroup/AclPermissions.php | 3 +- .../src/Charcoal/Admin/Widget/MapWidget.php | 5 +- .../src/Charcoal/Admin/Widget/TableWidget.php | 3 +- .../src/Charcoal/Email/Services/Parser.php | 5 +- 12 files changed, 98 insertions(+), 21 deletions(-) create mode 100644 packages/admin/src/Charcoal/Admin/Support/Sanitizer.php diff --git a/packages/admin/src/Charcoal/Admin/AdminTemplate.php b/packages/admin/src/Charcoal/Admin/AdminTemplate.php index 6945b9c00..621598c2e 100644 --- a/packages/admin/src/Charcoal/Admin/AdminTemplate.php +++ b/packages/admin/src/Charcoal/Admin/AdminTemplate.php @@ -24,6 +24,7 @@ use Charcoal\Admin\Ui\DashboardContainerInterface; use Charcoal\Admin\Support\AdminTrait; use Charcoal\Admin\Support\BaseUrlTrait; +use Charcoal\Admin\Support\Sanitizer; use Charcoal\Admin\Support\SecurityTrait; use Charcoal\Admin\Ui\FeedbackContainerTrait; @@ -830,7 +831,7 @@ private function mainMenuIdent($options = null) } // Get main menu from the obj_type - $objType = filter_input(INPUT_GET, 'obj_type', FILTER_SANITIZE_STRING); + $objType = Sanitizer::sanitizeGetParam('obj_type'); if ($objType) { $secondaryMenuItems = $this->adminConfig('secondary_menu'); foreach ($secondaryMenuItems as $main => $item) { @@ -842,7 +843,7 @@ private function mainMenuIdent($options = null) } // Choose main menu with a get parameter - $mainMenuFromRequest = filter_input(INPUT_GET, 'main_menu', FILTER_SANITIZE_STRING); + $mainMenuFromRequest = Sanitizer::sanitizeGetParam('main_menu'); if ($mainMenuFromRequest) { $mainMenuIdent = $mainMenuFromRequest; } diff --git a/packages/admin/src/Charcoal/Admin/Docs/Template/Object/DocTemplate.php b/packages/admin/src/Charcoal/Admin/Docs/Template/Object/DocTemplate.php index a3f8bdee5..312e4108d 100644 --- a/packages/admin/src/Charcoal/Admin/Docs/Template/Object/DocTemplate.php +++ b/packages/admin/src/Charcoal/Admin/Docs/Template/Object/DocTemplate.php @@ -7,6 +7,7 @@ use Pimple\Container; // From 'charcoal-admin' use Charcoal\Admin\AdminTemplate; +use Charcoal\Admin\Support\Sanitizer; use Charcoal\Admin\Ui\DashboardContainerInterface; use Charcoal\Admin\Ui\DashboardContainerTrait; use Charcoal\Admin\Ui\ObjectContainerInterface; @@ -84,7 +85,7 @@ public function title() if (!$objLabel && isset($metadata['admin']['forms'])) { $adminMetadata = $metadata['admin']; - $formIdent = filter_input(INPUT_GET, 'form_ident', FILTER_SANITIZE_STRING); + $formIdent = Sanitizer::sanitizeGetParam('form_ident'); if (!$formIdent) { if (isset($adminMetadata['defaultForm'])) { $fomIdent = $adminMetadata['defaultForm']; @@ -147,7 +148,7 @@ protected function createDashboardConfig() $dashboardIdent = $this->dashboardIdent(); if (empty($dashboardIdent)) { - $dashboardIdent = filter_input(INPUT_GET, 'dashboard_ident', FILTER_SANITIZE_STRING); + $dashboardIdent = Sanitizer::sanitizeGetParam('dashboard_ident'); } if (empty($dashboardIdent)) { diff --git a/packages/admin/src/Charcoal/Admin/Support/Sanitizer.php b/packages/admin/src/Charcoal/Admin/Support/Sanitizer.php new file mode 100644 index 000000000..3e7c5d55d --- /dev/null +++ b/packages/admin/src/Charcoal/Admin/Support/Sanitizer.php @@ -0,0 +1,64 @@ +getParams($keys); if (isset($data['obj_type'])) { - $this->objType = filter_var($data['obj_type'], FILTER_SANITIZE_STRING); + $this->objType = Sanitizer::sanitizeString($data['obj_type']); } if (isset($data['obj_id'])) { - $this->objId = filter_var($data['obj_id'], FILTER_SANITIZE_STRING); + $this->objId = Sanitizer::sanitizeString($data['obj_id']); } if (isset($data['property'])) { - $this->propertyIdent = filter_var($data['property'], FILTER_SANITIZE_STRING); + $this->propertyIdent = Sanitizer::sanitizeString($data['property']); } if (isset($data['assets'])) { @@ -119,7 +120,7 @@ protected function setDataFromRequest(RequestInterface $request) } if (isset($data['callback'])) { - $this->callbackIdent = filter_var($data['callback'], FILTER_SANITIZE_STRING); + $this->callbackIdent = Sanitizer::sanitizeString($data['callback']); } if (isset($this->elfinderConfig['translations'])) { @@ -487,7 +488,7 @@ public function elfinderClientConfig() $property = $this->formProperty(); if ($property) { - $mimeTypes = filter_input(INPUT_GET, 'filetype', FILTER_SANITIZE_STRING); + $mimeTypes = Sanitizer::sanitizeGetParam('filetype'); if ($mimeTypes) { if ($mimeTypes === 'file') { diff --git a/packages/admin/src/Charcoal/Admin/Template/Object/CollectionTemplate.php b/packages/admin/src/Charcoal/Admin/Template/Object/CollectionTemplate.php index d7e213814..4554ada38 100644 --- a/packages/admin/src/Charcoal/Admin/Template/Object/CollectionTemplate.php +++ b/packages/admin/src/Charcoal/Admin/Template/Object/CollectionTemplate.php @@ -10,6 +10,7 @@ use Pimple\Container; // From 'charcoal-admin' use Charcoal\Admin\AdminTemplate; +use Charcoal\Admin\Support\Sanitizer; use Charcoal\Admin\Ui\CollectionContainerInterface; use Charcoal\Admin\Ui\CollectionContainerTrait; use Charcoal\Admin\Ui\DashboardContainerInterface; @@ -154,7 +155,7 @@ public function title() if (!$objLabel && isset($metadata['admin']['lists'])) { $adminMetadata = $metadata['admin']; - $listIdent = filter_input(INPUT_GET, 'collection_ident', FILTER_SANITIZE_STRING); + $listIdent = Sanitizer::sanitizeGetParam('collection_ident'); if (!$listIdent) { $listIdent = $this->collectionIdent(); } @@ -289,7 +290,7 @@ private function metadataListIdent() */ private function metadataDashboardIdent() { - $dashboardIdent = filter_input(INPUT_GET, 'dashboard_ident', FILTER_SANITIZE_STRING); + $dashboardIdent = Sanitizer::sanitizeGetParam('dashboard_ident'); if ($dashboardIdent) { return $dashboardIdent; } diff --git a/packages/admin/src/Charcoal/Admin/Template/Object/CreateTemplate.php b/packages/admin/src/Charcoal/Admin/Template/Object/CreateTemplate.php index 4fa387bcf..b68c5d05e 100644 --- a/packages/admin/src/Charcoal/Admin/Template/Object/CreateTemplate.php +++ b/packages/admin/src/Charcoal/Admin/Template/Object/CreateTemplate.php @@ -9,6 +9,7 @@ use Pimple\Container; // From 'charcoal-admin' use Charcoal\Admin\AdminTemplate; +use Charcoal\Admin\Support\Sanitizer; use Charcoal\Admin\Ui\DashboardContainerInterface; use Charcoal\Admin\Ui\DashboardContainerTrait; use Charcoal\Admin\Ui\ObjectContainerInterface; @@ -82,7 +83,7 @@ public function title() if (!$title && isset($metadata['admin']['forms'])) { $adminMetadata = $metadata['admin']; - $formIdent = filter_input(INPUT_GET, 'form_ident', FILTER_SANITIZE_STRING); + $formIdent = Sanitizer::sanitizeGetParam('form_ident'); if (!$formIdent) { if (isset($adminMetadata['defaultForm'])) { $fomIdent = $adminMetadata['defaultForm']; diff --git a/packages/admin/src/Charcoal/Admin/Template/Object/EditTemplate.php b/packages/admin/src/Charcoal/Admin/Template/Object/EditTemplate.php index 9aedc36f5..f572da9d2 100644 --- a/packages/admin/src/Charcoal/Admin/Template/Object/EditTemplate.php +++ b/packages/admin/src/Charcoal/Admin/Template/Object/EditTemplate.php @@ -8,6 +8,7 @@ use Psr\Http\Message\RequestInterface; // From 'charcoal-admin' use Charcoal\Admin\AdminTemplate; +use Charcoal\Admin\Support\Sanitizer; use Charcoal\Admin\Ui\DashboardContainerInterface; use Charcoal\Admin\Ui\DashboardContainerTrait; use Charcoal\Admin\Ui\ObjectContainerInterface; @@ -82,7 +83,7 @@ public function title() if (!$title && isset($metadata['admin']['forms'])) { $adminMetadata = $metadata['admin']; - $formIdent = filter_input(INPUT_GET, 'form_ident', FILTER_SANITIZE_STRING); + $formIdent = Sanitizer::sanitizeGetParam('form_ident'); if (!$formIdent) { if (isset($adminMetadata['defaultForm'])) { $fomIdent = $adminMetadata['defaultForm']; @@ -175,7 +176,7 @@ protected function createDashboardConfig() $dashboardIdent = $this->dashboardIdent(); if (empty($dashboardIdent)) { - $dashboardIdent = filter_input(INPUT_GET, 'dashboard_ident', FILTER_SANITIZE_STRING); + $dashboardIdent = Sanitizer::sanitizeGetParam('dashboard_ident'); } if (empty($dashboardIdent)) { diff --git a/packages/admin/src/Charcoal/Admin/Ui/ActionContainerTrait.php b/packages/admin/src/Charcoal/Admin/Ui/ActionContainerTrait.php index b0fa09721..9218e3646 100644 --- a/packages/admin/src/Charcoal/Admin/Ui/ActionContainerTrait.php +++ b/packages/admin/src/Charcoal/Admin/Ui/ActionContainerTrait.php @@ -11,6 +11,7 @@ // From 'charcoal-user' use Charcoal\User\AuthAwareInterface; // From 'charcoal-admin' +use Charcoal\Admin\Support\Sanitizer; use Charcoal\Admin\Ui\CollectionContainerInterface; use Charcoal\Admin\Ui\FormSidebarInterface; use Charcoal\Admin\Ui\ObjectContainerInterface; @@ -424,13 +425,13 @@ protected function parseActionUrl($url, $action = null, $renderer = null) if ($renderer === null) { /** @todo Shame! Force `{{ id }}` to use "obj_id" GET parameter… */ - $objId = filter_input(INPUT_GET, 'obj_id', FILTER_SANITIZE_STRING); + $objId = Sanitizer::sanitizeGetParam('obj_id'); if ($objId) { $url = preg_replace('~\{\{\s*(obj_)?id\s*\}\}~', $objId, $url); } /** @todo Shame! Force `{{ type }}` to use "obj_type" GET parameter… */ - $objType = filter_input(INPUT_GET, 'obj_type', FILTER_SANITIZE_STRING); + $objType = Sanitizer::sanitizeGetParam('obj_type'); if ($objType) { $url = preg_replace('~\{\{\s*(obj_)?type\s*\}\}~', $objType, $url); } diff --git a/packages/admin/src/Charcoal/Admin/Widget/FormGroup/AclPermissions.php b/packages/admin/src/Charcoal/Admin/Widget/FormGroup/AclPermissions.php index d0789e22a..63cb2e845 100644 --- a/packages/admin/src/Charcoal/Admin/Widget/FormGroup/AclPermissions.php +++ b/packages/admin/src/Charcoal/Admin/Widget/FormGroup/AclPermissions.php @@ -19,6 +19,7 @@ use Charcoal\User\Acl\Manager as AclManager; // From 'charcoal-admin' use Charcoal\Admin\AdminWidget; +use Charcoal\Admin\Support\Sanitizer; use Charcoal\Admin\User\Permission; use Charcoal\Admin\User\PermissionCategory; @@ -73,7 +74,7 @@ class AclPermissions extends AdminWidget implements */ public function objId() { - return filter_input(INPUT_GET, 'obj_id', FILTER_SANITIZE_STRING); + return Sanitizer::sanitizeGetParam('obj_id'); } /** diff --git a/packages/admin/src/Charcoal/Admin/Widget/MapWidget.php b/packages/admin/src/Charcoal/Admin/Widget/MapWidget.php index c7cf12a67..5e8ffa5d5 100644 --- a/packages/admin/src/Charcoal/Admin/Widget/MapWidget.php +++ b/packages/admin/src/Charcoal/Admin/Widget/MapWidget.php @@ -10,6 +10,7 @@ use Charcoal\Ui\FormGroup\FormGroupTrait; // From 'charcoal-admin' use Charcoal\Admin\AdminWidget; +use Charcoal\Admin\Support\Sanitizer; /** * Map Widget displays a google map widget, with UI to add polygons, lines and points. @@ -331,8 +332,8 @@ public function hasObj() public function obj() { if ($this->obj === null) { - $objId = filter_input(INPUT_GET, 'obj_id', FILTER_SANITIZE_STRING); - $objType = filter_input(INPUT_GET, 'obj_type', FILTER_SANITIZE_STRING); + $objId = Sanitizer::sanitizeGetParam('obj_id'); + $objType = Sanitizer::sanitizeGetParam('obj_type'); if ($objId && $objType) { $obj = $this->modelFactory()->create($objType); $obj->load($objId); diff --git a/packages/admin/src/Charcoal/Admin/Widget/TableWidget.php b/packages/admin/src/Charcoal/Admin/Widget/TableWidget.php index 5db4d740c..a955ecaa5 100644 --- a/packages/admin/src/Charcoal/Admin/Widget/TableWidget.php +++ b/packages/admin/src/Charcoal/Admin/Widget/TableWidget.php @@ -15,6 +15,7 @@ // From 'charcoal-admin' use Charcoal\Admin\AdminWidget; use Charcoal\Admin\Support\HttpAwareTrait; +use Charcoal\Admin\Support\Sanitizer; use Charcoal\Admin\Ui\ActionContainerTrait; use Charcoal\Admin\Ui\CollectionContainerInterface; use Charcoal\Admin\Ui\CollectionContainerTrait; @@ -1068,7 +1069,7 @@ protected function configureCollectionLoader(CollectionLoader $loader, array $da $this->configureCollectionLoaderFromTrait($loader, $data); if (!isset($loader->hasMainMenuCallback)) { - $mainMenu = filter_input(INPUT_GET, 'main_menu', FILTER_SANITIZE_STRING); + $mainMenu = Sanitizer::sanitizeGetParam('main_menu'); if ($mainMenu) { $fn = function (&$obj) use ($mainMenu) { if (!$obj['main_menu']) { diff --git a/packages/email/src/Charcoal/Email/Services/Parser.php b/packages/email/src/Charcoal/Email/Services/Parser.php index 841a4bff7..7ebdafc64 100644 --- a/packages/email/src/Charcoal/Email/Services/Parser.php +++ b/packages/email/src/Charcoal/Email/Services/Parser.php @@ -72,7 +72,10 @@ public function emailFromArray(array $arr): string return $email; } - $name = str_replace('"', '', filter_var($arr['name'], FILTER_SANITIZE_STRING)); + $name = strip_tags((string)$arr['name']); + $name = str_replace("\0", '', $name); + $name = str_replace([ '\'', '"' ], [ ''', '"' ], $name); + $name = str_replace('"', '', $name); return sprintf('"%s" <%s>', $name, $email); } } From 3bd5835574410bf09c1102e8c7baca9adfbe65d6 Mon Sep 17 00:00:00 2001 From: Mathieu Ducharme Date: Tue, 8 Sep 2026 08:50:49 -0400 Subject: [PATCH 2/3] fix: sanitize remaining unfiltered request inputs --- .../src/Charcoal/Admin/Action/Account/LostPasswordAction.php | 4 ++-- .../Charcoal/Admin/Action/Account/ResetPasswordAction.php | 2 +- packages/admin/src/Charcoal/Admin/Action/LoginAction.php | 2 +- packages/admin/src/Charcoal/Admin/Action/LogoutAction.php | 2 +- packages/admin/src/Charcoal/Admin/AdminAction.php | 5 +++-- .../src/Charcoal/Admin/Template/Object/CreateTemplate.php | 5 +++-- packages/object/src/Charcoal/Object/UserData.php | 5 +++-- packages/user/src/Charcoal/User/Authenticator.php | 4 ++-- 8 files changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/admin/src/Charcoal/Admin/Action/Account/LostPasswordAction.php b/packages/admin/src/Charcoal/Admin/Action/Account/LostPasswordAction.php index 6ccedf528..5c119f703 100644 --- a/packages/admin/src/Charcoal/Admin/Action/Account/LostPasswordAction.php +++ b/packages/admin/src/Charcoal/Admin/Action/Account/LostPasswordAction.php @@ -65,7 +65,7 @@ public function run(RequestInterface $request, ResponseInterface $response) { $translator = $this->translator(); - $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null; + $ip = filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP) ?: null; $email = $request->getParam('email'); if (!$email) { @@ -267,7 +267,7 @@ private function sendLostPasswordEmail(User $user, LostPasswordToken $token) 'adminUrl' => $this->adminUrl(), 'urlResetPassword' => $this->adminUrl() . 'account/reset-password/' . $publicToken, 'expiry' => $token->expiry()->format('Y-m-d H:i:s'), - 'ipAddress' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '', + 'ipAddress' => filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP) ?: '', ], ]); $emailObj->send(); diff --git a/packages/admin/src/Charcoal/Admin/Action/Account/ResetPasswordAction.php b/packages/admin/src/Charcoal/Admin/Action/Account/ResetPasswordAction.php index 2c4af9e9b..881dab158 100644 --- a/packages/admin/src/Charcoal/Admin/Action/Account/ResetPasswordAction.php +++ b/packages/admin/src/Charcoal/Admin/Action/Account/ResetPasswordAction.php @@ -55,7 +55,7 @@ public function run(RequestInterface $request, ResponseInterface $response) { $translator = $this->translator(); - $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null; + $ip = filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP) ?: null; $token = $request->getParam('token'); $email = $request->getParam('email'); diff --git a/packages/admin/src/Charcoal/Admin/Action/LoginAction.php b/packages/admin/src/Charcoal/Admin/Action/LoginAction.php index c05cae0e3..1000b61aa 100644 --- a/packages/admin/src/Charcoal/Admin/Action/LoginAction.php +++ b/packages/admin/src/Charcoal/Admin/Action/LoginAction.php @@ -65,7 +65,7 @@ public function run(RequestInterface $request, ResponseInterface $response) '{{ errorMessage }}' => $failMessage ]); - $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null; + $ip = filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP) ?: null; $email = $request->getParam('email'); $password = $request->getParam('password'); diff --git a/packages/admin/src/Charcoal/Admin/Action/LogoutAction.php b/packages/admin/src/Charcoal/Admin/Action/LogoutAction.php index e521ed2b6..db8959bbe 100644 --- a/packages/admin/src/Charcoal/Admin/Action/LogoutAction.php +++ b/packages/admin/src/Charcoal/Admin/Action/LogoutAction.php @@ -62,7 +62,7 @@ public function run(RequestInterface $request, ResponseInterface $response) } /** Fail silently — Never confirm or deny the existence of an account. */ - $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null; + $ip = filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP) ?: null; if ($ip) { $logMessage = sprintf('[Admin] Logout attempt for unauthenticated user from %s', $ip); } else { diff --git a/packages/admin/src/Charcoal/Admin/AdminAction.php b/packages/admin/src/Charcoal/Admin/AdminAction.php index f3dd98eb2..8600bbc71 100644 --- a/packages/admin/src/Charcoal/Admin/AdminAction.php +++ b/packages/admin/src/Charcoal/Admin/AdminAction.php @@ -347,8 +347,9 @@ protected function validateCaptcha($token) 'response' => $token, ]; - if (isset($_SERVER['REMOTE_ADDR'])) { - $data['remoteip'] = $_SERVER['REMOTE_ADDR']; + $remoteIp = filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP); + if ($remoteIp !== false) { + $data['remoteip'] = $remoteIp; } $query = http_build_query($data); diff --git a/packages/admin/src/Charcoal/Admin/Template/Object/CreateTemplate.php b/packages/admin/src/Charcoal/Admin/Template/Object/CreateTemplate.php index b68c5d05e..6af82956e 100644 --- a/packages/admin/src/Charcoal/Admin/Template/Object/CreateTemplate.php +++ b/packages/admin/src/Charcoal/Admin/Template/Object/CreateTemplate.php @@ -113,10 +113,11 @@ public function title() ? $translator->translation($metadata['labels']['singular_name']) : null); - if (!empty($_GET['clone_id'])) { + $cloneId = Sanitizer::sanitizeGetParam('clone_id'); + if (!empty($cloneId)) { $title = sprintf( $translator->translation('Create: {{ objType }} from ID ""%s""'), - $_GET['clone_id'] + $cloneId ); } else { $title = $translator->translation('Create: {{ objType }}'); diff --git a/packages/object/src/Charcoal/Object/UserData.php b/packages/object/src/Charcoal/Object/UserData.php index 8c252233f..cfd8924ec 100644 --- a/packages/object/src/Charcoal/Object/UserData.php +++ b/packages/object/src/Charcoal/Object/UserData.php @@ -248,8 +248,9 @@ protected function preSave() $this->setTs('now'); - if (getenv('REMOTE_ADDR')) { - $this->setIp(getenv('REMOTE_ADDR')); + $remoteIp = filter_var(getenv('REMOTE_ADDR'), FILTER_VALIDATE_IP); + if ($remoteIp !== false) { + $this->setIp($remoteIp); } if (!isset($this->origin)) { diff --git a/packages/user/src/Charcoal/User/Authenticator.php b/packages/user/src/Charcoal/User/Authenticator.php index 455eecc73..4d7d9e2a7 100644 --- a/packages/user/src/Charcoal/User/Authenticator.php +++ b/packages/user/src/Charcoal/User/Authenticator.php @@ -79,7 +79,7 @@ public function touchUserLogin(AuthenticatableInterface $user, $update = true) } $user['lastLoginDate'] = 'now'; - $user['lastLoginIp'] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null; + $user['lastLoginIp'] = filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP) ?: null; if ($update && $userId) { $result = $user->update([ @@ -142,7 +142,7 @@ public function changeUserPassword(AuthenticatableInterface $user, $password, $u $user[$passwordKey] = password_hash($password, PASSWORD_DEFAULT); $user['lastPasswordDate'] = 'now'; - $user['lastPasswordIp'] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null; + $user['lastPasswordIp'] = filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP) ?: null; if ($update && $userId) { $result = $user->update([ From 4a47093a26365300b4474d3377560708f2918436 Mon Sep 17 00:00:00 2001 From: Mathieu Ducharme Date: Tue, 8 Sep 2026 09:33:36 -0400 Subject: [PATCH 3/3] Fix phpcs --- .../src/Charcoal/Admin/Action/Account/LostPasswordAction.php | 4 ++-- .../src/Charcoal/Admin/Action/Account/ResetPasswordAction.php | 2 +- packages/admin/src/Charcoal/Admin/Action/LoginAction.php | 2 +- packages/admin/src/Charcoal/Admin/Action/LogoutAction.php | 2 +- packages/admin/src/Charcoal/Admin/AdminAction.php | 2 +- packages/user/src/Charcoal/User/Authenticator.php | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/admin/src/Charcoal/Admin/Action/Account/LostPasswordAction.php b/packages/admin/src/Charcoal/Admin/Action/Account/LostPasswordAction.php index 5c119f703..0f0483267 100644 --- a/packages/admin/src/Charcoal/Admin/Action/Account/LostPasswordAction.php +++ b/packages/admin/src/Charcoal/Admin/Action/Account/LostPasswordAction.php @@ -65,7 +65,7 @@ public function run(RequestInterface $request, ResponseInterface $response) { $translator = $this->translator(); - $ip = filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP) ?: null; + $ip = filter_var(($_SERVER['REMOTE_ADDR'] ?? null), FILTER_VALIDATE_IP) ?: null; $email = $request->getParam('email'); if (!$email) { @@ -267,7 +267,7 @@ private function sendLostPasswordEmail(User $user, LostPasswordToken $token) 'adminUrl' => $this->adminUrl(), 'urlResetPassword' => $this->adminUrl() . 'account/reset-password/' . $publicToken, 'expiry' => $token->expiry()->format('Y-m-d H:i:s'), - 'ipAddress' => filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP) ?: '', + 'ipAddress' => filter_var(($_SERVER['REMOTE_ADDR'] ?? null), FILTER_VALIDATE_IP) ?: '', ], ]); $emailObj->send(); diff --git a/packages/admin/src/Charcoal/Admin/Action/Account/ResetPasswordAction.php b/packages/admin/src/Charcoal/Admin/Action/Account/ResetPasswordAction.php index 881dab158..4be42a360 100644 --- a/packages/admin/src/Charcoal/Admin/Action/Account/ResetPasswordAction.php +++ b/packages/admin/src/Charcoal/Admin/Action/Account/ResetPasswordAction.php @@ -55,7 +55,7 @@ public function run(RequestInterface $request, ResponseInterface $response) { $translator = $this->translator(); - $ip = filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP) ?: null; + $ip = filter_var(($_SERVER['REMOTE_ADDR'] ?? null), FILTER_VALIDATE_IP) ?: null; $token = $request->getParam('token'); $email = $request->getParam('email'); diff --git a/packages/admin/src/Charcoal/Admin/Action/LoginAction.php b/packages/admin/src/Charcoal/Admin/Action/LoginAction.php index 1000b61aa..3577f8f2a 100644 --- a/packages/admin/src/Charcoal/Admin/Action/LoginAction.php +++ b/packages/admin/src/Charcoal/Admin/Action/LoginAction.php @@ -65,7 +65,7 @@ public function run(RequestInterface $request, ResponseInterface $response) '{{ errorMessage }}' => $failMessage ]); - $ip = filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP) ?: null; + $ip = filter_var(($_SERVER['REMOTE_ADDR'] ?? null), FILTER_VALIDATE_IP) ?: null; $email = $request->getParam('email'); $password = $request->getParam('password'); diff --git a/packages/admin/src/Charcoal/Admin/Action/LogoutAction.php b/packages/admin/src/Charcoal/Admin/Action/LogoutAction.php index db8959bbe..51b722e62 100644 --- a/packages/admin/src/Charcoal/Admin/Action/LogoutAction.php +++ b/packages/admin/src/Charcoal/Admin/Action/LogoutAction.php @@ -62,7 +62,7 @@ public function run(RequestInterface $request, ResponseInterface $response) } /** Fail silently — Never confirm or deny the existence of an account. */ - $ip = filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP) ?: null; + $ip = filter_var(($_SERVER['REMOTE_ADDR'] ?? null), FILTER_VALIDATE_IP) ?: null; if ($ip) { $logMessage = sprintf('[Admin] Logout attempt for unauthenticated user from %s', $ip); } else { diff --git a/packages/admin/src/Charcoal/Admin/AdminAction.php b/packages/admin/src/Charcoal/Admin/AdminAction.php index 8600bbc71..a69eead7f 100644 --- a/packages/admin/src/Charcoal/Admin/AdminAction.php +++ b/packages/admin/src/Charcoal/Admin/AdminAction.php @@ -347,7 +347,7 @@ protected function validateCaptcha($token) 'response' => $token, ]; - $remoteIp = filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP); + $remoteIp = filter_var(($_SERVER['REMOTE_ADDR'] ?? null), FILTER_VALIDATE_IP); if ($remoteIp !== false) { $data['remoteip'] = $remoteIp; } diff --git a/packages/user/src/Charcoal/User/Authenticator.php b/packages/user/src/Charcoal/User/Authenticator.php index 4d7d9e2a7..0bfef7d83 100644 --- a/packages/user/src/Charcoal/User/Authenticator.php +++ b/packages/user/src/Charcoal/User/Authenticator.php @@ -79,7 +79,7 @@ public function touchUserLogin(AuthenticatableInterface $user, $update = true) } $user['lastLoginDate'] = 'now'; - $user['lastLoginIp'] = filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP) ?: null; + $user['lastLoginIp'] = filter_var(($_SERVER['REMOTE_ADDR'] ?? null), FILTER_VALIDATE_IP) ?: null; if ($update && $userId) { $result = $user->update([ @@ -142,7 +142,7 @@ public function changeUserPassword(AuthenticatableInterface $user, $password, $u $user[$passwordKey] = password_hash($password, PASSWORD_DEFAULT); $user['lastPasswordDate'] = 'now'; - $user['lastPasswordIp'] = filter_var($_SERVER['REMOTE_ADDR'] ?? null, FILTER_VALIDATE_IP) ?: null; + $user['lastPasswordIp'] = filter_var(($_SERVER['REMOTE_ADDR'] ?? null), FILTER_VALIDATE_IP) ?: null; if ($update && $userId) { $result = $user->update([