Skip to content

Implement PHP 8.2 SensitiveParameter to redact sensitive/password data in backtraces. #38142

Open
@convenient

Description

@convenient

Summary

Currently if an exception is thrown while handling a sensitive parameter, part of that parameter is exposed in a stack trace.

We could enable zend.exception_ignore_args to turn off all the arguments from the traces, but that would affect the ability to support the sites and debug issues as we'd have no data.

As of PHP 8.2 there is support to provide annotations to function parameters to ensure they're excluded from back traces for this exact purpose.

It looks like

function test(
    $foo,
    #[\SensitiveParameter] $bar,
    $baz
) {

And would prevent the contents of $bar being exposed in any traces

Examples

For example it looks like this at a basic level

<?php
class Example
{
    public function login($username, $password)
    {
        throw new \Exception('something unexpected happened');
    }
}

(new Example)->login('SomeCoolUsername', 'SomeCoolerPassword12345');
PHP Fatal error:  Uncaught Exception: something unexpected happened in /Users/lukerodgers/src/example.php:6
Stack trace:
#0 /Users/lukerodgers/src/example.php(10): Example->login('SomeCoolUsernam...', 'SomeCoolerPassw...')
#1 {main}
  thrown in /Users/lukerodgers/src/example.php on line 6

See the the log contains SomeCoolerPassw which is not my full example password, but it is a lot.

The extensible nature of Magento means this kind of thing can happen in many core places

For example inside performIdentityCheck if someone had hooked into the observer admin_user_authenticate_after with some flaky logic that could trigger an exception, it could cause this function to fail like in the above demo.

This would result in part of the password being exposed in the logs

public function performIdentityCheck($passwordString)
{
try {
$isCheckSuccessful = $this->verifyIdentity($passwordString);
} catch (\Magento\Framework\Exception\AuthenticationException $e) {
$isCheckSuccessful = false;
}
$this->_eventManager->dispatch(
'admin_user_authenticate_after',
[
'username' => $this->getUserName(),
'password' => $passwordString,
'user' => $this,
'result' => $isCheckSuccessful
]
);
// Check if lock information has been updated in observers
$clonedUser = clone($this);
$clonedUser->reload();
if ($clonedUser->getLockExpires()) {
throw new \Magento\Framework\Exception\State\UserLockedException(
__('Your account is temporarily disabled. Please try again later.')
);
}
if (!$isCheckSuccessful) {
throw new \Magento\Framework\Exception\AuthenticationException(
__('The password entered for the current user is invalid. Verify the password and try again.')
);
}
return $this;
}

Proposed solution

When it becomes time to drop PHP 8.1 support add #[\SensitiveParameter] to all password / token fields in the codebase.

Release note

No response

Triage and priority

  • Severity: S0 - Affects critical data or functionality and leaves users without workaround.
  • Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
  • Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
  • Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
  • Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

Status

In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions