Should messages in WP_Error already be html escaped?

No, escaping should happen at the moment of output ( late escaping ) so that we know that it only occurs once. Double escaping can allow specially crafted output to break out.

By escaping, we’re talking about functions such as esc_html, wp_kses_post, esc_url, etc.

Sanitizing functions and validating functions are not the same, e.g. sanitize_textfield. Sanitising cleans data, validation tests data, escaping enforces a type of data.

Think of it like this for a triangle factory:

  • The validator tests the item is a triangle , and gives it a thumb up or down, it only observes. If it’s triangle shaped, yes! If not, no. Validators are a good way to reject input, and should happen on input.
  • The sanitizer cleans the item, removes things that don’t belong on a triangle on input. Other examples might be removing trailing spaces. If the item is meant to be a number it might strip out any letters and symbols. The end result is just a cleaner, easier to manage version of what went in.
  • The escaper enforces the triangle shape, it’s like a cookie cutter with an triangle shaped hole in a triangle factory. It doesn’t matter what goes in, a triangle is coming out, even if a square went in. Sure you might end up with a mangled broken thing that’s triangle shaped, but triangles are what we intended and triangles are what we’re getting

Double escaping is bad because if we then take our broken square that’s shaped like a triangle, flip it upside down, and run it through the cookie cutter a second time, we don’t get a triangle, we get a hexagon. We didn’t want hexagons!

We can sanitize and validate as many times as we want, but we should only escape once, and it should happen at the moment of output, if not as close as possible to it.


So since WP_Error does not output, and is not responsible for outputting, it should not perform any escaping internally, nor should its inputs be escaped. Validated/sanitized perhaps, but not escaped.

If we did escape on input, we would either have to double escape, or trust all WP_Error objects, which is a non-starter. All it would take is a single plugin developer forgetting to escape on input. It’s also a lot easier to escape in the one place that outputs, than to escape in the many places that input.

So instead, the code that receives and outputs the WP_Error object is where the escaping should be, that way we escape on output safe in the knowledge that no early escaping has occurred, no double escaping happens, whether it’s been escaped is not a problem we have to deal with, and the responsibility for escaping is clear and straight forward

As for how to safely output a WP_Error object, either esc_html or wp_kses_post will suffice. The latter will allow tags such as <strong> etc. Generally, putting anything more complex in an error object than what you’d put into a post is a bad idea, WP_Error objects are structured data already

Leave a Comment