WordPress Output Escaping Guide

WordPress Output Escaping: esc_html(), esc_attr(), and esc_url()

A WordPress website can have dynamic content, like the post title, username, links, and custom fields, or form values. If this information is integrated into a page without proper escaping it can cause security issues, such as cross-site scripting (XSS).

There are different functions that WordPress has under its own banner which can help developers to display the dynamic data safely. The three main functions are esc_html(), esc_attr(), and esc_url().

While these functions do exactly the same thing, they have specific output context. This way, you can use the right function to retain the integrity of your website’s HTML and functionality.

Over this course, you are going to find out about those functions, when they’re utilized, the distinctions between them, and how to use them in real WordPress development.

What Is WordPress Output Escaping?

Output Escaping involves converting potentially unsafe characters into some safe representation for a specific context.

For instance, HTML depicts elements with extraordinary characterizations like < and >. These characters can make the browser believe that they are HTML and not ordinary text if they are part of dynamic content.

Consider this example:

$user_input = '<script>alert("Hello");</script>';

echo $user_input;

When directly printed into an HTML page, this information may appear as executable JavaScript to the Web browser.

The alternative is to use a safer way to get out of the output:

$user_input = '<script>alert("Hello");</script>';

echo esc_html( $user_input );

The browser now shows the script markup as text rather than HTML script.

Output escaping plays an important role in WordPress security, particularly with user-provided, database-provided, URL, or otherwise provided content.

Important: Escaping output is not input validation or sanitization. WordPress developers should check, sanitize and validate data collected if it is needed to be used, and escape the data in the place where it is displayed/used.

Esc_html() in WordPress is what?

The esc_html function escapes a string, so that it can be used safely within an HTML context.

It resolves special html characters to the html entities that can be printed as text instead as markups.

When Will You Use esc_html()?

Ensure that dynamic text is HTML-escaped before being used between HTML tags, such as:

  • Post titles
  • Usernames
  • Custom field values
  • Plain-text labels
  • Clear explanations with good structure and sub headings
  • Other text that shouldn’t have HTML in it.

Example of esc_html()

If you would like show up a WordPress title for the post:

$post_title = get_the_title();

echo '<h2>' . esc_html( $post_title ) . '</h2>';

The string “esc_html(get_the_title())” outputs the title of the post with the comes safe HTML function.

This will help to ensure that special characters in the title will not be interpreted as HTML.

Shows with untrusted text:

$message = '<b>Welcome to my website</b>';

echo '<p>' . esc_html( $message ) . '</p>';

The browser will print the following words:

<b>Welcome to my website</b>

Because esc_html() escapes the HTML tags, the text won’t be rendered in bold.

If you want to show plain text, this is the right thing to do.

In WordPress Templates, you can use “esc_html” for securing your text.

Alternatively, you could use esc_html() within a template:

<h1><?php echo esc_html( get_bloginfo( 'name' ) ); ?></h1>

Nicely put HTML heading around the site name.

Note: Only use esc_html() for any text you’re going to use within HTML tags, NOT ALL output.

2. What Is esc_attr() in WordPress?

The esc_attr() function escapes a string to use on HTML attributes.

HTML attributes contain more information about the element. Examples include the title, alt, class, value and data- attributes.

Special characters must be handled properly, however, when dynamic content is embedded inside an attribute they have to make sure that the value does not escape the attribute.

When to Use esc_attr()?

When output within attributes, like class, name, etc., of HTML elements, use esc_attr():

  • Input field values
  • Image alt text
  • Element titles
  • Custom data attributes
  • Values derived from the various settings or content in Databases

Example of esc_attr()

Suppose you would like to put a custom value in an HTML input field:

$display_name = get_option( 'display_name' );

echo '<input type="text" value="' . esc_attr( $display_name ) . '">';

The value is escaped by the function esc_attr prior to being placed in the ‘value’ attribute.

This makes it easier to prevent the alteration of the desired HTML attribute format by special characters.

Example With an Image Attribute

$image_alt = get_post_meta(
    get_the_ID(),
    'image_alt_text',
    true
);

echo '<img src="image.jpg" alt="' . esc_attr( $image_alt ) . '">';

In this case the dynamically-generated value for the alt attribute is also protected by the use of esc_attr().

However, when using a dynamic image URL, use esc_url() instead of esc_attr().

A better illustration of it is:

$image_url = get_template_directory_uri() . '/images/photo.jpg';

echo '<img src="' . esc_url( $image_url ) . '" alt="' . esc_attr( $image_alt ) . '">';

Here every function has its own context:

  • esc_url() escapes the URL for the image.
  • esc_attr() escapes the alternative text.

The reason why it is important to attribute escape.

Consider this example:

