Skip to content

Conversation

@hbhalodia
Copy link

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

Screenshots

Publicly accessible Not Publicly Accessible
Screenshot 2026-01-06 at 11 41 28 AM Screenshot 2026-01-06 at 11 42 39 AM

This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

@github-actions
Copy link

github-actions bot commented Jan 6, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props hbhalodia, westonruter, mukesh27.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@hbhalodia
Copy link
Author

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

Thank You,

@github-actions
Copy link

github-actions bot commented Jan 6, 2026

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • The Plugin and Theme Directories cannot be accessed within Playground.
  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@hbhalodia hbhalodia requested a review from westonruter January 8, 2026 06:49
Copy link
Member

@westonruter westonruter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@hbhalodia
Copy link
Author

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.

@hbhalodia hbhalodia requested a review from westonruter January 8, 2026 07:39
@westonruter
Copy link
Member

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:

if ( in_array( strtolower( (string) WP_DEBUG_LOG ), array( 'true', '1' ), true ) ) {
$log_path = WP_CONTENT_DIR . '/debug.log';

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;

@hbhalodia hbhalodia requested a review from westonruter January 9, 2026 05:15
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a false positive in WordPress Site Health where a warning about WP_DEBUG_LOG being set to a potentially public file is shown even when the debug log is configured to be outside the wp-content directory (and thus not publicly accessible).

Changes:

  • Modified the debug mode check to determine if error log files are within or outside the WordPress document root
  • Added different status levels (critical vs good) and messages based on whether the log file is publicly accessible
  • Differentiated messaging between WP_DEBUG_LOG constant usage and direct PHP error_log configuration

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if ( ! empty( ini_get( 'error_log' ) ) ) {
$debug_log_path = realpath( dirname( ini_get( 'error_log' ) ) ) . DIRECTORY_SEPARATOR;
$absolute_path = realpath( ABSPATH ) . DIRECTORY_SEPARATOR;
$is_public_log = $debug_log_path && $absolute_path && str_starts_with( $debug_log_path, $absolute_path );
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable name $is_public_log is misleading when it's false. A value of false could mean either "the log is not public" (which is good) or "we couldn't determine the path" (which is an error). Consider renaming or restructuring to make the distinction clearer, or handle the error case explicitly.

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented as below,

$log_path_status = 'private';

if ( false === $debug_log_path ) {
	$log_path_status = 'error';
} elseif ( str_starts_with( $debug_log_path . DIRECTORY_SEPARATOR, $absolute_path ) ) {
	$log_path_status = 'public';
}

$is_wp_debug_log = defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG;

if ( $log_path_status === 'public' ) {
	$result['label']  = __( 'Your site is set to log errors to a potentially public file' );
	$result['status'] = 'critical';
} elseif ( $log_path_status === 'private' ) {
	$result['label']  = __( 'Your site is set to log errors to a file outside the document root' );
	$result['status'] = 'good';
} else {
	$result['label']  = __( 'Unable to determine error log file location' );
	$result['status'] = 'critical';
}

Update the $result['description'] based on the $log_path_status as below,

if ( $is_wp_debug_log ) {
	$result['description'] .= sprintf(
		'<p>%s</p>',
		sprintf(
			/* translators: %s: WP_DEBUG_LOG */
			$log_path_status === 'public'
				? __( 'The constant, %s, has been added to this website&#8217;s configuration file. This means any errors on the site will be written to a file which is likely publicly accessible.' )
				: ( $log_path_status === 'private'
					? __( 'The configuration constant, %s, is enabled. In addition, your site is set to write errors to a file outside the WordPress directory, which is a good practice as the log file should not be publicly accessible.' )
					: __( 'The configuration constant, %s, is enabled, but the log file location could not be determined.' )
				),
			'<code>WP_DEBUG_LOG</code>'
		)
	);
} else {
	$result['description'] .= sprintf(
		'<p>%s</p>',
		$log_path_status === 'public'
			? __( 'The error log path has been configured to a file within your WordPress directory. This means any errors on the site will be written to a file which is likely publicly accessible.' )
			: ( $log_path_status === 'private'
				? __( 'The error log path has been configured to a file outside your WordPress directory. This is a good practice as the log file should not be publicly accessible.' )
				: __( 'The error log path could not be determined. Please check your PHP configuration.' )
			)
	);
}

Copy link
Member

@westonruter westonruter Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hbhalodia Could the setting of the $result['description'] be moved up to the existing if/elseif/else for $log_path_status? This would ensure there is only one set of conditions, and it would address the nested ternary feedback from Copilot in #10684 (comment)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure would update it.

Copy link
Author

@hbhalodia hbhalodia Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now moved to if/elseif/else condition. But we have to check for $is_wp_debug_log constant being set or not. So it would be something like below,

if ( 'public' === $log_path_status ) {
	$result['label']  = __( 'Your site is set to log errors to a potentially public file' );
	$result['status'] = 'critical';

	if ( $is_wp_debug_log ) {
		$result['description'] .= sprintf(
			'<p>%s</p>',
			sprintf(
				/* translators: %s: WP_DEBUG_LOG */
				__( 'The constant, %s, has been added to this website&#8217;s configuration file. This means any errors on the site will be written to a file which is likely publicly accessible.' ),
				'<code>WP_DEBUG_LOG</code>'
			)
		);
	} else {
		$result['description'] .= sprintf(
			'<p>%s</p>',
			__( 'The error log path has been configured to a file within the WordPress directory. This means any errors on the site will be written to a file which is likely publicly accessible.' )
		);
	}
} elseif ( 'private' === $log_path_status ) {
	$result['label']  = __( 'Your site is set to log errors to a file outside the document root' );
	$result['status'] = 'good';

	if ( $is_wp_debug_log ) {
		$result['description'] .= sprintf(
			'<p>%s</p>',
			sprintf(
				/* translators: %s: WP_DEBUG_LOG */
				__( 'The configuration constant, %s, is enabled. In addition, your site is set to write errors to a file outside the WordPress directory, which is a good practice as the log file should not be publicly accessible.' ),
				'<code>WP_DEBUG_LOG</code>'
			)
		);
	} else {
		$result['description'] .= sprintf(
			'<p>%s</p>',
			__( 'The error log path has been configured to a file outside the WordPress directory. This is a good practice as the log file should not be publicly accessible.' )
		);
	}
} else {
	$result['label']  = __( 'Unable to determine error log file location' );
	$result['status'] = 'critical';

	if ( $is_wp_debug_log ) {
		$result['description'] .= sprintf(
			'<p>%s</p>',
			sprintf(
				/* translators: %s: WP_DEBUG_LOG */
				__( 'The configuration constant, %s, is enabled, but the log file location could not be determined.' ),
				'<code>WP_DEBUG_LOG</code>'
			)
		);
	} else {
		$result['description'] .= sprintf(
			'<p>%s</p>',
			__( 'The error log path could not be determined. Please check your PHP configuration.' )
		);
	}
}

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants