Why does PDO print my password when the connection fails?

We use encoded username and passwords, and decode those in the PDO constructor. Then we catch the PDOException and throw a new PDOException with the old exception its message, so that the trace will show only the encoded username and password.

A good encryption library for PHP is defuse/php-encryption.

Example code:

<?php
class myPDOWrapper extends PDO
    {

        public function __construct(string $dns, string $encodedUser, string $encodedPassword)
        {
            try {
                parent::__construct($dns, $this->decodeFunction($encodedUser), $this->decodeFunction($encodedPassword),
                    [
                        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    ]
                );
            }
            catch (PDOException $exception) {
                throw new PDOException($exception->getMessage());
            }
        }

        private function decodeFunction(string $encoded): string
        {
            return \Defuse\Crypto\Crypto::decrypt($encoded, $this->decodeKey());
        }

        private function decodeKey(): \Defuse\Crypto\Key
        {
            static $key = null;

            if(null === $key) {
                $key = \Defuse\Crypto\Key::loadFromAsciiSafeString(getenv('MY_PDO_DECODE_KEY'));
            }

            return $key;
        }
    }

You should have display_errors = off in your PHP.ini anyway to avoid this problem. Errors that reveal details like these come from many places, in addition to PDO.

Yes, you should also have it in a try/catch block.

You can also $pdo->setAttribute(PDO::ERRMODE_SILENT), but then you need to be checking the error codes manually rather than using a try/catch block. See http://php.net/manual/en/pdo.setattribute.php for more error constants.


A simple workaround is to catch the PDOException thrown by the PDO constructor:

try {
    $dbh  =  new PDO('mysql:host=localhost;dbname=DB;port=3306', 'USER',
    'SECRET', array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
} catch (PDOException $e) {
    throw new Exception($e->getMessage());
}

Ok, this made me giggle a little. The usage of error reporting is for debugging purposes, and it allows you to quickly find and fix issues.

When you're within a live environment your server should be configured for internal logging only, and not direct output, so basically you will need to turn off the output of errors within your php.ini.

display_errors = Off

But while you're within your test environment, this stack is merely a tool to help you and is configurable.

When errors occur within a live environment they would be logged, so you should always be checking your log files and then fix accordingly.

People may specify that you can manage errors within your PHP application, but by personal preference I think this is the wrong way to go about it. Configuring the INI and configuration files for your web-server and MySQL / SQL Server will result in more acute management.

If your application is a public application then it would also be a good idea to handle errors within the application as a large percentage of clients may be on shared hosting and not have full access to server configurations.