$custom_value = '" autofocus onfocus="alert(1)';

echo '<input value="' . $custom_value . '">';

The unescaped value can cause problems with the HTML attribute structure as well as add an event handler.

The use of esc_attr() ensures that the value is kept to its intended attribute:

$custom_value = '" autofocus onfocus="alert(1)';

echo '<input value="' . esc_attr( $custom_value ) . '">';

That’s why WordPress coders should need to escape dynamic attribute values rather than insert them in the HTML.

3. What Is esc_url() in WordPress?

The esc_url() function sanitises an URL to safely output it.

They are usually utilized on URLs for links, pictures, navigation menus, stylesheets and other HTML elements. But some characters or schemes in a URL may not be permitted in a specific output context.

The WordPress function, esc_url(), is an escaping function that removes disallowed and unsupported protocols based on WordPress’ policy.

What is the appropriate time to use esc_url()?

When displaying dynamic urls in html use: esc_url() for urls like:

  • Anchor links
  • Image sources
  • Navigation links
  • Theme asset URLs
  • External website links
  • URLs in href attributes of HTML anchor tags

Example of esc_url()

If you wish to use a URL from a WordPress option to build a link, let’s say:

$website_url = get_option( 'website_url' );

echo '<a href="' . esc_url( $website_url ) . '">Visit Website</a>';

The esc_url() hook sanitizes the URL that is placed in the href attribute.

This helps prevent to use of unsafe URL schemes as output.

Provides an example of dynamic image URL.

$image_url = get_template_directory_uri() . '/images/banner.jpg';

echo '<img src="' . esc_url( $image_url ) . '" alt="Website banner">';

The URL is escaped can be used inside the image’s src attribute.

Example With an Anchor Link

$profile_url = get_option( 'profile_url' );

echo '<a href="' . esc_url( $profile_url ) . '">View Profile</a>';

It is a widespread practice when developing WordPress themes, custom templates and plugin interfaces.

But, What About JavaScript URL’s?

Any URL that contains javascript should not be used as a normal website link, for example a URL likejavascript:alert(1) shouldn’t work as a site link.

Although, WordPress’s esc_url() filters prevent certain protocols from being output as a useable link, which helps prevent this type of URL from being output.

Nevertheless, the developers need to still assess URLs as per the application requirements and not depending on escaping as a full security check.

4) What is the difference between esc_html(), esc_attr() and esc_url()?

These three functions are utilized to guard WordPress output, but not interchangeable.

FunctionIntended contextCommon examples
esc_html()HTML text contentTitles, paragraphs, labels
esc_attr()HTML attribute valuesvalue, alt, title, data-
esc_url()URLs in HTML outputhref, src

Most critical guideline: if the data will be displayed in the cell, select the function that can be output there.

For instance if you have an <h2> element for a post title, the post title should be passed through esc_html(). An attribute value should use the same title as an attribute value, use esc_attr(). esc_url() should be passed a link destination.

Practical Comparison

$title = get_the_title();
$label = get_option( 'button_label' );
$link  = get_option( 'button_url' );

Escaping text:

echo '<h2>' . esc_html( $title ) . '</h2>';

Escaping an attribute:

echo '<button title="' . esc_attr( $label ) . '">Click</button>';

Escaping a URL:

echo '<a href="' . esc_url( $link ) . '">Read More</a>';

An example of each function for each output context are provided.

Now let’s see how to employ these functions in a WordPress style.

Let’s combine the three functions in a basic WordPress template.

If you desired to present a post title, a concise description and a link?

<?php
$title       = get_the_title();
$description = get_post_meta(
    get_the_ID(),
    'custom_description',
    true
);
$button_url  = get_permalink();
?>

<article>
    <h2><?php echo esc_html( $title ); ?></h2>

    <p><?php echo esc_html( $description ); ?></p>

    <a href="<?php echo esc_url( $button_url ); ?>">
        Read More
    </a>
</article>

This example uses:

esc_html() for post title.
The plain-text description can be done with esc_html ().
This means using esc_url() for the post permalink.

The functions are used when the data is printed, sticking to WordPress’ “escaped output as late as possible” principle.

Set out and explain an example using a Form Field.

If you build a form in a theme or plugin, you should escape values of these attributes dynamically as well.

<?php
$username = get_option( 'site_username', '' );
?>

<label for="username">Username</label>

<input
    type="text"
    id="username"
    name="username"
    value="<?php echo esc_attr( $username ); ?>"
>

The output of the function is the username that is stored but escaped to be used in the input’s value attribute.

If you are receiving data via the form, you still need to do the validation and sanitization work and should do this separately during the processing for such data.

6. Mistakes to not make.

Even advanced WordPress coders can get the escaping of the output wrong. Knowing about these common issues can guide you to program more securely.

