Current situation: PHP2Shell. Two critical PHP vulnerabilities (CVSS 9.2) allow malicious code without login. Patches since 21 October 2026.What to do now →

Logging Securely: Recording Errors Without a Data Leak

Logs help with troubleshooting and forensics but quickly become a data leak themselves. What PHP applications should log, what never, and how to protect logs.

Last updated 6 min readSecure development

In short: Logging in PHP with data protection in mind means recording security-relevant events completely but never writing passwords, tokens, session identifiers and sensitive customer data into the log. Errors belong in the log, not on the screen; logs are kept outside the web root and protected against modification. How long logs are kept, you decide deliberately together with the data protection officer.

Between Preserving Evidence and a Data Leak

After PHP2Shell, trade media advised keeping web server logs from 20 October 2026 onward. Anyone who wanted to do this often found two things. Either the logs had long since been rotated and deleted. Or they contained things that should never have been there: complete form inputs, passwords from failed logins, API keys in URLs.

Both are a problem. Without logs, an incident can hardly be reconstructed. With too much content, the log itself becomes a target, because anyone who gains access to the server gladly reads it too. Good logging lies in between: enough for tracing, as little protected data as possible.

What a PHP Application Should Log

The OWASP Logging Cheat Sheet names events that count for security and traceability. For typical PHP applications, they can be summarized as follows:

In the log Not in the log
successful and failed logins passwords, even mistyped ones
failed authorization checks session identifiers in plain text
changes to accounts and rights access tokens and API keys
input validation errors database credentials
uploads, imports and exports payment and bank data
configuration changes, start and stop health data and other particularly sensitive data
runtime errors with location, without payload data complete form contents

Every entry should answer the questions when, where, who and what: timestamp, application and host, source address, user identifier, type of event and result. Names or email addresses can often be masked or replaced by an internal identifier without losing usefulness.

Two sources of unwanted data in the log are often overlooked. The first are URLs: if a token, a password reset key or an email address is in the query string, it ends up automatically in the web server's access log, in proxy logs and in the browser history. Such values belong in the request body or a header, not in the address. The second source is debug mode. In debug operation, frameworks and plugins often log complete requests, database queries and environment variables. If this mode stays active after troubleshooting, a file grows unnoticed with exactly the information an attacker is looking for. After every troubleshooting session, check whether debug output has been switched off again, and delete the files created in the process.

Logging in PHP: The Basic Settings

The first level is PHP itself. In production, errors should be logged but not displayed. The log sits outside the web root so that it cannot be retrieved via a URL.

; php.ini or FPM pool for production
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/app-error.log

Why visible errors are dangerous is described in Switching Off Error Output in Production. How errors and exceptions in PHP relate is explained in Errors and Exceptions in PHP.

The second level is the application. Many frameworks use a library following the PHP-FIG's PSR-3 standard, which defines a uniform logger interface. What matters is not the library but the discipline: choose context data deliberately instead of writing entire requests or objects into the log.

<?php
// Neutralize and mask input before logging
function logSicher(string $text): string {
    return mb_substr(str_replace(["\r", "\n"], ' ', $text), 0, 200);
}

function maskiereMail(string $mail): string {
    [$name, $domain] = array_pad(explode('@', $mail, 2), 2, '');
    return mb_substr($name, 0, 1) . '***@' . $domain;
}

$logger->warning('Anmeldung fehlgeschlagen', [
    'benutzer' => maskiereMail(logSicher($_POST['email'] ?? '')),
    'ip'       => $_SERVER['REMOTE_ADDR'] ?? '',
    // never: 'passwort' => $_POST['passwort']
]);

Log Injection and Manipulated Entries

If an application writes input unfiltered into the log, an attacker can use line breaks to create forged entries. That confuses the evaluation and can cover tracks. The OWASP cheat sheet recommends structured formats such as JSON, removing or encoding line breaks, and a length limit for input in the log.

Equally important is protecting the logs themselves:

  1. Storage outside the web root and with rights that the web server user needs to write but not to delete old files.
  2. Copy to a second system, for example via syslog over an encrypted connection. Whoever takes over the server should not be able to simply delete the traces.
  3. Restrict read access and log it yourself. Logs almost always contain personal data.
  4. Detect failure: If the log suddenly stays empty, that is a warning sign.
  5. Synchronize the time: All servers get the time from the same source and write an unambiguous time zone into the log. Otherwise, entries from web server, PHP and database can hardly be put together into a timeline after an incident.
Important

A log that exists only on the compromised server is weak as evidence. A running copy on a separate system is often the only reliable source after an incident.

Deciding Retention and Data Protection Deliberately

How long logs may and must be kept is a balance between security interest, data minimization and legal or contractual requirements. Art. 32 GDPR requires technical and organizational measures appropriate to the risk, among other things to ensure the confidentiality, integrity and availability of systems on an ongoing basis; logging can contribute to this. At the same time, personal data must not be stored longer than necessary.

Therefore set a retention period per type of log, write down the justification and agree on both with your data protection officer. For an ongoing investigation, it may be necessary to preserve logs beyond the normal period. That too should then be documented. This page is general information and not legal advice; for specific questions, data protection officers and lawyers can help. How to evaluate logs after an attack is shown in Analyzing Web Server Logs After an Attack.

How does PHP SOS help?

  • We check your existing logs for passwords, tokens and other data that do not belong there.
  • We configure PHP and the application so that errors are logged but not displayed.
  • We set up a protected copy of the logs on a separate system.
  • Through security monitoring, we continuously evaluate security-relevant entries and report anything unusual in an understandable way.

Conclusion: Good logs are frugal with content and generous with protection. Anyone who decides today what is logged and what never is will have usable traces in an emergency and no additional data leak.

Frequently asked questions

May IP addresses appear in log files?

IP addresses can be personal data. Whether and for how long you store them depends on purpose and legal basis. Clarify scope and retention with your data protection officer; this page is not legal advice.

How long should logs be kept?

As long as is necessary and legally permissible for security and troubleshooting, and no longer. After PHP2Shell, the trade press recommended keeping web server logs from 20 October 2026 onward. Set retention periods deliberately and document them.

What is log injection?

If an input contains line breaks or control characters and is written unfiltered into the log, it can create forged entries. That falsifies evaluations. Structured formats such as JSON and removing line breaks prevent this.

Should display_errors be off in production?

Yes. Errors belong in the log, not in the output to visitors. Visible error messages reveal paths, queries and sometimes credentials.

Sources

Immediate contact

Every hour counts. Write to us now.

Briefly describe your system, PHP version and observation. We will get back to you, clarify the situation and work remotely until the incident is closed and documented.

Immediate help