Skip to content

Conversation

@anomiex
Copy link

@anomiex anomiex commented Sep 4, 2023

WordPress relies on PHP's display_errors setting for error reporting. One unfortunate result of that is that errors containing HTML may be served to the browser unescaped.

WordPress/WordPress-Coding-Standards tries to help avoid this by having a sniff (WordPress.Security.EscapeOutput) that, among other things, asks that strings passed to trigger_error() and throw new SomeClass() be escaped. This is not a very good solution for a few reasons:

  • It doesn't do anything about errors or exceptions thrown by PHP itself.
  • It doesn't do anything about errors or exceptions thrown by libraries that might be bundled into themes or plugins or any custom code blog authors might inject.
  • It means that text-based log files, non-HTML emails, CLI output, and the like will contain HTML entities.

Instead we should follow the principle that values should be escaped close to the point of output, when we know what kind of escaping will be needed. Which, in the context of PHP, means using set_error_handler() and set_exception_handler() to handle the outputting.

But WordPress also relies on various other things that PHP's default handlers do, not all of which we can duplicate. But on the plus side since display_errors is not exactly a boolean (and PHP doesn't care anyway) we can have the handlers themselves set display_errors to a sentinel value that PHP will interpret as "off", do any necessary output, and then hand off to PHP's default handlers to do everything else.

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


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.

Copy link
Member

@dingo-d dingo-d left a comment

Choose a reason for hiding this comment

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

Left some minor comments regarding code readability mostly.

I think the new functions should be covered by unit tests.

@anomiex anomiex force-pushed the add/set_error_handler branch from 222db53 to 23ab66a Compare January 31, 2024 16:09
@github-actions
Copy link

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.

anomiex added 8 commits June 25, 2025 11:59
WordPress relies on PHP's `display_errors` setting for error reporting.
One unfortunate result of that is that errors containing HTML may be
served to the browser unescaped.

WordPress/WordPress-Coding-Standards tries to help avoid this by having
a sniff (WordPress.Security.EscapeOutput) that, among other things, asks
that strings passed to `trigger_error()` and `throw new SomeClass()` be
escaped. This is not a very good solution for a few reasons:

* It doesn't do anything about errors or exceptions thrown by PHP
  itself.
* It doesn't do anything about errors or exceptions thrown by libraries
  that might be bundled into themes or plugins or any custom code blog
  authors might inject.
* It means that text-based log files, non-HTML emails, CLI output, and
  the like will contain HTML entities.

Instead we should follow the principle that values should be escaped
close to the point of output, when we know what kind of escaping will be
needed. Which, in the context of PHP, means using `set_error_handler()`
and `set_exception_handler()` to handle the outputting.

But WordPress also relies on various other things that PHP's default
handlers do, not all of which we can duplicate. But on the plus side
since `display_errors` is not exactly a boolean (and PHP doesn't care
anyway) we can have the handlers themselves set `display_errors` to a
sentinel value that PHP will interpret as "off", do any necessary
output, and then hand off to PHP's default handlers to do everything
else.
And also don't bother replacing falsey values with "wp".
…config.

That also requires separating the "print" logic into a separate helper function.
This seems opposite to how we do anonymous functions, but 🤷.
@anomiex anomiex force-pushed the add/set_error_handler branch from e8bd4b5 to 21492b4 Compare June 25, 2025 16:02
@github-actions
Copy link

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.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @paulshryock.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

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

Props bjorsch, dingo_d.

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

@anomiex anomiex force-pushed the add/set_error_handler branch from 68d368d to faaf287 Compare June 25, 2025 16:42
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