Mistake 1: Using print Dynamic Data Without Escaping

Avoid this pattern:

echo get_the_title();

Prefer:

echo esc_html( get_the_title() );

When displaying title as HTML in simple text label, ‘esc_html()’ is a good option.

Mistake #2: Using esc_html() for urls

The following strategy should not be used:

echo '<a href="' . esc_html( $url ) . '">Visit</a>';

Use esc_url() instead:

echo '<a href="' . esc_url( $url ) . '">Visit</a>';

No, a URL requires handling at the URL level, not just the HTML text that’s going to be escaped.

Mistake 3: Putting esc_url() to All The Attributes

RT make sure that esc_url is not suitable for all values of attributes.

A button label, or input value for instance, is not a URL.

For each situation, use the appropriate function:

echo '<input value="' . esc_attr( $value ) . '">';

Mistake 4: Mistaking Escaping For Sanitization

The escape and sanitizing are for different reasons.

Outgoing data is sanitized by cleaning or applying a rule to it. Escaping is needed to make data safe for output in a specific context.

For instance, if saving a plain-text setting, then sanitize_text_field() may be used:

$clean_value = sanitize_text_field(
    wp_unslash( $_POST['site_name'] ?? '' )
);

You should also escape that value when later displaying it:

Yes, it is demonstrated in the example, but when handling production data, the necessary checks and verifications of nonce, authorisation and validations for the particular context need to be done as well.

Mistake 5: Getting Out of the Ditch too Soon

Don’t escape a value, then store the escaped value as the permanent data.

For instance, HTML entities might be saved in the database because some value might later be on a webpage; this may double escape a value and cause unwanted output.

Rather, store it as needed for the application and escape it later when it gets displayed.

Inappropriate use of esc_html() where HTML is purposefully used.

At times, a WordPress plugin or theme must showcase some restricted HTML code like making a bold sentence or maybe adding a link.

In that case, esc_html() will simply echo the markup; it won’t render it.

If HTML is intentional, heed to wp_kses() or some WordPress special HTML allowing function. Limit the elements and features that the application requires.

Other Useful WordPress Escaping Functions – Some other useful escaping functions for WordPress.

There are more escaping functions in WordPress that go beyond just escaping HTML text, attributes, and URLs.

There are a number of helpful ones to know.

esc_textarea()

For dynamic content in a <textarea>.

echo '<textarea>';
echo esc_textarea( $message );
echo '</textarea>';

esc_js()

When working with output to a JavaScript environment where WordPress’s JavaScript escaping would be desirable, use this function. Don’t always pass untrusted data into code that can be executed – JavaScript contexts may be complex.

wp_kses()

Use this function when you want to accept a defined set of HTML elements/attributes and strip away other html that is not acceptable.

$allowed_html = array(
    'strong' => array(),
    'em'     => array(),
);

echo wp_kses( $content, $allowed_html );

This example allows for opening in <strong> and <em> tags, but disallows using random HTML attributes.

esc_html_e()

Control function that provides options to escape and directly display a translatable string.

esc_html_e( 'Welcome to our website', 'my-theme' );

esc_attr_e()

Use this function to escape and print to screen a string for translation as a string value of some HTML attribute.

esc_attr_e( 'Enter your name', 'my-theme' );

These functions can be helpful if you are creating a theme or plugin that requires an awareness of the type of output to provide.

WordPress Output Escaping Best Practices

Here are some simple tips when creating WordPress themes and plugins:

  • Move to dynamics-out as late as possible.
  • Esc_html() should be used for plain text within HTML elements.
    For dynamically rendered HTML attribute values use esc_attr().
    Use esc_url() for HTML displayed URLs.
  • To generate dynamic content in textual areas, use esc_textarea().
  • When you want to include a purposefully-restricted set of HTML elements, use wp_kses().
  • Filter, clean, and validate data for a particular purpose.
    In your own database, don’t assume that the data you pull up is safe.
    Don’t handcraft quote escapes when a good WordPress function is available.
    Output escaping is not authentication, authorization, nonce verification or any other kind of security.

These are some of the steps that can be taken to make WordPress code easier to maintain and mitigate common output related security risks.

Conclusion

You should know how to output escape a word press as a developer working with dynamic content.

esc_html(), esc_attr(), and esc_url() are used for different purposes: escaping output, escaping HTML attribute values, and escaping URLs for output.

Selecting the suitable function in the suitable situation enables you to prevent typical cross-site scripting vulnerabilities and maintain your website’s HTML structure.

For WordPress theme, plugin, and custom template creators, it should become a habit to escape output. When used with the correct sanitization and validation (and other security measures), it allows you to create safer and more reliable WordPress sites.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *