PHP code example of lychee-org / phpstan-sensitive-parameter-values

1. Go to this page and download the library: Download lychee-org/phpstan-sensitive-parameter-values library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

lychee-org / phpstan-sensitive-parameter-values example snippets


function example(string $password): void {
    $sensitive = new \SensitiveParameterValue($password);

    // PHPStan now sees $sensitive as SensitiveParameterValue<string>
    // and infers the return type of getValue() as string, not mixed.
    $plain = $sensitive->getValue();
}

foreach ($exception->getTrace() as $frame) {
    foreach ($frame['args'] ?? [] as $arg) {
        if ($arg instanceof \SensitiveParameterValue) {
            // getValue() keeps the original argument's type.
            $original = $arg->getValue();
        }
    }
}

class AuthService {
    // $password is marked sensitive here...
    public function authenticate(#[\SensitiveParameter] string $password): bool {
        // ...but login()'s parameter isn't, so the value is unprotected
        // as soon as it enters login()'s stack frame.
        return $this->login($password);
    }

    public function login(string $password): bool {
        // ...
    }
}

function hashPassword(#[\SensitiveParameter] string $password): string
{
    return password_hash($password, PASSWORD_BCRYPT); // ✅ not flagged
}

class AuthService
{
    public function store(#[\SensitiveParameter] string $password): void
    {
        $hash = Hash::make($password); // ✅ not flagged (Laravel)
    }
}

class Credentials {
    private string $password; // ❌ raw storage

    public function __construct(#[\SensitiveParameter] string $password) {
        $this->password = $password; // flagged: sensitiveParameter.unwrappedStorage
    }
}

class Credentials {
    private \SensitiveParameterValue $password; // ✅ wrapped storage

    public function __construct(#[\SensitiveParameter] string $password) {
        $this->password = new \SensitiveParameterValue($password);
    }
}

class Credentials {
    public function __construct(
        // flagged: sensitiveParameter.unwrappedPromotion
        #[\SensitiveParameter] private readonly string $password,
    ) {}
}

class Credentials {
    private string $password;

    public function __construct(\SensitiveParameterValue $password) {
        // flagged: sensitiveParameter.unwrappedGetValue
        $this->password = $password->getValue();
    }
}

function login(string $username, string $password) {
    // Parameter $password should use #[\SensitiveParameter]
}

class AuthService {
    public function setCredentials(string $apikey, string $secret) {
        // Both $apikey and $secret should be marked sensitive
    }
}

// Function-level protection
#[\SensitiveParameter]
function login(string $username, string $password) {
    // All parameters are protected
}

// Parameter-level protection
function authenticate(
    string $username,
    #[\SensitiveParameter] string $password
) {
    // Only $password is protected
}

// Mixed protection
class AuthService {
    public function verify(
        #[\SensitiveParameter] string $token,
        string $userId,
        string $apikey  // This will still trigger a warning
    ) {
        // $token is protected, $apikey needs protection
    }
}

// @phpstan-ignore-next-line sensitiveParameter.missing
function legacyFunction(string $password) {
    // Legacy code that cannot be updated
}

// @phpstan-ignore-next-line sensitiveParameter.missing
function anotherLegacyFunction(string $secret) {
    // Another legacy function
}

function modernFunction(string $password): void // @phpstan-ignore-line sensitiveParameter.missing
{
    // Function with inline ignore comment
}

// @phpstan-ignore-next-line sensitiveParameter.missing
public function __construct(
    private readonly SomeService $serviceWithSensitiveKeywordInName
) {}