3

Should the value of functions such as the_permalink() be escaped before outputting to the browser? For example, do I need to escape the following?

<a href="<?php the_permalink(); ?>">Link text</a>

I'm aware I should escape user-submitted data etc but is it safe to assume WordPress has escaped data in core functions such as this already?

The solution could be this:

<a href="<?php echo esc_attr( get_permalink() ); ?>">Link text</a>

But why should I do that if WordPress has already escaped the data upstream?

1 Answer 1

4

The WordPress Codex says:

It's important to note that most WordPress functions properly prepare the data for output, and you don't need to escape again.

For example the_permalink() already escapes the output with:

echo esc_url( apply_filters( 'the_permalink', get_permalink( $post ), $post ) );

so you don't need to do that yourself here. But the get_the_permalink() function doesn't:

return get_permalink( $post, $leavename );

Neither does the get_permalink() function:

return apply_filters( 'post_link', $permalink, $post, $leavename );

They are not specific display functions.

WordPress uses filters all around the code base, to make it possible for themes and plugins to adjust the output of various core functions. Here are some possible (edge case) examples:

add_filter( 'post_link', function( $link )
{
    return get_option( 'some_url' );
}, PHP_INT_MAX );

or even:

add_filter( 'post_link', function( $link )
{
    return get_post_meta( 1, 'some_url', true );
}, PHP_INT_MAX );

So if we are displaying the output of get_permalink() directly, we should escape it with e.g.

<a href="<?php echo esc_url( get_permalink() );?>">...</a>

But in general I think it would be better to escape the output of a core function if we don't know how it handles it, but it shouldn't be too much work to just check it out.

5
  • Thanks for another great answer, birgire. I've noticed some WordPress functions return HTML (get_the_archive_description() is an example). I'm wondering if we just need to trust WordPress in these cases because escaping the return value will result in HTML tags displaying on screen? Commented Jun 27, 2016 at 10:37
  • It looks like the_archive_description() isn't escaping the output explicitly and it's even possible to adjust it via the get_the_archive_description filter. Tthe description is sanitized during insert/update, but we can e.g. add some HTML with missing closing tags in the term editor. Plugins/themes could also add what ever HTML (edge case) they fancy. So here I would feel more comfortable to e.g. strip the output of HTML tags myself. @henrywright
    – birgire
    Commented Jun 27, 2016 at 10:58
  • 1
    Right! I think that calls for something like wp_filter_nohtml_kses() and it highlights how we should trust nothing :) Commented Jun 27, 2016 at 11:01
  • The problem then of course is we lose all of the HTML formatting added by the user in places such as WP Admin > Post > Categories Commented Jun 27, 2016 at 11:09
  • 1
    yes the case of allowed HTML is in general difficult and even the esc_url(), esc_html() and esc_attr() can be modified via filters ;-) @henrywright
    – birgire
    Commented Jun 27, 2016 at 12:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.