Skip to content

Escaping a WP_Error object

Denis Žoljom edited this page Aug 20, 2023 · 7 revisions

Say you have some code like this:

if ( is_wp_error( $foo ) ) {
    wp_die( $foo );
}

WordPressCS will give you an error like:

Expected next thing to be an escaping function, not $foo.

If you are absolutely sure that all of the data in the WP_Error object is escaped, you can use the phpcs:ignore comment, so that WordPressCS will ignore it, like this:

wp_die( $foo ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $foo is escaped before being passed in.

However, usually, you'll want to actually escape the WP_Error object instead of ignoring this issue. Unfortunately, WordPress doesn't include any functions for escaping a WP_Error objects. So you'd have to create your own custom function, like this:

/**
 * Escape a WP_Error object for passing directly to wp_die().
 *
 * The wp_die() function accepts an WP_Error object as the first parameter, but it
 * does not escape its contents before printing it out to the user. By passing
 * the object through this function before giving it to wp_die(), the potential for
 * XSS should be avoided.
 *
 * Example:
 *
 * wp_die( my_prefix_escape_wp_error( $error ) );
 *
 * @param WP_Error $error The error to escape.
 *
 * @return WP_Error The escaped error.
 */
function my_prefix_escape_wp_error( $error ) {

	$code = $error->get_error_code();

	$error_data = $error->error_data;

	if ( isset( $error_data[ $code ]['title'] ) ) {
		$error_data[ $code ]['title'] = wp_kses(
			$error->error_data[ $code ]['title']
			, 'escape_wp_error_title'
		);
		$error->error_data = $error_data;
	}

	$all_errors = $error->errors;

	foreach ( $all_errors as $code => $errors ) {
		foreach ( $errors as $key => $message ) {
			$all_errors[ $code ][ $key ] = wp_kses(
				$message
				, 'escape_wp_error_message'
			);
		}
	}

	$error->errors = $all_errors;
	return $error;
}

Then you could escape the WP_Error object like this:

    wp_die( my_prefix_escape_wp_error( $foo ) );

Of course, WordPressCS won't recognize this as an escaping function unless you modify your custom PHPCS ruleset like so:

	<rule ref="WordPress.Security.EscapeOutput">
		<properties>
			<property name="customEscapingFunctions" type="array">
				<element value="my_prefix_escape_wp_error"/>
			</property>
		</properties>
	</rule>