Escaping Data

Escaping output is the process of securing output data by stripping out unwanted data, like malformed HTML or script tags. This process helps secure your data prior to rendering it for the end user. 

Note:
most WordPress functions properly prepare the data for output, and additional escaping is not needed.

Escaping Functions

WordPress has many helper functions you can use for most common scenarios.

Pay close attention to what each function does, as some will remove HTML while others will permit it. You must use the most appropriate function to the content and context of what you’re echoing. You always want to escape when you echo, not before.

  • esc_html() – Use anytime an HTML element encloses a section of data being displayed. This will remove HTML.
<h4><?php echo esc_html( $title ); ?></h4>
  • esc_js() – Use for inline Javascript.
<div onclick='<?php echo esc_js( $value ); ?>' />
  • esc_url() – Use on all URLs, including those in the src and href attributes of an HTML element.
<img alt="" src="<?php echo esc_url( $media_url ); ?>" />
  • esc_url_raw() – Use when storing a URL in the database or in other cases where non-encoded URLs are needed.
  • esc_xml() – Use to escape XML block.
  • esc_attr() – Use on everything else that’s printed into an HTML element’s attribute.
<ul class="<?php echo esc_attr( $stored_class ); ?>">
  • esc_textarea() – Use this to encode text for use inside a textarea element.
  • wp_kses() – Use to safely escape for all non-trusted HTML (post text, comment text, etc.). This preserves HTML.
  • wp_kses_post() – Alternative version of wp_kses()that automatically allows all HTML that is permitted in post content.
  • wp_kses_data() – Alternative version of wp_kses()that allows only the HTML permitted in post comments.

Top ↑

Custom Escaping Example

In the case that you need to escape your output in a specific way, the function wp_kses() (pronounced “kisses”) will come in handy.

This function makes sure that only the specified HTML elements, attributes, and attribute values will occur in your output, and normalizes HTML entities.

<?php
echo wp_kses_post( $partial_html );
echo wp_kses(
    $another_partial_html,
    array(
        'a'      => array(
            'href'  => array(),
            'title' => array(),
        ),
        'br'     => array(),
        'em'     => array(),
        'strong' => array(),
    )
); ?>

In this example, all tags other than <a><br><em>, and <strong> will be stripped out. Additionally, if an <a> tag is passed, the escaping ensures that only the href and the title are returned.

Top ↑

Always escape late

It is best to do the output escaping as late as possible, ideally as data is being outputted.

It is better to escape late for a few reasons:

  • Code reviews and deploys can happen faster because it can be deemed safe for output at a glance, rather than hunting through many lines of code to see where and if it was already escaped.
  • Something could inadvertently change the variable between when it was firstly cast and when it is outputted, introducing a potential vulnerability.
  • Late escaping makes it easier to do automatic code scanning, saving time and cutting down on review and deploy times.
  • Late escaping whenever possible makes the code more robust and future proof.
  • Escaping/casting on output removes any ambiguity and adds clarity (always develop for the maintainer).
// Okay, but not great.
$url = esc_url( $url );
$text = esc_html( $text );
echo '<a href="'. $url . '">' . $text . '</a>';

// Much better!
echo '<a href="'. esc_url( $url ) . '">' . esc_html( $text ) . '</a>';

Top ↑

… Except when you can’t

It is sometimes not practical to escape late. In a few rare circumstances output cannot be passed to wp_kses(), since by definition it would strip the scripts that are being generated.

In situations like this, always escape while creating the string and store the value in a variable that is a postfixed with _escaped_safe or _clean (e.g., $variable becomes $variable_escaped or $variable_safe).

If a function cannot output internally and escape late, then it must always return “safe” HTML. This allows echo my_custom_script_code(); to be done without needing the script tag to be passed through a version of wp_kses() that would allow such tags.

Top ↑

Escaping with Localization

Rather than using echo to output data, it’s common to use the WordPress localization functions, such as _e() or __().

These functions simply wrap a localization function inside an escaping function:

esc_html_e( 'Hello World', 'text_domain' );
// Same as
echo esc_html( __( 'Hello World', 'text_domain' ) );

These helper functions combine localization and escaping: