How to Fix PHP Error Reporting to Avoid Information Leakage
Improper PHP error reporting is one of the most common ways that sensitive information—like file paths, database credentials, and server configuration—leaks to end‑users or bots. This article walks you through the best practices for configuring error reporting, both in php.ini and at runtime, so you can keep your application secure while still having the debugging information you need.
Why Default PHP Error Settings Are Dangerous
Out‑of‑the‑box PHP installations often enable display_errors = On and set error_reporting = E_ALL. While this is handy for local development, it can expose:
- Absolute file system paths (e.g.,
/var/www/html/config.php) - SQL queries with raw parameters
- Stack traces that reveal the structure of your codebase
- Server environment variables (including API keys in some cases)
When these details appear on a public page, attackers gain valuable clues for exploitation.
Step‑by‑Step: Secure PHP Error Reporting
1. Adjust php.ini for Production
Open the main php.ini file (location varies by OS) and set the following directives:
display_errors = Off ; Never show errors to users
log_errors = On ; Log them instead
error_log = /var/log/php_errors.log ; Choose a secure, write‑able location
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT ; Log everything except noisy notices
After saving, restart your web server (e.g., systemctl restart apache2 or service php-fpm restart).
2. Override Settings with .htaccess (Apache)
If you cannot edit php.ini directly, use an .htaccess file in the application root:
php_flag display_errors Off
php_flag log_errors On
php_value error_log /var/www/html/logs/php_errors.log
Make sure the log directory is outside the web root and not world‑writable.
3. Runtime Configuration for Specific Scripts
Sometimes you need more granular control. Use ini_set() at the top of a script that runs in a development environment:
<?php
if (getenv('APP_ENV') === 'development') {
ini_set('display_errors', 1);
ini_set('error_reporting', E_ALL);
} else {
ini_set('display_errors', 0);
ini_set('log_errors', 1);
}
?>
This pattern keeps production safe while still showing errors locally.
4. Implement a Custom Error Handler
A custom handler lets you filter or format errors before they are logged. Example:
<?php
function secureErrorHandler($severity, $message, $file, $line) {
// Ignore suppressed errors
if (error_reporting() === 0) {
return false;
}
$logEntry = sprintf(
"[%s] %s in %s on line %d",
date('Y-m-d H:i:s'),
$message,
$file,
$line
);
error_log($logEntry, 3, '/var/log/php_secure_errors.log');
// Optionally, display a generic message to the user
if (php_sapi_name() !== 'cli') {
http_response_code(500);
echo "An unexpected error occurred. Please try again later.";
}
return true; // Prevent PHP's internal handler
}
set_error_handler('secureErrorHandler');
?>
This approach ensures that no sensitive data ever reaches the browser.
Testing Your Configuration
After applying the changes, verify that errors are hidden from the UI but logged correctly:
- Create a test script that triggers a warning, e.g.,
strpos()with an array. - Visit the script in a browser. You should see the generic message or a blank page.
- Check the log file (
/var/log/php_errors.log) for the detailed entry.
Use tools like securityheaders.com or Shodan to scan for exposed error messages on public URLs.
Common Pitfalls & How to Avoid Them
Leaving display_errors On in Sub‑directories
Even if the root .htaccess disables display_errors, a child directory may contain its own .htaccess that re‑enables it. Audit all directories for conflicting directives.
Logging to a World‑Writable File
Make sure the log file permissions are 640 (owner read/write, group read, others none) and owned by the web‑server user.
Using error_reporting = E_ALL in Production
While logging everything is useful, consider filtering out E_NOTICE and E_DEPRECATED to reduce noise and avoid accidental exposure of internal variable names.
Conclusion
Properly configuring PHP error reporting is a simple yet powerful step to prevent information leakage. By turning off display_errors, routing all messages to a secure log, and optionally using a custom error handler, you protect both your users and your application from unwanted disclosure.
Remember to:
- Separate development and production environments.
- Keep logs outside the web root and restrict file permissions.
- Regularly audit server configurations for accidental overrides.
Implement these practices today and strengthen your PHP applications against one of the most common vectors for data exposure.