Make WordPress Core

Opened 4 months ago

Last modified 8 days ago

#64071 assigned defect (bug)

Site Health false positive: WP_DEBUG_LOG warning when debug.log is outside wp-content

Reported by: dannythedog's profile dannythedog Owned by: hbhalodia's profile hbhalodia
Milestone: 7.0 Priority: normal
Severity: normal Version:
Component: Site Health Keywords: has-patch has-unit-tests
Focuses: administration Cc:

Description (last modified by sabernhardt)

Site Health shows a security warning about WP_DEBUG_LOG being publicly accessible, even when the debug log file is stored outside the wp-content directory and is not publicly accessible.

Steps to Reproduce

  1. Configure WordPress with custom debug log location outside wp-content:
    define('WP_DEBUG', true);
    define('WP_DEBUG_LOG', '/var/www/logs/debug.log'); // Outside wp-content
    define('WP_DEBUG_DISPLAY', false);
    
  2. Ensure the /logs/ directory is not mapped as a public URL
  3. Verify the file is NOT accessible via HTTP (returns 404)
  4. Check Site Health (Tools → Site Health → Info)

Expected Behavior

Site Health should verify whether the debug log file is actually publicly accessible before showing the security warning.

Actual Behavior

Site Health shows:

"Your site is set to log errors to a potentially public file"
"The value, WP_DEBUG_LOG, has been added to this website's configuration file. This means any errors on the site will be written to a file which is potentially available to all users."

This is a false positive when the log file is stored outside wp-content or protected by server configuration.

Suggested Fix

Enhance the Site Health check to:

  1. Detect if WP_DEBUG_LOG points to a custom path outside wp-content
  2. Attempt to verify if the file is publicly accessible via HTTP
  3. Only show the warning if the file is actually in a public directory

Environment

WordPress Version: 6.8.3
Server: Docker (nginx + php-fpm)
Debug log location: /var/www/logs/debug.log (outside web root)
Public accessibility: Verified 404 via curl -I https://example.com/logs/debug.log

Additional Context

This affects Docker/containerized WordPress installations where logs are commonly stored in separate volumes outside the public web directory for security and log management purposes.

Attachments (2)

site-health-debug-log-outside-abspath.php (1.4 KB) - added by dennishall 5 weeks ago.
MU-Plugin that fixes the false positive WordPress Site Health > Status > Critical information whereas a debug log file that is outside the ABSPATH will not be reported as "potentially" publicly accessible.
site-health-debug-log-outside-abspath.2.php (1.4 KB) - added by dennishall 5 weeks ago.
MU-Plugin that fixes the false positive WordPress Site Health > Status > Critical information whereas a debug log file that is outside the ABSPATH will not be reported as "potentially" publicly accessible. This mu-plugin is only a patch and should work with ALL WP 6.0+ installations which "may include - but not tested with" WPMU sites.

Download all attachments as: .zip

Change History (17)

#1 @sabernhardt
4 months ago

  • Component changed from General to Site Health
  • Description modified (diff)

#2 follow-up: @westonruter
4 months ago

  • Type changed from enhancement to defect (bug)

Thanks for opening a ticket!

To be fair, the Site Health message does say the file is "potentially available to all users".

How would the test be able to reliably know whether the directory for where the logs are written to is mounted somewhere publicly or not?

#3 in reply to: ↑ 2 @dennishall
5 weeks ago

Replying to westonruter:

Thanks for opening a ticket!

To be fair, the Site Health message does say the file is "potentially available to all users".

How would the test be able to reliably know whether the directory for where the logs are written to is mounted somewhere publicly or not?

Why not just use the webroot path that WordPress is installed in?
I place ALL debug log files outside the webroot /var/www/ and the web roots are all at /var/www/domain.com (sudo foldername used).
If the " define('WEBROOT_PATH', $_SERVERDOCUMENT_ROOT? . '/'); " is present in wp-config.php, WordPress should be able to know the debug.log file is outside that path.
WordPress also has the ABSPATH WordPress constant available even if you don't use the WEBROOT_PATH.

Again, if the debug log is not located in or below that ABSPATH, why should WordPress even display "potentially available to all users" when it's outside the webroot?

I constantly have to let my customers know this is a WordPress bug in the Site Health > Recommended Improvements logic and to disregard it.

#4 @westonruter
5 weeks ago

  • Keywords needs-patch added; 2nd-opinion removed
  • Milestone changed from Awaiting Review to Future Release

@dennishall that makes sense to me. Do you want to work on a patch?

@dennishall
5 weeks ago

MU-Plugin that fixes the false positive WordPress Site Health > Status > Critical information whereas a debug log file that is outside the ABSPATH will not be reported as "potentially" publicly accessible.

@dennishall
5 weeks ago

MU-Plugin that fixes the false positive WordPress Site Health > Status > Critical information whereas a debug log file that is outside the ABSPATH will not be reported as "potentially" publicly accessible. This mu-plugin is only a patch and should work with ALL WP 6.0+ installations which "may include - but not tested with" WPMU sites.

#5 @dennishall
5 weeks ago

  • Resolution set to maybelater
  • Status changed from new to closed

I've uploaded an mu-plugin I created as a patch.
I won't have time to apply the patch to the WP core for a while.

#6 @knutsp
5 weeks ago

  • Keywords needs-patch removed
  • Resolution maybelater deleted
  • Status changed from closed to reopened

Somebody else may want to test the plugin and apply a pacth based on it.

#7 @westonruter
5 weeks ago

  • Severity changed from minor to normal
  • Version 6.8.3 deleted

#8 @westonruter
5 weeks ago

  • Keywords needs-patch added

This ticket was mentioned in PR #10684 on WordPress/wordpress-develop by @hbhalodia.


5 weeks ago
#9

  • Keywords has-patch added; needs-patch removed

Trac ticket: https://core.trac.wordpress.org/ticket/64071

## Screenshots

Publicly accessible Not Publicly Accessible
https://github.com/user-attachments/assets/4df2f0cd-3363-4809-b2a8-fec9280a90fe https://github.com/user-attachments/assets/c21be088-73d6-43cf-9457-a0595d4c6d93

@hbhalodia commented on PR #10684:


5 weeks ago
#10

Hi Team, Can you please help review and update the wordings if needed?

Thank You,

@hbhalodia commented on PR #10684:


5 weeks ago
#11

If we wanted to go the extra mile, there could be a loopback request to try to actually request the file over HTTP to see if it returns anything. This may not be helpful in the end, however, as the file may not be present if nothing has been written to the log yet. Just an idea.

Thanks @westonruter, I thought of an edge case as well, what if there is no any log file present, then realpath will return false, and since we are checking a condition out there related if both the paths are present and if that is public path, then only to consider it as the debugging log is present in public directory, else we can show what we are showing.

@westonruter commented on PR #10684:


5 weeks ago
#12

I thought of an edge case as well, what if there is no any log file present, then realpath will return false, and since we are checking a condition out there related if both the paths are present and if that is public path, then only to consider it as the debugging log is present in public directory, else we can show what we are showing.

Good point. Well, in that case you could always check to see if ini_get( 'error_log' ) === WP_CONTENT_DIR . '/debug.log' in case the realpath() returns false. This will catch the default case when someone uses the default when setting WP_DEBUG_LOG to true:

https://github.com/WordPress/wordpress-develop/blob/5a53b94e89ff4276dbb235434ce8bfc99335366e/src/wp-includes/load.php#L622-L623

If, however, they do something like:

define( 'WP_DEBUG_LOG`, ABSPATH . 'debug.log' );

Then checking WP_DEBUG_LOG could fail if no logs have been written yet. In that case, if realpath() returns false, then actually there isn't a need to check realpath() on the full error log. All we need to do is check the path to the _directory_ because that's not something which would be automatically created when a new error log entry is written. So I think this can be simplified by turning $debug_log_path = realpath( $debug_log_path ); into $debug_log_path = realpath( dirname( $debug_log_path ) ) . DIRECTORY_SEPARATOR;

#14 @westonruter
3 weeks ago

  • Keywords has-unit-tests added
  • Milestone changed from Future Release to 7.0
  • Owner set to hbhalodia
  • Status changed from reopened to assigned

@hbhalodia commented on PR #10684:


8 days ago
#15

Hi @westonruter, Firstly apologies for the delay here in addressing the feedbacks, I was caught up with some other tasks.

I do have addressed the feedbacks, Can you please re-review the PR for the same.

Thanks,

Note: See TracTickets for help on using tickets.