Redact Parameters in Back Traces in PHP 8.2

Redact Parameters in Back Traces in PHP 8.2

Stack traces in exceptions can be useful for testing and debugging purposes. The stack trace contains the function names and parameters for each stack frame. It allows seeing what data was passed to the function. However, this functionality can cause security issues. It can happen when sensitive values, such as credentials, are passed to the function.

Let's say we have a function that accepts a password parameter:

<?php

function encryptPassword(string $password): string {
    throw new Exception('Error');
}

encryptPassword('pwd123');

If a function was called and something goes wrong, then an exception can be thrown. In our case, password will be visible in the stack trace:

Fatal error: Uncaught Exception: Error in main.php:4
Stack trace:
#0 main.php(7): encryptPassword('pwd123')
#1 {main}
  thrown in main.php on line 4

Since PHP 8.2, the #[\SensitiveParameter] attribute can be used to mark which function parameters shouldn't be listed in the stack trace.

<?php

function encryptPassword(#[\SensitiveParameter] string $password): string {
    throw new Exception('Error');
}

encryptPassword('pwd123');

If a function was called, and it causes an exception, the parameter value passed to the function will be replaced with a SensitiveParameterValue object.

Fatal error: Uncaught Exception: Error in main.php:4
Stack trace:
#0 main.php(7): encryptPassword(Object(SensitiveParameterValue))
#1 {main}
  thrown in main.php on line 4

The #[\SensitiveParameter] attribute can also be used to mark sensitive parameters in class methods.

CryptoUtil.php

<?php

class CryptoUtil
{
    public static function encryptPassword(#[\SensitiveParameter] string $password): string
    {
        throw new Exception('Error');
    }
}

Note that PHP built-in functions (e.g. password_hash, password_verify) has sensitive parameters that already marked with the #[\SensitiveParameter] attribute.

<?php

password_hash('pwd123', 'unknown_algo');
Fatal error: Uncaught ValueError: password_hash(): Argument #2 ($algo) must be a valid password hashing algorithm in main.php:3
Stack trace:
#0 main.php(3): password_hash(Object(SensitiveParameterValue), 'unknown_algo')
#1 {main}
  thrown in main.php on line 3

Leave a Comment

Cancel reply

Your email address will not be published.